[njs] Improved Array object allocation after ccfa84cea2b3.

Dmitry Volyntsev xeioex at nginx.com
Mon Feb 10 16:01:59 UTC 2020


details:   https://hg.nginx.org/njs/rev/79c14715edc2
branches:  
changeset: 1323:79c14715edc2
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Mon Feb 10 17:09:53 2020 +0300
description:
Improved Array object allocation after ccfa84cea2b3.

Sometimes flat array alignment is desired, even if its "length" exceeds
32768. This patch introduces additional argument for njs_array_alloc()
which enforced flat allocation when it is set.

diffstat:

 src/njs_array.c    |  75 +++++++++++++++++++++++++++++++++++++++++++----------
 src/njs_array.h    |   5 ++-
 src/njs_builtin.c  |   2 +-
 src/njs_extern.c   |   2 +-
 src/njs_function.c |   4 +-
 src/njs_json.c     |  20 ++++++++++----
 src/njs_object.c   |  73 ++++++++++++++++++++++++++++++---------------------
 src/njs_regexp.c   |   2 +-
 src/njs_string.c   |   4 +-
 src/njs_value.c    |   4 +-
 src/njs_vm.c       |   2 +-
 src/njs_vmcode.c   |   2 +-
 12 files changed, 133 insertions(+), 62 deletions(-)

diffs (715 lines):

diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_array.c
--- a/src/njs_array.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_array.c	Mon Feb 10 17:09:53 2020 +0300
@@ -32,7 +32,7 @@ static njs_int_t njs_array_prototype_sli
 
 
 njs_array_t *
-njs_array_alloc(njs_vm_t *vm, uint64_t length, uint32_t spare)
+njs_array_alloc(njs_vm_t *vm, njs_bool_t flat, uint64_t length, uint32_t spare)
 {
     uint64_t     size;
     njs_int_t    ret;
@@ -50,7 +50,7 @@ njs_array_alloc(njs_vm_t *vm, uint64_t l
 
     size = length + spare;
 
-    if (size <= NJS_ARRAY_LARGE_OBJECT_LENGTH) {
+    if (flat || size <= NJS_ARRAY_LARGE_OBJECT_LENGTH) {
         array->data = njs_mp_align(vm->mem_pool, sizeof(njs_value_t),
                                    size * sizeof(njs_value_t));
         if (njs_slow_path(array->data == NULL)) {
@@ -102,6 +102,19 @@ overflow:
 }
 
 
+void
+njs_array_destroy(njs_vm_t *vm, njs_array_t *array)
+{
+    if (array->data != NULL) {
+        njs_mp_free(vm->mem_pool, array->data);
+    }
+
+    /* TODO: destroy keys. */
+
+    njs_mp_free(vm->mem_pool, array);
+}
+
+
 njs_int_t
 njs_array_convert_to_slow_array(njs_vm_t *vm, njs_array_t *array)
 {
@@ -195,6 +208,8 @@ njs_array_length_set(njs_vm_t *vm, njs_v
         return ret;
     }
 
+    keys = NULL;
+
     if (length < prev_length) {
         keys = njs_array_indices(vm, value);
         if (njs_slow_path(keys == NULL)) {
@@ -210,7 +225,7 @@ njs_array_length_set(njs_vm_t *vm, njs_v
                     ret = njs_value_property_delete(vm, value, &keys->start[i],
                                                     NULL);
                     if (njs_slow_path(ret == NJS_ERROR)) {
-                        return ret;
+                        goto done;
                     }
                 }
             } while (i-- != 0);
@@ -222,7 +237,15 @@ njs_array_length_set(njs_vm_t *vm, njs_v
         return ret;
     }
 
-    return NJS_OK;
+    ret = NJS_OK;
+
+done:
+
+    if (keys != NULL) {
+        njs_array_destroy(vm, keys);
+    }
+
+    return ret;
 }
 
 
@@ -341,7 +364,8 @@ njs_array_constructor(njs_vm_t *vm, njs_
         args = NULL;
     }
 
-    array = njs_array_alloc(vm, size, NJS_ARRAY_SPARE);
+    array = njs_array_alloc(vm, size <= NJS_ARRAY_FLAT_MAX_LENGTH,
+                            size, NJS_ARRAY_SPARE);
 
     if (njs_fast_path(array != NULL)) {
 
@@ -401,7 +425,7 @@ njs_array_of(njs_vm_t *vm, njs_value_t *
 
     length = nargs > 1 ? nargs - 1 : 0;
 
-    array = njs_array_alloc(vm, length, NJS_ARRAY_SPARE);
+    array = njs_array_alloc(vm, 0, length, NJS_ARRAY_SPARE);
     if (njs_slow_path(array == NULL)) {
         return NJS_ERROR;
     }
@@ -639,12 +663,14 @@ njs_array_prototype_slice_copy(njs_vm_t 
     njs_slice_prop_t   string_slice;
     njs_string_prop_t  string;
 
-    array = njs_array_alloc(vm, length, NJS_ARRAY_SPARE);
+    keys = NULL;
+    array = njs_array_alloc(vm, 0, length, NJS_ARRAY_SPARE);
     if (njs_slow_path(array == NULL)) {
         return NJS_ERROR;
     }
 
     if (njs_slow_path(length == 0)) {
+        ret = NJS_OK;
         goto done;
     }
 
@@ -744,6 +770,7 @@ njs_array_prototype_slice_copy(njs_vm_t 
             } while (length != 0);
         }
 
+        ret = NJS_OK;
         goto done;
     }
 
@@ -768,6 +795,7 @@ njs_array_prototype_slice_copy(njs_vm_t 
             length--;
         } while (length != 0);
 
+        ret = NJS_OK;
         goto done;
     }
 
@@ -779,21 +807,27 @@ njs_array_prototype_slice_copy(njs_vm_t 
     for (n = 0; n < keys->length; n++) {
         ret = njs_value_property(vm, this, &keys->start[n], &retval);
         if (njs_slow_path(ret == NJS_ERROR)) {
-            return ret;
+            goto done;
         }
 
         ret = njs_value_property_set(vm, &array_value, &keys->start[n],
                                      &retval);
         if (njs_slow_path(ret == NJS_ERROR)) {
-            return ret;
+            goto done;
         }
     }
 
+    ret = NJS_OK;
+
 done:
 
+    if (keys != NULL) {
+        njs_array_destroy(vm, keys);
+    }
+
     njs_set_array(&vm->retval, array);
 
-    return NJS_OK;
+    return ret;
 }
 
 
@@ -992,6 +1026,7 @@ njs_array_prototype_unshift(njs_vm_t *vm
             ret = njs_value_property_delete(vm, this, &keys->start[--from],
                                             &entry);
             if (njs_slow_path(ret == NJS_ERROR)) {
+                njs_array_destroy(vm, keys);
                 return ret;
             }
 
@@ -1002,11 +1037,14 @@ njs_array_prototype_unshift(njs_vm_t *vm
 
                 ret = njs_value_property_set(vm, this, &index, &entry);
                 if (njs_slow_path(ret == NJS_ERROR)) {
+                    njs_array_destroy(vm, keys);
                     return ret;
                 }
             }
         }
 
+        njs_array_destroy(vm, keys);
+
         length += nargs - 1;
 
         goto copy;
@@ -1208,7 +1246,7 @@ njs_array_prototype_splice(njs_vm_t *vm,
         }
     }
 
-    deleted = njs_array_alloc(vm, delete, 0);
+    deleted = njs_array_alloc(vm, 0, delete, 0);
     if (njs_slow_path(deleted == NULL)) {
         return NJS_ERROR;
     }
@@ -1711,10 +1749,13 @@ process_object:
             ret = njs_array_object_handler(vm, handler, args, &keys->start[i],
                                            idx);
             if (njs_slow_path(ret != NJS_OK)) {
+                njs_array_destroy(vm, keys);
                 return ret;
             }
         }
 
+        njs_array_destroy(vm, keys);
+
         return NJS_OK;
     }
 
@@ -1867,10 +1908,13 @@ process_object:
             ret = njs_array_object_handler(vm, handler, args, &keys->start[i],
                                            idx);
             if (njs_slow_path(ret != NJS_OK)) {
+                njs_array_destroy(vm, keys);
                 return ret;
             }
         }
 
+        njs_array_destroy(vm, keys);
+
         return NJS_OK;
     }
 
@@ -1934,7 +1978,7 @@ njs_array_prototype_concat(njs_vm_t *vm,
 
     /* TODO: ArraySpeciesCreate(). */
 
-    array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
+    array = njs_array_alloc(vm, 0, 0, NJS_ARRAY_SPARE);
     if (njs_slow_path(array == NULL)) {
         return NJS_ERROR;
     }
@@ -2035,11 +2079,14 @@ njs_array_prototype_concat(njs_vm_t *vm,
 
                     ret = njs_value_property_set(vm, &this, &index, &retval);
                     if (njs_slow_path(ret == NJS_ERROR)) {
+                        njs_array_destroy(vm, keys);
                         return ret;
                     }
                 }
             }
 
+            njs_array_destroy(vm, keys);
+
             length += len;
 
             continue;
@@ -2589,7 +2636,7 @@ njs_array_prototype_filter(njs_vm_t *vm,
         return ret;
     }
 
-    iargs.array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
+    iargs.array = njs_array_alloc(vm, 0, 0, NJS_ARRAY_SPARE);
     if (njs_slow_path(iargs.array == NULL)) {
         return NJS_ERROR;
     }
@@ -2779,7 +2826,7 @@ njs_array_prototype_map(njs_vm_t *vm, nj
         goto unexpected_args;
     }
 
-    iargs.array = njs_array_alloc(vm, length, 0);
+    iargs.array = njs_array_alloc(vm, 0, length, 0);
     if (njs_slow_path(iargs.array == NULL)) {
         return NJS_ERROR;
     }
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_array.h
--- a/src/njs_array.h	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_array.h	Mon Feb 10 17:09:53 2020 +0300
@@ -16,8 +16,11 @@
 #define NJS_ARRAY_MAX_LENGTH53         (0x1fffffffffffff)
 #define NJS_ARRAY_FAST_OBJECT_LENGTH   (128)
 #define NJS_ARRAY_LARGE_OBJECT_LENGTH  (32768)
+#define NJS_ARRAY_FLAT_MAX_LENGTH      (1048576)
 
-njs_array_t *njs_array_alloc(njs_vm_t *vm, uint64_t length, uint32_t spare);
+njs_array_t *njs_array_alloc(njs_vm_t *vm, njs_bool_t flat, uint64_t length,
+    uint32_t spare);
+void njs_array_destroy(njs_vm_t *vm, njs_array_t *array);
 njs_int_t njs_array_add(njs_vm_t *vm, njs_array_t *array, njs_value_t *value);
 njs_int_t njs_array_convert_to_slow_array(njs_vm_t *vm, njs_array_t *array);
 njs_int_t njs_array_length_redefine(njs_vm_t *vm, njs_value_t *value,
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_builtin.c
--- a/src/njs_builtin.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_builtin.c	Mon Feb 10 17:09:53 2020 +0300
@@ -1511,7 +1511,7 @@ njs_process_object_argv(njs_vm_t *vm, nj
 
     static const njs_value_t  argv_string = njs_string("argv");
 
-    argv = njs_array_alloc(vm, vm->options.argc, 0);
+    argv = njs_array_alloc(vm, 1, vm->options.argc, 0);
     if (njs_slow_path(argv == NULL)) {
         return NJS_ERROR;
     }
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_extern.c
--- a/src/njs_extern.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_extern.c	Mon Feb 10 17:09:53 2020 +0300
@@ -234,7 +234,7 @@ njs_extern_keys_array(njs_vm_t *vm, cons
         keys_length++;
     }
 
-    keys = njs_array_alloc(vm, keys_length, NJS_ARRAY_SPARE);
+    keys = njs_array_alloc(vm, 1, keys_length, NJS_ARRAY_SPARE);
     if (njs_slow_path(keys == NULL)) {
         return NULL;
     }
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_function.c
--- a/src/njs_function.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_function.c	Mon Feb 10 17:09:53 2020 +0300
@@ -301,7 +301,7 @@ njs_function_rest_parameters_init(njs_vm
     n = frame->function->u.lambda->nargs;
     length = (nargs >= n) ? (nargs - n + 1) : 0;
 
-    array = njs_array_alloc(vm, length, 0);
+    array = njs_array_alloc(vm, 1, length, 0);
     if (njs_slow_path(array == NULL)) {
         return NJS_ERROR;
     }
@@ -1125,7 +1125,7 @@ njs_function_prototype_apply(njs_vm_t *v
         return ret;
     }
 
-    arr = njs_array_alloc(vm, length, NJS_ARRAY_SPARE);
+    arr = njs_array_alloc(vm, 1, length, NJS_ARRAY_SPARE);
     if (njs_slow_path(arr == NULL)) {
         return NJS_ERROR;
     }
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_json.c
--- a/src/njs_json.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_json.c	Mon Feb 10 17:09:53 2020 +0300
@@ -31,6 +31,7 @@ typedef struct {
     uint32_t                   index;
     uint32_t                   length;
     njs_array_t                *keys;
+    njs_value_t                *key;
     njs_object_prop_t          *prop;
 } njs_json_state_t;
 
@@ -448,7 +449,7 @@ njs_json_parse_array(njs_json_parse_ctx_
         return NULL;
     }
 
-    array = njs_array_alloc(ctx->vm, 0, 0);
+    array = njs_array_alloc(ctx->vm, 0, 0, NJS_ARRAY_SPARE);
     if (njs_slow_path(array == NULL)) {
         return NULL;
     }
@@ -1027,6 +1028,8 @@ njs_json_push_stringify_state(njs_vm_t *
     state->value = *value;
     state->index = 0;
     state->written = 0;
+    state->keys = NULL;
+    state->key = NULL;
 
     if (njs_is_fast_array(value)) {
         state->type = NJS_JSON_ARRAY;
@@ -1069,6 +1072,12 @@ njs_json_pop_stringify_state(njs_json_st
 {
     njs_json_state_t  *state;
 
+    state = &stringify->states[stringify->depth - 1];
+    if (!njs_is_array(&stringify->replacer) && state->keys != NULL) {
+        njs_array_destroy(stringify->vm, state->keys);
+        state->keys = NULL;
+    }
+
     if (stringify->depth > 1) {
         stringify->depth--;
         state = &stringify->states[stringify->depth - 1];
@@ -1411,7 +1420,7 @@ njs_json_stringify_replacer(njs_json_str
 
 
 static njs_int_t
-njs_json_stringify_array(njs_vm_t *vm, njs_json_stringify_t  *stringify)
+njs_json_stringify_array(njs_vm_t *vm, njs_json_stringify_t *stringify)
 {
     njs_int_t    ret;
     uint32_t     i, n, k, properties_length, array_length;
@@ -1428,7 +1437,7 @@ njs_json_stringify_array(njs_vm_t *vm, n
         }
     }
 
-    properties = njs_array_alloc(vm, properties_length, NJS_ARRAY_SPARE);
+    properties = njs_array_alloc(vm, 1, properties_length, NJS_ARRAY_SPARE);
     if (njs_slow_path(properties == NULL)) {
         return NJS_ERROR;
     }
@@ -2086,7 +2095,6 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
         goto memory_error;
     }
 
-    key = NULL;
     (void) njs_dump_visit(&visited, value);
 
     for ( ;; ) {
@@ -2106,12 +2114,11 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
 
                 njs_chb_append(&chain, state->array ? "[" : "{", 1);
                 njs_json_stringify_indent(stringify, &chain, 1);
-
             }
 
             if (state->index >= state->keys->length) {
                 njs_dump_empty(stringify, state, &chain, state->length,
-                     (state->index > 0) ? njs_key_to_index(key) : -1, 0);
+                     (state->index > 0) ? njs_key_to_index(state->key) : -1, 0);
 
                 njs_json_stringify_indent(stringify, &chain, 0);
                 njs_chb_append(&chain, state->array ? "]" : "}", 1);
@@ -2127,6 +2134,7 @@ njs_vm_value_dump(njs_vm_t *vm, njs_str_
             njs_property_query_init(&pq, NJS_PROPERTY_QUERY_GET, 0);
 
             key = &state->keys->start[state->index++];
+            state->key = key;
 
             ret = njs_property_query(vm, &pq, &state->value, key);
             if (njs_slow_path(ret != NJS_OK)) {
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_object.c
--- a/src/njs_object.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_object.c	Mon Feb 10 17:09:53 2020 +0300
@@ -584,16 +584,11 @@ njs_object_enumerate(njs_vm_t *vm, const
 
     length = njs_object_enumerate_length(object, type, all);
 
-    items = njs_array_alloc(vm, length, NJS_ARRAY_SPARE);
+    items = njs_array_alloc(vm, 1, length, NJS_ARRAY_SPARE);
     if (njs_slow_path(items == NULL)) {
         return NULL;
     }
 
-    if (njs_slow_path(!items->object.fast_array)) {
-        njs_internal_error(vm, "njs_object_enumerate() too many keys");
-        return NULL;
-    }
-
     ret = njs_object_enumerate_value(vm, object, items, kind, type, all);
     if (njs_slow_path(ret != NJS_OK)) {
         return NULL;
@@ -615,16 +610,11 @@ njs_object_own_enumerate(njs_vm_t *vm, c
 
     length = njs_object_own_enumerate_length(object, object, type, all);
 
-    items = njs_array_alloc(vm, length, NJS_ARRAY_SPARE);
+    items = njs_array_alloc(vm, 1, length, NJS_ARRAY_SPARE);
     if (njs_slow_path(items == NULL)) {
         return NULL;
     }
 
-    if (njs_slow_path(!items->object.fast_array)) {
-        njs_internal_error(vm, "njs_object_own_enumerate() too many keys");
-        return NULL;
-    }
-
     ret = njs_object_own_enumerate_value(vm, object, object, items, kind, type,
                                          all);
     if (njs_slow_path(ret != NJS_OK)) {
@@ -804,7 +794,7 @@ njs_object_enumerate_array(njs_vm_t *vm,
         for (i = 0; i < array->length; i++) {
             if (njs_is_valid(&array->start[i])) {
 
-                entry = njs_array_alloc(vm, 2, 0);
+                entry = njs_array_alloc(vm, 0, 2, 0);
                 if (njs_slow_path(entry == NULL)) {
                     return NJS_ERROR;
                 }
@@ -857,7 +847,7 @@ njs_object_enumerate_typed_array(njs_vm_
 
     case NJS_ENUM_BOTH:
         for (i = 0; i < length; i++) {
-            entry = njs_array_alloc(vm, 2, 0);
+            entry = njs_array_alloc(vm, 0, 2, 0);
             if (njs_slow_path(entry == NULL)) {
                 return NJS_ERROR;
             }
@@ -938,7 +928,7 @@ njs_object_enumerate_string(njs_vm_t *vm
 
             for (i = 0; i < len; i++) {
 
-                entry = njs_array_alloc(vm, 2, 0);
+                entry = njs_array_alloc(vm, 0, 2, 0);
                 if (njs_slow_path(entry == NULL)) {
                     return NJS_ERROR;
                 }
@@ -965,7 +955,7 @@ njs_object_enumerate_string(njs_vm_t *vm
             i = 0;
 
             do {
-                entry = njs_array_alloc(vm, 2, 0);
+                entry = njs_array_alloc(vm, 0, 2, 0);
                 if (njs_slow_path(entry == NULL)) {
                     return NJS_ERROR;
                 }
@@ -1171,7 +1161,7 @@ njs_object_own_enumerate_object(njs_vm_t
             if (ext_prop == NULL && prop->type != NJS_WHITEOUT
                 && (prop->enumerable || all))
             {
-                entry = njs_array_alloc(vm, 2, 0);
+                entry = njs_array_alloc(vm, 0, 2, 0);
                 if (njs_slow_path(entry == NULL)) {
                     return NJS_ERROR;
                 }
@@ -1209,7 +1199,7 @@ njs_object_own_enumerate_object(njs_vm_t
                 ext_prop = njs_object_exist_in_proto(parent, object, &lhq);
 
                 if (ext_prop == NULL) {
-                    entry = njs_array_alloc(vm, 2, 0);
+                    entry = njs_array_alloc(vm, 0, 2, 0);
                     if (njs_slow_path(entry == NULL)) {
                         return NJS_ERROR;
                     }
@@ -1442,7 +1432,7 @@ njs_object_define_properties(njs_vm_t *v
     for (i = 0; i < length; i++) {
         ret = njs_property_query(vm, &pq, descs, &keys->start[i]);
         if (njs_slow_path(ret == NJS_ERROR)) {
-            return ret;
+            goto done;
         }
 
         prop = pq.lhq.value;
@@ -1453,19 +1443,24 @@ njs_object_define_properties(njs_vm_t *v
 
         ret = njs_value_property(vm, descs, &keys->start[i], &desc);
         if (njs_slow_path(ret == NJS_ERROR)) {
-            return ret;
+            goto done;
         }
 
         ret = njs_object_prop_define(vm, value, &keys->start[i], &desc,
                                      NJS_OBJECT_PROP_DESCRIPTOR);
         if (njs_slow_path(ret != NJS_OK)) {
-            return NJS_ERROR;
+            goto done;
         }
     }
 
+    ret = NJS_OK;
     vm->retval = *value;
 
-    return NJS_OK;
+done:
+
+    njs_array_destroy(vm, keys);
+
+    return ret;
 }
 
 
@@ -1520,7 +1515,8 @@ njs_object_get_own_property_descriptors(
 
     descriptors = njs_object_alloc(vm);
     if (njs_slow_path(descriptors == NULL)) {
-        return NJS_ERROR;
+        ret = NJS_ERROR;
+        goto done;
     }
 
     lhq.replace = 0;
@@ -1531,12 +1527,14 @@ njs_object_get_own_property_descriptors(
         key = &names->start[i];
         ret = njs_object_prop_descriptor(vm, &descriptor, value, key);
         if (njs_slow_path(ret != NJS_OK)) {
-            return ret;
+            ret = NJS_ERROR;
+            goto done;
         }
 
         pr = njs_object_prop_alloc(vm, key, &descriptor, 1);
         if (njs_slow_path(pr == NULL)) {
-            return NJS_ERROR;
+            ret = NJS_ERROR;
+            goto done;
         }
 
         njs_object_property_key_set(&lhq, key, 0);
@@ -1545,13 +1543,18 @@ njs_object_get_own_property_descriptors(
         ret = njs_lvlhsh_insert(&descriptors->hash, &lhq);
         if (njs_slow_path(ret != NJS_OK)) {
             njs_internal_error(vm, "lvlhsh insert failed");
-            return NJS_ERROR;
+            goto done;
         }
     }
 
+    ret = NJS_OK;
     njs_set_object(&vm->retval, descriptors);
 
-    return NJS_OK;
+done:
+
+    njs_array_destroy(vm, names);
+
+    return ret;
 }
 
 
@@ -1912,6 +1915,8 @@ njs_object_assign(njs_vm_t *vm, njs_valu
         return ret;
     }
 
+    names = NULL;
+
     for (i = 2; i < nargs; i++) {
         source = &args[i];
 
@@ -1930,7 +1935,7 @@ njs_object_assign(njs_vm_t *vm, njs_valu
 
             ret = njs_property_query(vm, &pq, source, key);
             if (njs_slow_path(ret != NJS_OK)) {
-                return NJS_ERROR;
+                goto exception;
             }
 
             prop = pq.lhq.value;
@@ -1940,19 +1945,27 @@ njs_object_assign(njs_vm_t *vm, njs_valu
 
             ret = njs_value_property(vm, source, key, &setval);
             if (njs_slow_path(ret != NJS_OK)) {
-                return NJS_ERROR;
+                goto exception;
             }
 
             ret = njs_value_property_set(vm, value, key, &setval);
             if (njs_slow_path(ret != NJS_OK)) {
-                return NJS_ERROR;
+                goto exception;
             }
         }
+
+        njs_array_destroy(vm, names);
     }
 
     vm->retval = *value;
 
     return NJS_OK;
+
+exception:
+
+    njs_array_destroy(vm, names);
+
+    return NJS_ERROR;
 }
 
 
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_regexp.c
--- a/src/njs_regexp.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_regexp.c	Mon Feb 10 17:09:53 2020 +0300
@@ -1072,7 +1072,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs
     static const njs_value_t  string_input = njs_string("input");
     static const njs_value_t  string_groups = njs_string("groups");
 
-    array = njs_array_alloc(vm, regexp->pattern->ncaptures, 0);
+    array = njs_array_alloc(vm, 0, regexp->pattern->ncaptures, 0);
     if (njs_slow_path(array == NULL)) {
         goto fail;
     }
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_string.c
--- a/src/njs_string.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_string.c	Mon Feb 10 17:09:53 2020 +0300
@@ -3237,7 +3237,7 @@ njs_string_match_multiple(njs_vm_t *vm, 
 
     if (njs_regex_is_valid(&pattern->regex[type])) {
 
-        array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
+        array = njs_array_alloc(vm, 0, 0, NJS_ARRAY_SPARE);
         if (njs_slow_path(array == NULL)) {
             return NJS_ERROR;
         }
@@ -3330,7 +3330,7 @@ njs_string_prototype_split(njs_vm_t *vm,
         return ret;
     }
 
-    array = njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
+    array = njs_array_alloc(vm, 0, 0, NJS_ARRAY_SPARE);
     if (njs_slow_path(array == NULL)) {
         return NJS_ERROR;
     }
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_value.c
--- a/src/njs_value.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_value.c	Mon Feb 10 17:09:53 2020 +0300
@@ -228,7 +228,7 @@ njs_value_enumerate(njs_vm_t *vm, const 
             return njs_extern_keys_array(vm, ext_proto);
         }
 
-        return njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
+        return njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
     }
 
     obj_val.object = vm->string_object;
@@ -273,7 +273,7 @@ njs_value_own_enumerate(njs_vm_t *vm, co
             return njs_extern_keys_array(vm, ext_proto);
         }
 
-        return njs_array_alloc(vm, 0, NJS_ARRAY_SPARE);
+        return njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
     }
 
     obj_val.object = vm->string_object;
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_vm.c
--- a/src/njs_vm.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_vm.c	Mon Feb 10 17:09:53 2020 +0300
@@ -805,7 +805,7 @@ njs_vm_array_alloc(njs_vm_t *vm, njs_val
 {
     njs_array_t  *array;
 
-    array = njs_array_alloc(vm, 0, spare);
+    array = njs_array_alloc(vm, 0, 0, spare);
 
     if (njs_slow_path(array == NULL)) {
         return NJS_ERROR;
diff -r 1f3e045ea017 -r 79c14715edc2 src/njs_vmcode.c
--- a/src/njs_vmcode.c	Sun Jan 26 21:56:23 2020 +0300
+++ b/src/njs_vmcode.c	Mon Feb 10 17:09:53 2020 +0300
@@ -966,7 +966,7 @@ njs_vmcode_array(njs_vm_t *vm, u_char *p
 
     code = (njs_vmcode_array_t *) pc;
 
-    array = njs_array_alloc(vm, code->length, NJS_ARRAY_SPARE);
+    array = njs_array_alloc(vm, 0, code->length, NJS_ARRAY_SPARE);
 
     if (njs_fast_path(array != NULL)) {
 


More information about the nginx-devel mailing list