[njs] Optimized inlining of njs_values_strict_equal().

Valentin Bartenev vbart at nginx.com
Thu Jul 11 13:11:11 UTC 2019


details:   https://hg.nginx.org/njs/rev/ea18aa7693da
branches:  
changeset: 1041:ea18aa7693da
user:      Valentin Bartenev <vbart at 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;


More information about the nginx-devel mailing list