[njs] Array creation and reallocation optimizations.

Igor Sysoev igor at sysoev.ru
Mon Oct 24 12:03:50 UTC 2016


details:   http://hg.nginx.org/njs/rev/bf848210269c
branches:  
changeset: 212:bf848210269c
user:      Igor Sysoev <igor at sysoev.ru>
date:      Mon Oct 24 14:12:12 2016 +0300
description:
Array creation and reallocation optimizations.

diffstat:

 njs/njs_array.c        |  35 ++++++++++-------------------------
 njs/njs_disassembler.c |   5 +++--
 njs/njs_generator.c    |   6 +-----
 njs/njs_parser.c       |   5 +++--
 njs/njs_vm.c           |  41 ++++++++++++++++++++++++++++++-----------
 5 files changed, 47 insertions(+), 45 deletions(-)

diffs (213 lines):

diff -r cec366d97854 -r bf848210269c njs/njs_array.c
--- a/njs/njs_array.c	Sat Oct 22 20:24:32 2016 +0300
+++ b/njs/njs_array.c	Mon Oct 24 14:12:12 2016 +0300
@@ -184,8 +184,7 @@ njs_ret_t
 njs_array_realloc(njs_vm_t *vm, njs_array_t *array, uint32_t prepend,
     uint32_t size)
 {
-    nxt_uint_t   n;
-    njs_value_t  *value, *old;
+    njs_value_t  *start, *old;
 
     if (size != array->size) {
         if (size < 16) {
@@ -196,35 +195,21 @@ njs_array_realloc(njs_vm_t *vm, njs_arra
         }
     }
 
-    value = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
+    start = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
                                 (prepend + size) * sizeof(njs_value_t));
-    if (nxt_slow_path(value == NULL)) {
+    if (nxt_slow_path(start == NULL)) {
         return NXT_ERROR;
     }
 
-    old = array->data;
-    array->data = value;
-
-    while (prepend != 0) {
-        njs_set_invalid(value);
-        value++;
-        prepend--;
-    }
-
-    memcpy(value, array->start, array->size * sizeof(njs_value_t));
-
-    array->start = value;
-    n = array->size;
     array->size = size;
 
-    value += n;
-    size -= n;
+    old = array->data;
+    array->data = start;
+    start += prepend;
 
-    while (size != 0) {
-        njs_set_invalid(value);
-        value++;
-        size--;
-    }
+    memcpy(start, array->start, array->length * sizeof(njs_value_t));
+
+    array->start = start;
 
     nxt_mem_cache_free(vm->mem_cache_pool, old);
 
@@ -515,7 +500,7 @@ njs_array_prototype_unshift(njs_vm_t *vm
 
         if (n != 0) {
             if ((intptr_t) n > (array->start - array->data)) {
-                ret = njs_array_realloc(vm, array, n, array->size);
+                ret = njs_array_realloc(vm, array, n, 0);
                 if (nxt_slow_path(ret != NXT_OK)) {
                     return ret;
                 }
diff -r cec366d97854 -r bf848210269c njs/njs_disassembler.c
--- a/njs/njs_disassembler.c	Sat Oct 22 20:24:32 2016 +0300
+++ b/njs/njs_disassembler.c	Mon Oct 24 14:12:12 2016 +0300
@@ -197,8 +197,9 @@ njs_disassemble(u_char *start, u_char *e
         if (operation == njs_vmcode_array) {
             array = (njs_vmcode_array_t *) p;
 
-            printf("%05zd ARRAY             %04zX %zd\n",
-                   p - start, (size_t) array->retval, (size_t) array->length);
+            printf("%05zd ARRAY             %04zX %zd%s\n",
+                   p - start, (size_t) array->retval, (size_t) array->length,
+                   array->code.ctor ? " INIT" : "");
 
             p += sizeof(njs_vmcode_array_t);
 
diff -r cec366d97854 -r bf848210269c njs/njs_generator.c
--- a/njs/njs_generator.c	Sat Oct 22 20:24:32 2016 +0300
+++ b/njs/njs_generator.c	Mon Oct 24 14:12:12 2016 +0300
@@ -1510,15 +1510,11 @@ njs_generate_array(njs_vm_t *vm, njs_par
     array->code.operation = njs_vmcode_array;
     array->code.operands = NJS_VMCODE_1OPERAND;
     array->code.retval = NJS_VMCODE_RETVAL;
+    array->code.ctor = node->ctor;
     array->retval = node->index;
     array->length = node->u.length;
 
-    if (node->left == NULL) {
-        return NXT_OK;
-    }
-
     /* Initialize array. */
-
     return njs_generator(vm, parser, node->left);
 }
 
diff -r cec366d97854 -r bf848210269c njs/njs_parser.c
--- a/njs/njs_parser.c	Sat Oct 22 20:24:32 2016 +0300
+++ b/njs/njs_parser.c	Mon Oct 24 14:12:12 2016 +0300
@@ -1885,6 +1885,7 @@ njs_parser_array(njs_vm_t *vm, njs_parse
         }
 
         if (token == NJS_TOKEN_COMMA) {
+            obj->ctor = 1;
             index++;
             continue;
         }
@@ -1942,11 +1943,11 @@ njs_parser_array(njs_vm_t *vm, njs_parse
         stmt->left = left;
         stmt->right = assign;
 
-        parser->code_size += sizeof(njs_vmcode_2addr_t);
         parser->node = stmt;
-
         left = stmt;
 
+        obj->ctor = 0;
+
         if (token == NJS_TOKEN_CLOSE_BRACKET) {
             break;
         }
diff -r cec366d97854 -r bf848210269c njs/njs_vm.c
--- a/njs/njs_vm.c	Sat Oct 22 20:24:32 2016 +0300
+++ b/njs/njs_vm.c	Mon Oct 24 14:12:12 2016 +0300
@@ -366,7 +366,7 @@ njs_vmcode_object(njs_vm_t *vm, njs_valu
 njs_ret_t
 njs_vmcode_array(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
 {
-    uint32_t            size;
+    uint32_t            length;
     njs_array_t         *array;
     njs_value_t         *value;
     njs_vmcode_array_t  *code;
@@ -376,14 +376,22 @@ njs_vmcode_array(njs_vm_t *vm, njs_value
     array = njs_array_alloc(vm, code->length, NJS_ARRAY_SPARE);
 
     if (nxt_fast_path(array != NULL)) {
-        size = array->size;
-        value = array->start;
-
-        do {
-            njs_set_invalid(value);
-            value++;
-            size--;
-        } while (size != 0);
+
+        if (code->code.ctor) {
+            /* Array of the form [,,,], [1,,]. */
+            value = array->start;
+            length = array->length;
+
+            do {
+                njs_set_invalid(value);
+                value++;
+                length--;
+            } while (length != 0);
+
+        } else {
+            /* Array of the form [], [,,1], [1,2,3]. */
+            array->length = 0;
+        }
 
         vm->retval.data.u.array = array;
         vm->retval.type = NJS_ARRAY;
@@ -1039,7 +1047,9 @@ static njs_ret_t
 njs_array_property_query(njs_vm_t *vm, njs_property_query_t *pq,
     njs_value_t *object, int32_t index)
 {
+    size_t       size;
     njs_ret_t    ret;
+    njs_value_t  *value;
     njs_array_t  *array;
 
     array = object->data.u.array;
@@ -1057,6 +1067,15 @@ njs_array_property_query(njs_vm_t *vm, n
             }
         }
 
+        value = &array->start[array->length];
+        size = index - array->length;
+
+        while (size != 0) {
+            njs_set_invalid(value);
+            value++;
+            size--;
+        }
+
         array->length = index + 1;
     }
 
@@ -1182,7 +1201,7 @@ njs_vmcode_property_foreach(njs_vm_t *vm
         next->lhe.proto = &njs_object_hash_proto;
         next->index = -1;
 
-        if (njs_is_array(object) && object->data.u.array->size != 0) {
+        if (njs_is_array(object) && object->data.u.array->length != 0) {
             next->index = 0;
         }
 
@@ -1222,7 +1241,7 @@ njs_vmcode_property_next(njs_vm_t *vm, n
         if (next->index >= 0) {
             array = object->data.u.array;
 
-            while ((uint32_t) next->index < array->size) {
+            while ((uint32_t) next->index < array->length) {
                 n = next->index++;
 
                 if (njs_is_valid(&array->start[n])) {



More information about the nginx-devel mailing list