diff options
Diffstat (limited to 'src/njs_object.c')
-rw-r--r-- | src/njs_object.c | 240 |
1 files changed, 127 insertions, 113 deletions
diff --git a/src/njs_object.c b/src/njs_object.c index 63273628..7f0b1822 100644 --- a/src/njs_object.c +++ b/src/njs_object.c @@ -15,7 +15,7 @@ typedef enum { static njs_object_prop_t *njs_object_exist_in_proto(const njs_object_t *begin, - const njs_object_t *end, njs_flathsh_query_t *lhq); + const njs_object_t *end, njs_flathsh_query_t *fhq); static njs_int_t njs_object_enumerate_array(njs_vm_t *vm, const njs_array_t *array, njs_array_t *items, uint32_t flags); static njs_int_t njs_object_enumerate_typed_array(njs_vm_t *vm, @@ -41,8 +41,8 @@ njs_object_alloc(njs_vm_t *vm) object = njs_mp_alloc(vm->mem_pool, sizeof(njs_object_t)); if (njs_fast_path(object != NULL)) { - njs_lvlhsh_init(&object->hash); - njs_lvlhsh_init(&object->shared_hash); + njs_flathsh_init(&object->hash); + njs_flathsh_init(&object->shared_hash); object->__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_OBJECT); object->slots = NULL; object->type = NJS_OBJECT; @@ -126,13 +126,13 @@ njs_object_value_alloc(njs_vm_t *vm, njs_uint_t prototype_index, size_t extra, return NULL; } - njs_lvlhsh_init(&ov->object.hash); + njs_flathsh_init(&ov->object.hash); if (prototype_index == NJS_OBJ_TYPE_STRING) { ov->object.shared_hash = vm->shared->string_instance_hash; } else { - njs_lvlhsh_init(&ov->object.shared_hash); + njs_flathsh_init(&ov->object.shared_hash); } ov->object.type = NJS_OBJECT_VALUE; @@ -157,22 +157,31 @@ njs_object_hash_create(njs_vm_t *vm, njs_flathsh_t *hash, const njs_object_prop_init_t *prop, njs_uint_t n) { njs_int_t ret; - njs_flathsh_query_t lhq; + njs_object_prop_t *obj_prop; + njs_flathsh_query_t fhq; - lhq.replace = 0; - lhq.proto = &njs_object_hash_proto; - lhq.pool = vm->mem_pool; + fhq.replace = 0; + fhq.proto = &njs_object_hash_proto; + fhq.pool = vm->mem_pool; while (n != 0) { - lhq.key_hash = prop->atom_id; - lhq.value = (void *) prop; + fhq.key_hash = prop->desc.atom_id; + fhq.value = (void *) prop; - ret = njs_flathsh_unique_insert(hash, &lhq); + ret = njs_flathsh_unique_insert(hash, &fhq); if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); + njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } + obj_prop = fhq.value; + + obj_prop->type = prop->desc.type; + obj_prop->enumerable = prop->desc.enumerable; + obj_prop->configurable = prop->desc.configurable; + obj_prop->writable = prop->desc.writable; + obj_prop->u.value = prop->desc.u.value; + prop++; n--; } @@ -184,10 +193,9 @@ njs_object_hash_create(njs_vm_t *vm, njs_flathsh_t *hash, const njs_flathsh_proto_t njs_object_hash_proto njs_aligned(64) = { - 0, NULL, - njs_lvlhsh_alloc, - njs_lvlhsh_free, + njs_flathsh_proto_alloc, + njs_flathsh_proto_free, }; @@ -371,28 +379,28 @@ njs_object_entries(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, static njs_object_prop_t * njs_object_exist_in_proto(const njs_object_t *object, const njs_object_t *end, - njs_flathsh_query_t *lhq) + njs_flathsh_query_t *fhq) { njs_int_t ret; njs_object_prop_t *prop; while (object != end) { - ret = njs_flathsh_unique_find(&object->hash, lhq); + ret = njs_flathsh_unique_find(&object->hash, fhq); if (njs_fast_path(ret == NJS_OK)) { - prop = lhq->value; + prop = fhq->value; if (prop->type == NJS_WHITEOUT) { goto next; } - return lhq->value; + return fhq->value; } - ret = njs_flathsh_unique_find(&object->shared_hash, lhq); + ret = njs_flathsh_unique_find(&object->shared_hash, fhq); if (njs_fast_path(ret == NJS_OK)) { - return lhq->value; + return fhq->value; } next: @@ -910,7 +918,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, njs_flathsh_elt_t *elt; njs_flathsh_each_t lhe; const njs_flathsh_t *hash; - njs_flathsh_query_t lhq; + njs_flathsh_query_t fhq; items_length = items->length; @@ -924,7 +932,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, return NJS_ERROR; } - lhq.proto = &njs_object_hash_proto; + fhq.proto = &njs_object_hash_proto; njs_flathsh_each_init(&lhe, &njs_object_hash_proto); hash = &object->shared_hash; @@ -939,7 +947,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, break; } - prop = elt->value; + prop = (njs_object_prop_t *) elt; ret = njs_atom_to_value(vm, &prop_name, elt->key_hash); if (ret != NJS_OK) { @@ -950,14 +958,14 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, continue; } - lhq.key_hash = elt->key_hash; + fhq.key_hash = elt->key_hash; - ext_prop = njs_object_exist_in_proto(parent, object, &lhq); + ext_prop = njs_object_exist_in_proto(parent, object, &fhq); if (ext_prop != NULL) { continue; } - ret = njs_flathsh_unique_find(&object->hash, &lhq); + ret = njs_flathsh_unique_find(&object->hash, &fhq); if (ret != NJS_OK) { if (!(prop->enumerable || !(flags & NJS_ENUM_ENUMERABLE_ONLY))) { @@ -980,7 +988,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, } else { - if (!(((njs_object_prop_t *)(lhq.value))->enumerable + if (!(((njs_object_prop_t *) (fhq.value))->enumerable || !(flags & NJS_ENUM_ENUMERABLE_ONLY))) { continue; @@ -991,15 +999,9 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object, num = njs_string_to_index(&prop_name); if (!njs_number_is_integer_index(num)) { - njs_object_prop_t *hash_prop = lhq.value; + njs_object_prop_t *hash_prop = fhq.value; - /* select names of prop which are not deleted and - * not deleted and created again i.e., - * they are replaced shared hash props - */ - if (hash_prop->type != NJS_WHITEOUT && - !(hash_prop->enum_in_object_hash)) - { + if (hash_prop->type != NJS_WHITEOUT) { njs_process_prop(vm, &prop_name, flags, items_string, items_symbol); } @@ -1018,7 +1020,7 @@ local_hash: break; } - prop = elt->value; + prop = (njs_object_prop_t *) elt; ret = njs_atom_to_value(vm, &prop_name, elt->key_hash); if (ret != NJS_OK) { @@ -1032,9 +1034,9 @@ local_hash: continue; } - lhq.key_hash = elt->key_hash; + fhq.key_hash = elt->key_hash; - ext_prop = njs_object_exist_in_proto(parent, object, &lhq); + ext_prop = njs_object_exist_in_proto(parent, object, &fhq); if (ext_prop != NULL) { continue; } @@ -1049,7 +1051,7 @@ local_hash: } else { - ret = njs_flathsh_unique_find(&object->shared_hash, &lhq); + ret = njs_flathsh_unique_find(&object->shared_hash, &fhq); if (ret != NJS_OK) { /* prop is: in_hash && !in_shared_hash */ @@ -1060,8 +1062,7 @@ local_hash: } else { /* prop is: in_hash && in_shared_hash */ - /* select names of not deleted and created again */ - if (prop->enum_in_object_hash) { + if (prop->type == NJS_WHITEOUT) { njs_process_prop(vm, &prop_name, flags, items_string, items_symbol); } @@ -1222,7 +1223,7 @@ njs_object_copy_shared_hash(njs_vm_t *vm, njs_object_t *object) njs_int_t ret; njs_value_t prop_name; njs_flathsh_t new_hash, *shared_hash; - njs_object_prop_t *prop; + njs_object_prop_t *prop, *obj_prop; njs_flathsh_elt_t *elt; njs_flathsh_each_t fhe; njs_flathsh_query_t fhq; @@ -1242,7 +1243,7 @@ njs_object_copy_shared_hash(njs_vm_t *vm, njs_object_t *object) break; } - prop = elt->value; + prop = (njs_object_prop_t *) elt; ret = njs_atom_to_value(vm, &prop_name, elt->key_hash); if (ret != NJS_OK) { @@ -1258,13 +1259,19 @@ njs_object_copy_shared_hash(njs_vm_t *vm, njs_object_t *object) fhq.key_hash = elt->key_hash; } - fhq.value = prop; - ret = njs_flathsh_unique_insert(&new_hash, &fhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } + + obj_prop = fhq.value; + + obj_prop->type = prop->type; + obj_prop->enumerable = prop->enumerable; + obj_prop->configurable = prop->configurable; + obj_prop->writable = prop->writable; + obj_prop->u.value = prop->u.value; } object->shared_hash = new_hash; @@ -1281,7 +1288,7 @@ njs_object_make_shared(njs_vm_t *vm, njs_object_t *object) njs_object_t **start; njs_value_t value, *key; njs_traverse_t *s; - njs_object_prop_t *prop; + njs_object_prop_t *prop, *obj_prop; njs_property_query_t pq; njs_traverse_t state[NJS_TRAVERSE_MAX_DEPTH]; @@ -1318,8 +1325,8 @@ njs_object_make_shared(njs_vm_t *vm, njs_object_t *object) (void) njs_traverse_visit(&visited, &s->value); - pq.lhq.replace = 0; - pq.lhq.pool = vm->mem_pool; + pq.fhq.replace = 0; + pq.fhq.pool = vm->mem_pool; for ( ;; ) { @@ -1351,15 +1358,23 @@ njs_object_make_shared(njs_vm_t *vm, njs_object_t *object) } - prop = pq.lhq.value; + prop = pq.fhq.value; ret = njs_flathsh_unique_insert(&njs_object(&s->value)->shared_hash, - &pq.lhq); + &pq.fhq); if (njs_slow_path(ret != NJS_OK)) { njs_internal_error(vm, "flathsh insert failed"); return NJS_ERROR; } + obj_prop = pq.fhq.value; + + obj_prop->type = prop->type; + obj_prop->enumerable = prop->enumerable; + obj_prop->configurable = prop->configurable; + obj_prop->writable = prop->writable; + obj_prop->u.value = prop->u.value; + njs_value_assign(&value, njs_prop_value(prop)); if (njs_is_object(&value) @@ -1465,9 +1480,9 @@ njs_object_traverse(njs_vm_t *vm, njs_object_t *object, void *ctx, return NJS_ERROR; } - prop = pq.lhq.value; + prop = pq.fhq.value; s->prop = prop; - s->atom_id = pq.lhq.key_hash; + s->atom_id = pq.fhq.key_hash; ret = cb(vm, s, ctx); if (njs_slow_path(ret != NJS_OK)) { @@ -1481,7 +1496,7 @@ njs_object_traverse(njs_vm_t *vm, njs_object_t *object, void *ctx, njs_value_assign(&value, njs_prop_value(prop)); if (prop->type == NJS_PROPERTY_HANDLER) { - ret = njs_prop_handler(prop)(vm, prop, pq.lhq.key_hash, &s->value, + ret = njs_prop_handler(prop)(vm, prop, pq.fhq.key_hash, &s->value, NULL, &value); if (njs_slow_path(ret == NJS_ERROR)) { return ret; @@ -1601,7 +1616,7 @@ njs_object_define_properties(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto done; } - prop = pq.lhq.value; + prop = pq.fhq.value; if (ret == NJS_DECLINED || !prop->enumerable) { continue; @@ -1659,8 +1674,8 @@ njs_object_get_own_property_descriptors(njs_vm_t *vm, njs_value_t *args, njs_array_t *names; njs_value_t descriptor, *value, *key; njs_object_t *descriptors; - njs_object_prop_t *pr; - njs_flathsh_query_t lhq; + njs_object_prop_t *prop; + njs_flathsh_query_t fhq; value = njs_arg(args, nargs, 1); @@ -1685,9 +1700,9 @@ njs_object_get_own_property_descriptors(njs_vm_t *vm, njs_value_t *args, goto done; } - lhq.replace = 0; - lhq.pool = vm->mem_pool; - lhq.proto = &njs_object_hash_proto; + fhq.replace = 0; + fhq.pool = vm->mem_pool; + fhq.proto = &njs_object_hash_proto; for (i = 0; i < length; i++) { key = &names->start[i]; @@ -1697,20 +1712,22 @@ njs_object_get_own_property_descriptors(njs_vm_t *vm, njs_value_t *args, goto done; } - pr = njs_object_prop_alloc(vm, &descriptor, 1); - if (njs_slow_path(pr == NULL)) { - ret = NJS_ERROR; - goto done; - } - - lhq.key_hash = key->atom_id; - lhq.value = pr; + fhq.key_hash = key->atom_id; - ret = njs_flathsh_unique_insert(&descriptors->hash, &lhq); + ret = njs_flathsh_unique_insert(&descriptors->hash, &fhq); if (njs_slow_path(ret != NJS_OK)) { - njs_internal_error(vm, "lvlhsh insert failed"); + njs_internal_error(vm, "flathsh insert failed"); goto done; } + + prop = fhq.value; + + prop->type = NJS_PROPERTY; + prop->enumerable = 1; + prop->configurable = 1; + prop->writable = 1; + + prop->u.value = descriptor; } ret = NJS_OK; @@ -1889,7 +1906,7 @@ njs_object_set_integrity_level(njs_vm_t *vm, njs_value_t *args, break; } - prop = elt->value; + prop = (njs_object_prop_t *) elt; if (level == NJS_OBJECT_INTEGRITY_FROZEN && !njs_is_accessor_descriptor(prop)) @@ -1949,7 +1966,7 @@ njs_object_test_integrity_level(njs_vm_t *vm, njs_value_t *args, break; } - prop = elt->value; + prop = (njs_object_prop_t *) elt; if (prop->configurable) { goto done; @@ -2051,7 +2068,7 @@ njs_object_assign(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, goto exception; } - prop = pq.lhq.value; + prop = pq.fhq.value; if (!prop->enumerable) { continue; } @@ -2170,32 +2187,31 @@ njs_property_prototype_create(njs_vm_t *vm, njs_flathsh_t *hash, { njs_int_t ret; njs_object_prop_t *prop; - njs_flathsh_query_t lhq; - - prop = njs_object_prop_alloc(vm, &njs_value_undefined, 0); - if (njs_slow_path(prop == NULL)) { - return NULL; - } + njs_flathsh_query_t fhq; - lhq.value = prop; + fhq.key_hash = NJS_ATOM_STRING_prototype; - njs_set_type_object(njs_prop_value(prop), prototype, prototype->type); + fhq.replace = 1; + fhq.pool = vm->mem_pool; + fhq.proto = &njs_object_hash_proto; - lhq.key_hash = NJS_ATOM_STRING_prototype; + ret = njs_flathsh_unique_insert(hash, &fhq); - lhq.replace = 1; - lhq.pool = vm->mem_pool; - lhq.proto = &njs_object_hash_proto; + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert failed"); + return NULL; + } - ret = njs_flathsh_unique_insert(hash, &lhq); + prop = fhq.value; - if (njs_fast_path(ret == NJS_OK)) { - return njs_prop_value(prop); - } + prop->type = NJS_PROPERTY; + prop->enumerable = 0; + prop->configurable = 0; + prop->writable = 0; - njs_internal_error(vm, "lvlhsh insert failed"); + njs_set_type_object(njs_prop_value(prop), prototype, prototype->type); - return NULL; + return njs_prop_value(prop); } @@ -2431,32 +2447,30 @@ njs_property_constructor_set(njs_vm_t *vm, njs_flathsh_t *hash, { njs_int_t ret; njs_object_prop_t *prop; - njs_flathsh_query_t lhq; + njs_flathsh_query_t fhq; - prop = njs_object_prop_alloc(vm, constructor, 1); - if (njs_slow_path(prop == NULL)) { - return NULL; - } + fhq.key_hash = NJS_ATOM_STRING_constructor; - njs_value_assign(njs_prop_value(prop), constructor); - prop->enumerable = 0; - - lhq.value = prop; + fhq.replace = 1; + fhq.pool = vm->mem_pool; + fhq.proto = &njs_object_hash_proto; - lhq.key_hash = NJS_ATOM_STRING_constructor; + ret = njs_flathsh_unique_insert(hash, &fhq); + if (njs_slow_path(ret != NJS_OK)) { + njs_internal_error(vm, "flathsh insert/replace failed"); + return NULL; + } - lhq.replace = 1; - lhq.pool = vm->mem_pool; - lhq.proto = &njs_object_hash_proto; + prop = fhq.value; - ret = njs_flathsh_unique_insert(hash, &lhq); - if (njs_fast_path(ret == NJS_OK)) { - return njs_prop_value(prop); - } + prop->type = NJS_PROPERTY; + prop->enumerable = 0; + prop->configurable = 1; + prop->writable = 1; + prop->u.value = *constructor; - njs_internal_error(vm, "lvlhsh insert/replace failed"); + return njs_prop_value(prop); - return NULL; } @@ -2515,7 +2529,7 @@ njs_object_to_string(njs_vm_t *vm, njs_value_t *this, njs_value_t *retval) name = NJS_ATOM_STRING__object_Array_; } else if (njs_is_object(this) - && njs_lvlhsh_eq(&njs_object(this)->shared_hash, + && njs_flathsh_eq(&njs_object(this)->shared_hash, &vm->shared->arguments_object_instance_hash)) { name = NJS_ATOM_STRING__object_Arguments_; @@ -2656,7 +2670,7 @@ njs_object_prototype_prop_is_enumerable(njs_vm_t *vm, njs_value_t *args, switch (ret) { case NJS_OK: - prop = pq.lhq.value; + prop = pq.fhq.value; njs_set_boolean(retval, prop->enumerable); break; |