From: Valentin Bartenev Date: Thu, 11 Jul 2019 13:10:33 +0000 (+0300) Subject: Optimized inlining of njs_values_strict_equal(). X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=6b1467ca1247de6bb913977a3a515b326c066c6b;p=njs.git Optimized inlining of njs_values_strict_equal(). This function is often called inside loops and basically it does only a few cmp instructions that can be inlined. The more complex part related to comparing of two strings is functionally identical to njs_string_eq(), but contains an optimization that avoids memcmp() when strings have different lengths. This optimization has been merged into njs_string_eq(). No functional changes. --- diff --git a/njs/njs_string.c b/njs/njs_string.c index b6a21a54..050f25fe 100644 --- a/njs/njs_string.c +++ b/njs/njs_string.c @@ -689,7 +689,7 @@ njs_string_instance_length(njs_vm_t *vm, njs_value_t *value, nxt_bool_t njs_string_eq(const njs_value_t *v1, const njs_value_t *v2) { - size_t size; + size_t size, length1, length2; const u_char *start1, *start2; size = v1->short_string.size; @@ -699,6 +699,17 @@ njs_string_eq(const njs_value_t *v1, const njs_value_t *v2) } if (size != NJS_STRING_LONG) { + length1 = v1->short_string.length; + length2 = v2->short_string.length; + + /* + * Using full memcmp() comparison if at least one string + * is a Byte string. + */ + if (length1 != 0 && length2 != 0 && length1 != length2) { + return 0; + } + start1 = v1->short_string.start; start2 = v2->short_string.start; @@ -709,6 +720,17 @@ njs_string_eq(const njs_value_t *v1, const njs_value_t *v2) return 0; } + length1 = v1->long_string.data->length; + length2 = v2->long_string.data->length; + + /* + * Using full memcmp() comparison if at least one string + * is a Byte string. + */ + if (length1 != 0 && length2 != 0 && length1 != length2) { + return 0; + } + start1 = v1->long_string.data->start; start2 = v2->long_string.data->start; } diff --git a/njs/njs_string.h b/njs/njs_string.h index b8426ae9..6f47db1a 100644 --- a/njs/njs_string.h +++ b/njs/njs_string.h @@ -168,7 +168,6 @@ njs_ret_t njs_string_validate(njs_vm_t *vm, njs_string_prop_t *string, size_t njs_string_prop(njs_string_prop_t *string, const njs_value_t *value); njs_ret_t njs_string_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, njs_index_t unused); -nxt_bool_t njs_string_eq(const njs_value_t *val1, const njs_value_t *val2); nxt_int_t njs_string_cmp(const njs_value_t *val1, const njs_value_t *val2); void njs_string_slice_string_prop(njs_string_prop_t *dst, const njs_string_prop_t *string, const njs_slice_prop_t *slice); diff --git a/njs/njs_value.c b/njs/njs_value.c index 511720a6..16207a5a 100644 --- a/njs/njs_value.c +++ b/njs/njs_value.c @@ -91,77 +91,6 @@ njs_value_release(njs_vm_t *vm, njs_value_t *value) } -nxt_bool_t -njs_values_strict_equal(const njs_value_t *val1, const njs_value_t *val2) -{ - size_t size, length1, length2; - const u_char *start1, *start2; - - if (val1->type != val2->type) { - return 0; - } - - if (njs_is_numeric(val1)) { - - if (njs_is_undefined(val1)) { - return 1; - } - - /* Infinities are handled correctly by comparision. */ - return (njs_number(val1) == njs_number(val2)); - } - - if (njs_is_string(val1)) { - size = val1->short_string.size; - - if (size != val2->short_string.size) { - return 0; - } - - if (size != NJS_STRING_LONG) { - length1 = val1->short_string.length; - length2 = val2->short_string.length; - - /* - * Using full memcmp() comparison if at least one string - * is a Byte string. - */ - if (length1 != 0 && length2 != 0 && length1 != length2) { - return 0; - } - - start1 = val1->short_string.start; - start2 = val2->short_string.start; - - } else { - size = val1->long_string.size; - - if (size != val2->long_string.size) { - return 0; - } - - length1 = val1->long_string.data->length; - length2 = val2->long_string.data->length; - - /* - * Using full memcmp() comparison if at least one string - * is a Byte string. - */ - if (length1 != 0 && length2 != 0 && length1 != length2) { - return 0; - } - - start1 = val1->long_string.data->start; - start2 = val2->long_string.data->start; - } - - return (memcmp(start1, start2, size) == 0); - } - - return (njs_object(val1) == njs_object(val2)); -} - - /* * A hint value is 0 for numbers and 1 for strings. The value chooses * method calls order specified by ECMAScript 5.1: "valueOf", "toString" diff --git a/njs/njs_value.h b/njs/njs_value.h index e7025cbb..c614630d 100644 --- a/njs/njs_value.h +++ b/njs/njs_value.h @@ -685,8 +685,6 @@ njs_set_object_value(njs_value_t *value, njs_object_value_t *object_value) void njs_value_retain(njs_value_t *value); void njs_value_release(njs_vm_t *vm, njs_value_t *value); -nxt_bool_t njs_values_strict_equal(const njs_value_t *val1, - const njs_value_t *val2); njs_ret_t njs_value_to_primitive(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint); njs_array_t *njs_value_enumerate(njs_vm_t *vm, const njs_value_t *value, @@ -696,6 +694,33 @@ njs_array_t *njs_value_own_enumerate(njs_vm_t *vm, const njs_value_t *value, const char *njs_type_string(njs_value_type_t type); const char *njs_arg_type_string(uint8_t arg); +nxt_bool_t njs_string_eq(const njs_value_t *v1, const njs_value_t *v2); + + +nxt_inline nxt_bool_t +njs_values_strict_equal(const njs_value_t *val1, const njs_value_t *val2) +{ + if (val1->type != val2->type) { + return 0; + } + + if (njs_is_numeric(val1)) { + + if (njs_is_undefined(val1)) { + return 1; + } + + /* Infinities are handled correctly by comparision. */ + return (njs_number(val1) == njs_number(val2)); + } + + if (njs_is_string(val1)) { + return njs_string_eq(val1, val2); + } + + return (njs_object(val1) == njs_object(val2)); +} + extern const njs_value_t njs_value_null; extern const njs_value_t njs_value_undefined;