details: https://hg.nginx.org/njs/rev/ea18aa7693da branches: changeset: 1041:ea18aa7693da user: Valentin Bartenev <vb...@nginx.com> date: Thu Jul 11 16:10:33 2019 +0300 description: 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. diffstat: njs/njs_string.c | 24 ++++++++++++++++++- njs/njs_string.h | 1 - njs/njs_value.c | 71 -------------------------------------------------------- njs/njs_value.h | 29 +++++++++++++++++++++- 4 files changed, 50 insertions(+), 75 deletions(-) diffs (186 lines): diff -r b5f72739c00e -r ea18aa7693da njs/njs_string.c --- a/njs/njs_string.c Thu Jul 11 15:42:33 2019 +0300 +++ b/njs/njs_string.c Thu Jul 11 16:10:33 2019 +0300 @@ -689,7 +689,7 @@ njs_string_instance_length(njs_vm_t *vm, 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, con } 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, con 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 -r b5f72739c00e -r ea18aa7693da njs/njs_string.h --- a/njs/njs_string.h Thu Jul 11 15:42:33 2019 +0300 +++ b/njs/njs_string.h Thu Jul 11 16:10:33 2019 +0300 @@ -168,7 +168,6 @@ njs_ret_t njs_string_validate(njs_vm_t * 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 -r b5f72739c00e -r ea18aa7693da njs/njs_value.c --- a/njs/njs_value.c Thu Jul 11 15:42:33 2019 +0300 +++ b/njs/njs_value.c Thu Jul 11 16:10:33 2019 +0300 @@ -91,77 +91,6 @@ njs_value_release(njs_vm_t *vm, njs_valu } -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 -r b5f72739c00e -r ea18aa7693da njs/njs_value.h --- a/njs/njs_value.h Thu Jul 11 15:42:33 2019 +0300 +++ b/njs/njs_value.h Thu Jul 11 16:10:33 2019 +0300 @@ -685,8 +685,6 @@ njs_set_object_value(njs_value_t *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 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; _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel