[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