[njs] Simplifed object enumeration.

Dmitry Volyntsev xeioex at nginx.com
Wed Mar 18 11:55:45 UTC 2020


details:   https://hg.nginx.org/njs/rev/dee85b788982
branches:  
changeset: 1356:dee85b788982
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Wed Mar 18 14:50:46 2020 +0300
description:
Simplifed object enumeration.

diffstat:

 src/njs_object.c |  337 ++++++++++++++----------------------------------------
 1 files changed, 88 insertions(+), 249 deletions(-)

diffs (544 lines):

diff -r 627def6a4630 -r dee85b788982 src/njs_object.c
--- a/src/njs_object.c	Tue Mar 17 18:33:25 2020 +0300
+++ b/src/njs_object.c	Wed Mar 18 14:50:46 2020 +0300
@@ -11,13 +11,6 @@
 static njs_int_t njs_object_hash_test(njs_lvlhsh_query_t *lhq, void *data);
 static njs_object_prop_t *njs_object_exist_in_proto(const njs_object_t *begin,
     const njs_object_t *end, njs_lvlhsh_query_t *lhq);
-static uint32_t njs_object_enumerate_array_length(const njs_object_t *object);
-static uint32_t njs_object_enumerate_string_length(const njs_object_t *object);
-static uint32_t njs_object_enumerate_object_length(const njs_object_t *object,
-    njs_object_enum_type_t type, njs_bool_t all);
-static uint32_t njs_object_own_enumerate_object_length(
-    const njs_object_t *object, const njs_object_t *parent,
-    njs_object_enum_type_t type, njs_bool_t all);
 static njs_int_t njs_object_enumerate_array(njs_vm_t *vm,
     const njs_array_t *array, njs_array_t *items, njs_object_enum_t kind);
 static njs_int_t njs_object_enumerate_typed_array(njs_vm_t *vm,
@@ -425,64 +418,6 @@ next:
 }
 
 
-njs_inline uint32_t
-njs_object_enumerate_length(const njs_object_t *object,
-    njs_object_enum_type_t type, njs_bool_t all)
-{
-    uint32_t  length;
-
-    length = njs_object_enumerate_object_length(object, type, all);
-
-    if (type & NJS_STRING) {
-        switch (object->type) {
-        case NJS_ARRAY:
-            length += njs_object_enumerate_array_length(object);
-            break;
-
-        case NJS_OBJECT_STRING:
-            length += njs_object_enumerate_string_length(object);
-            break;
-
-        default:
-            break;
-        }
-    }
-
-    return length;
-}
-
-
-njs_inline uint32_t
-njs_object_own_enumerate_length(const njs_object_t *object,
-    const njs_object_t *parent, njs_object_enum_type_t type, njs_bool_t all)
-{
-    uint32_t  length;
-
-    length = njs_object_own_enumerate_object_length(object, parent, type, all);
-
-    if (type & NJS_ENUM_STRING) {
-        switch (object->type) {
-        case NJS_ARRAY:
-            length += njs_object_enumerate_array_length(object);
-            break;
-
-        case NJS_TYPED_ARRAY:
-            length += njs_typed_array_length((njs_typed_array_t *) object);
-            break;
-
-        case NJS_OBJECT_STRING:
-            length += njs_object_enumerate_string_length(object);
-            break;
-
-        default:
-            break;
-        }
-    }
-
-    return length;
-}
-
-
 njs_inline njs_int_t
 njs_object_enumerate_value(njs_vm_t *vm, const njs_object_t *object,
     njs_array_t *items, njs_object_enum_t kind, njs_object_enum_type_t type,
@@ -576,13 +511,10 @@ njs_array_t *
 njs_object_enumerate(njs_vm_t *vm, const njs_object_t *object,
     njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all)
 {
-    uint32_t     length;
     njs_int_t    ret;
     njs_array_t  *items;
 
-    length = njs_object_enumerate_length(object, type, all);
-
-    items = njs_array_alloc(vm, 1, length, NJS_ARRAY_SPARE);
+    items = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
     if (njs_slow_path(items == NULL)) {
         return NULL;
     }
@@ -592,8 +524,6 @@ njs_object_enumerate(njs_vm_t *vm, const
         return NULL;
     }
 
-    items->start -= items->length;
-
     return items;
 }
 
@@ -602,13 +532,10 @@ njs_array_t *
 njs_object_own_enumerate(njs_vm_t *vm, const njs_object_t *object,
     njs_object_enum_t kind, njs_object_enum_type_t type, njs_bool_t all)
 {
-    uint32_t     length;
     njs_int_t    ret;
     njs_array_t  *items;
 
-    length = njs_object_own_enumerate_length(object, object, type, all);
-
-    items = njs_array_alloc(vm, 1, length, NJS_ARRAY_SPARE);
+    items = njs_array_alloc(vm, 1, 0, NJS_ARRAY_SPARE);
     if (njs_slow_path(items == NULL)) {
         return NULL;
     }
@@ -619,64 +546,10 @@ njs_object_own_enumerate(njs_vm_t *vm, c
         return NULL;
     }
 
-    items->start -= items->length;
-
     return items;
 }
 
 
-static uint32_t
-njs_object_enumerate_array_length(const njs_object_t *object)
-{
-    uint32_t     i, length;
-    njs_array_t  *array;
-
-    length = 0;
-    array = (njs_array_t *) object;
-
-    if (object->fast_array) {
-        for (i = 0; i < array->length; i++) {
-            if (njs_is_valid(&array->start[i])) {
-                length++;
-            }
-        }
-    }
-
-    return length;
-}
-
-
-static uint32_t
-njs_object_enumerate_string_length(const njs_object_t *object)
-{
-    njs_object_value_t  *obj_val;
-
-    obj_val = (njs_object_value_t *) object;
-
-    return njs_string_length(&obj_val->value);
-}
-
-
-static uint32_t
-njs_object_enumerate_object_length(const njs_object_t *object,
-    njs_object_enum_type_t type, njs_bool_t all)
-{
-    uint32_t            length;
-    const njs_object_t  *proto;
-
-    length = njs_object_own_enumerate_object_length(object, object, type, all);
-
-    proto = object->__proto__;
-
-    while (proto != NULL) {
-        length += njs_object_own_enumerate_length(proto, object, type, all);
-        proto = proto->__proto__;
-    }
-
-    return length;
-}
-
-
 njs_inline njs_bool_t
 njs_is_enumerable(const njs_value_t *value, njs_object_enum_type_t type)
 {
@@ -685,136 +558,79 @@ njs_is_enumerable(const njs_value_t *val
 }
 
 
-static uint32_t
-njs_object_own_enumerate_object_length(const njs_object_t *object,
-    const njs_object_t *parent, njs_object_enum_type_t type, njs_bool_t all)
-{
-    uint32_t            length;
-    njs_int_t           ret;
-    njs_lvlhsh_each_t   lhe;
-    njs_object_prop_t   *prop, *ext_prop;
-    njs_lvlhsh_query_t  lhq;
-    const njs_lvlhsh_t  *hash;
-
-    njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
-    hash = &object->hash;
-
-    lhq.proto = &njs_object_hash_proto;
-
-    length = 0;
-
-    for ( ;; ) {
-        prop = njs_lvlhsh_each(hash, &lhe);
-
-        if (prop == NULL) {
-            break;
-        }
-
-        if (!njs_is_enumerable(&prop->name, type)) {
-            continue;
-        }
-
-        njs_object_property_key_set(&lhq, &prop->name, lhe.key_hash);
-
-        ext_prop = njs_object_exist_in_proto(parent, object, &lhq);
-
-        if (ext_prop == NULL && prop->type != NJS_WHITEOUT
-            && (prop->enumerable || all))
-        {
-            length++;
-        }
-    }
-
-    njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
-    hash = &object->shared_hash;
-
-    for ( ;; ) {
-        prop = njs_lvlhsh_each(hash, &lhe);
-
-        if (prop == NULL) {
-            break;
-        }
-
-        if (!njs_is_enumerable(&prop->name, type)) {
-            continue;
-        }
-
-        njs_object_property_key_set(&lhq, &prop->name, lhe.key_hash);
-
-        ret = njs_lvlhsh_find(&object->hash, &lhq);
-
-        if (ret != NJS_OK) {
-            ext_prop = njs_object_exist_in_proto(parent, object, &lhq);
-
-            if (ext_prop == NULL && (prop->enumerable || all)) {
-                length++;
-            }
-        }
-    }
-
-    return length;
-}
-
-
 static njs_int_t
 njs_object_enumerate_array(njs_vm_t *vm, const njs_array_t *array,
     njs_array_t *items, njs_object_enum_t kind)
 {
-    uint32_t     i;
-    njs_value_t  *item;
+    njs_int_t    ret;
+    njs_value_t  *p, *start, *end;
     njs_array_t  *entry;
 
     if (!array->object.fast_array) {
         return NJS_OK;
     }
 
-    item = items->start;
+    start = array->start;
+
+    p = start;
+    end = p + array->length;
 
     switch (kind) {
     case NJS_ENUM_KEYS:
-        for (i = 0; i < array->length; i++) {
-            if (njs_is_valid(&array->start[i])) {
-                njs_uint32_to_string(item++, i);
+        while (p < end) {
+            if (njs_is_valid(p)) {
+                ret = njs_array_expand(vm, items, 0, 1);
+                if (njs_slow_path(ret != NJS_OK)) {
+                    return NJS_ERROR;
+                }
+
+                njs_uint32_to_string(&items->start[items->length++], p - start);
             }
+
+            p++;
         }
 
         break;
 
     case NJS_ENUM_VALUES:
-        for (i = 0; i < array->length; i++) {
-            if (njs_is_valid(&array->start[i])) {
-                /* GC: retain. */
-                *item++ = array->start[i];
+        while (p < end) {
+            if (njs_is_valid(p)) {
+                ret = njs_array_add(vm, items, p);
+                if (njs_slow_path(ret != NJS_OK)) {
+                    return NJS_ERROR;
+                }
             }
+
+            p++;
         }
 
         break;
 
     case NJS_ENUM_BOTH:
-        for (i = 0; i < array->length; i++) {
-            if (njs_is_valid(&array->start[i])) {
-
+        while (p < end) {
+            if (njs_is_valid(p)) {
                 entry = njs_array_alloc(vm, 0, 2, 0);
                 if (njs_slow_path(entry == NULL)) {
                     return NJS_ERROR;
                 }
 
-                njs_uint32_to_string(&entry->start[0], i);
-
-                /* GC: retain. */
-                entry->start[1] = array->start[i];
-
-                njs_set_array(item, entry);
-
-                item++;
+                njs_uint32_to_string(&entry->start[0], p - start);
+                entry->start[1] = *p;
+
+                ret = njs_array_expand(vm, items, 0, 1);
+                if (njs_slow_path(ret != NJS_OK)) {
+                    return NJS_ERROR;
+                }
+
+                njs_set_array(&items->start[items->length++], entry);
             }
+
+            p++;
         }
 
         break;
     }
 
-    items->start = item;
-
     return NJS_OK;
 }
 
@@ -824,12 +640,19 @@ njs_object_enumerate_typed_array(njs_vm_
     njs_array_t *items, njs_object_enum_t kind)
 {
     uint32_t     i, length;
+    njs_int_t    ret;
     njs_value_t  *item;
     njs_array_t  *entry;
 
-    item = items->start;
     length = njs_typed_array_length(array);
 
+    ret = njs_array_expand(vm, items, 0, length);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
+
+    item = &items->start[items->length];
+
     switch (kind) {
     case NJS_ENUM_KEYS:
         for (i = 0; i < length; i++) {
@@ -861,7 +684,7 @@ njs_object_enumerate_typed_array(njs_vm_
         break;
     }
 
-    items->start = item;
+    items->length += length;
 
     return NJS_OK;
 }
@@ -873,14 +696,21 @@ njs_object_enumerate_string(njs_vm_t *vm
 {
     u_char             *begin;
     uint32_t           i, len, size;
+    njs_int_t          ret;
     njs_value_t        *item, *string;
     njs_array_t        *entry;
     const u_char       *src, *end;
     njs_string_prop_t  str_prop;
 
-    item = items->start;
     len = (uint32_t) njs_string_prop(&str_prop, value);
 
+    ret = njs_array_expand(vm, items, 0, len);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
+
+    item = &items->start[items->length];
+
     switch (kind) {
     case NJS_ENUM_KEYS:
         for (i = 0; i < len; i++) {
@@ -980,7 +810,7 @@ njs_object_enumerate_string(njs_vm_t *vm
         break;
     }
 
-    items->start = item;
+    items->length += len;
 
     return NJS_OK;
 }
@@ -1022,20 +852,18 @@ njs_object_own_enumerate_object(njs_vm_t
     njs_object_enum_type_t type, njs_bool_t all)
 {
     njs_int_t           ret;
-    njs_value_t         *item;
+    njs_value_t         value;
     njs_array_t         *entry;
     njs_lvlhsh_each_t   lhe;
     njs_object_prop_t   *prop, *ext_prop;
     njs_lvlhsh_query_t  lhq;
     const njs_lvlhsh_t  *hash;
 
+    lhq.proto = &njs_object_hash_proto;
+
     njs_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
-
-    item = items->start;
     hash = &object->hash;
 
-    lhq.proto = &njs_object_hash_proto;
-
     switch (kind) {
     case NJS_ENUM_KEYS:
         for ( ;; ) {
@@ -1056,7 +884,10 @@ njs_object_own_enumerate_object(njs_vm_t
             if (ext_prop == NULL && prop->type != NJS_WHITEOUT
                 && (prop->enumerable || all))
             {
-                njs_string_copy(item++, &prop->name);
+                ret = njs_array_add(vm, items, &prop->name);
+                if (njs_slow_path(ret != NJS_OK)) {
+                    return NJS_ERROR;
+                }
             }
         }
 
@@ -1082,7 +913,10 @@ njs_object_own_enumerate_object(njs_vm_t
                 ext_prop = njs_object_exist_in_proto(parent, object, &lhq);
 
                 if (ext_prop == NULL && (prop->enumerable || all)) {
-                    njs_string_copy(item++, &prop->name);
+                    ret = njs_array_add(vm, items, &prop->name);
+                    if (njs_slow_path(ret != NJS_OK)) {
+                        return NJS_ERROR;
+                    }
                 }
             }
         }
@@ -1108,8 +942,10 @@ njs_object_own_enumerate_object(njs_vm_t
             if (ext_prop == NULL && prop->type != NJS_WHITEOUT
                 && (prop->enumerable || all))
             {
-                /* GC: retain. */
-                *item++ = prop->value;
+                ret = njs_array_add(vm, items, &prop->value);
+                if (njs_slow_path(ret != NJS_OK)) {
+                    return NJS_ERROR;
+                }
             }
         }
 
@@ -1135,7 +971,10 @@ njs_object_own_enumerate_object(njs_vm_t
                 ext_prop = njs_object_exist_in_proto(parent, object, &lhq);
 
                 if (ext_prop == NULL && (prop->enumerable || all)) {
-                    *item++ = prop->value;
+                    ret = njs_array_add(vm, items, &prop->value);
+                    if (njs_slow_path(ret != NJS_OK)) {
+                        return NJS_ERROR;
+                    }
                 }
             }
         }
@@ -1167,13 +1006,14 @@ njs_object_own_enumerate_object(njs_vm_t
                 }
 
                 njs_string_copy(&entry->start[0], &prop->name);
-
-                /* GC: retain. */
                 entry->start[1] = prop->value;
 
-                njs_set_array(item, entry);
-
-                item++;
+                njs_set_array(&value, entry);
+
+                ret = njs_array_add(vm, items, &value);
+                if (njs_slow_path(ret != NJS_OK)) {
+                    return NJS_ERROR;
+                }
             }
         }
 
@@ -1205,13 +1045,14 @@ njs_object_own_enumerate_object(njs_vm_t
                     }
 
                     njs_string_copy(&entry->start[0], &prop->name);
-
-                    /* GC: retain. */
                     entry->start[1] = prop->value;
 
-                    njs_set_array(item, entry);
-
-                    item++;
+                    njs_set_array(&value, entry);
+
+                    ret = njs_array_add(vm, items, &value);
+                    if (njs_slow_path(ret != NJS_OK)) {
+                        return NJS_ERROR;
+                    }
                 }
             }
         }
@@ -1219,8 +1060,6 @@ njs_object_own_enumerate_object(njs_vm_t
         break;
     }
 
-    items->start = item;
-
     return NJS_OK;
 }
 


More information about the nginx-devel mailing list