The new hash takes 42% less memory per element.
}
}
- prop->type = NJS_PROPERTY;
- njs_set_number(njs_prop_value(prop), length);
+ ret = njs_array_length_redefine(vm, value, length, 1);
+ if (ret != NJS_OK) {
+ return ret;
+ }
njs_value_assign(retval, setval);
uint32_t hash)
{
njs_int_t ret;
- njs_value_t *entry;
+ njs_object_prop_t *prop;
njs_lvlhsh_query_t lhq;
lhq.key.start = key;
ret = njs_lvlhsh_find(vm->atom_hash_current, &lhq);
if (ret == NJS_OK) {
- return lhq.value;
+ return njs_prop_value(lhq.value);
}
ret = njs_lvlhsh_find(&vm->atom_hash_shared, &lhq);
if (ret == NJS_OK) {
- return lhq.value;
+ return njs_prop_value(lhq.value);
}
- entry = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t));
- if (njs_slow_path(entry == NULL)) {
+ lhq.pool = vm->mem_pool;
+
+ ret = njs_lvlhsh_insert(vm->atom_hash_current, &lhq);
+ if (njs_slow_path(ret != NJS_OK)) {
return NULL;
}
- ret = njs_string_create(vm, entry, key, size);
+ prop = lhq.value;
+
+ ret = njs_string_create(vm, &prop->u.value, key, size);
if (njs_slow_path(ret != NJS_OK)) {
return NULL;
}
- entry->string.atom_id = vm->atom_id_generator++;
- if (njs_atom_is_number(entry->string.atom_id)) {
+ prop->u.value.string.atom_id = vm->atom_id_generator++;
+ if (njs_atom_is_number(prop->u.value.string.atom_id)) {
njs_internal_error(vm, "too many atoms");
return NULL;
}
- entry->string.token_type = NJS_KEYWORD_TYPE_UNDEF;
+ prop->u.value.string.token_type = NJS_KEYWORD_TYPE_UNDEF;
+
+ return &prop->u.value;
+}
+
+
+static njs_value_t *
+njs_atom_find_or_add_string(njs_vm_t *vm, njs_value_t *value,
+ uint32_t hash)
+{
+ njs_int_t ret;
+ njs_object_prop_t *prop;
+ njs_lvlhsh_query_t lhq;
+
+ njs_assert(njs_is_string(value));
+
+ lhq.key.start = value->string.data->start;
+ lhq.key.length = value->string.data->size;
+ lhq.key_hash = hash;
+ lhq.proto = &njs_lexer_hash_proto;
+
+ ret = njs_lvlhsh_find(vm->atom_hash_current, &lhq);
+ if (ret == NJS_OK) {
+ return njs_prop_value(lhq.value);
+ }
+
+ ret = njs_lvlhsh_find(&vm->atom_hash_shared, &lhq);
+ if (ret == NJS_OK) {
+ return njs_prop_value(lhq.value);
+ }
- lhq.value = entry;
lhq.pool = vm->mem_pool;
ret = njs_lvlhsh_insert(vm->atom_hash_current, &lhq);
return NULL;
}
- return entry;
+ prop = lhq.value;
+
+ prop->u.value = *value;
+
+ prop->u.value.string.atom_id = vm->atom_id_generator++;
+ if (njs_atom_is_number(prop->u.value.string.atom_id)) {
+ njs_internal_error(vm, "too many atoms");
+ return NULL;
+ }
+
+ prop->u.value.string.token_type = NJS_KEYWORD_TYPE_UNDEF;
+
+ return &prop->u.value;
}
if (value->type == NJS_SYMBOL) {
lhq.key_hash = value->string.atom_id;
- lhq.value = (void *) value;
ret = njs_flathsh_insert(&vm->atom_hash_shared, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
lhq.key_hash = njs_djb_hash(start, len);
lhq.key.length = len;
lhq.key.start = start;
- lhq.value = (void *) value;
ret = njs_flathsh_insert(&vm->atom_hash_shared, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
return 0xffffffff;
}
}
+
+ *njs_prop_value(lhq.value) = *value;
}
vm->atom_hash_current = &vm->atom_hash_shared;
hash_id = njs_djb_hash(value->string.data->start,
value->string.data->size);
- entry = njs_atom_find_or_add(vm, value->string.data->start,
- value->string.data->size,
- value->string.data->length,
- hash_id);
+ entry = njs_atom_find_or_add_string(vm, value, hash_id);
if (njs_slow_path(entry == NULL)) {
return NJS_ERROR;
}
if (value->type == NJS_SYMBOL) {
lhq.key_hash = value->atom_id;
- lhq.value = (void *) value;
ret = njs_flathsh_insert(vm->atom_hash_current, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
njs_internal_error(vm, "flathsh insert/replace failed");
return NJS_ERROR;
}
+
+ *njs_prop_value(lhq.value) = *value;
}
return NJS_OK;
njs_buffer(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id,
njs_value_t *value, njs_value_t *unused, njs_value_t *retval)
{
- return njs_object_prop_init(vm, &njs_buffer_constructor_init, prop, atom_id,
- value, retval);
+ return njs_object_props_init(vm, &njs_buffer_constructor_init, prop,
+ atom_id, value, retval);
}
njs_buffer_constants(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t atom_id,
njs_value_t *value, njs_value_t *unused, njs_value_t *retval)
{
- return njs_object_prop_init(vm, &njs_buffer_constants_init, prop, atom_id,
- value, retval);
+ return njs_object_props_init(vm, &njs_buffer_constants_init, prop, atom_id,
+ value, retval);
}
/* NJS_BUILTIN_TRAVERSE_KEYS. */
- prop = njs_object_prop_alloc(vm, &njs_value_null, 0);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
ret = njs_atom_string_create(vm, &prop_name, buf, p - buf);
if (njs_slow_path(ret != NJS_OK)) {
return ret;
}
- lhq.value = prop;
lhq.key_hash = prop_name.atom_id;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
return NJS_ERROR;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 0;
+ prop->configurable = 0;
+ prop->writable = 0;
+ prop->u.value = njs_value_null;
+
return NJS_OK;
}
njs_uint_t i, n;
njs_value_t value, tag;
njs_object_t object;
+ njs_object_prop_t *prop;
njs_lvlhsh_each_t lhe;
njs_exotic_slots_t *slots;
njs_function_name_t *fn;
njs_lvlhsh_each_init(&lhe, &njs_modules_hash_proto);
for ( ;; ) {
- module = njs_lvlhsh_each(&vm->modules_hash, &lhe);
-
- if (module == NULL) {
+ prop = (njs_object_prop_t *) njs_flathsh_each(&vm->modules_hash, &lhe);
+ if (prop == NULL) {
break;
}
+ module = prop->u.mod;
+
if (njs_is_object(&module->value)
&& !njs_object(&module->value)->shared)
{
njs_value_assign(retval, setval);
}
- prop = njs_object_prop_alloc(vm, retval, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
- njs_value_assign(njs_prop_value(prop), retval);
- prop->enumerable = self->enumerable;
-
- lhq.value = prop;
lhq.key_hash = atom_id;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
return NJS_ERROR;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = self->enumerable;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = *retval;
+
return NJS_OK;
}
object->__proto__ = njs_vm_proto(vm, NJS_OBJ_TYPE_OBJECT);
}
- prop = njs_object_prop_alloc(vm, retval, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
- njs_value_assign(njs_prop_value(prop), retval);
- prop->enumerable = self->enumerable;
-
- lhq.value = prop;
lhq.key_hash = atom_id;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
return NJS_ERROR;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = self->enumerable;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = *retval;
+
return NJS_OK;
}
return NJS_OK;
}
- prop = njs_object_prop_alloc(vm, retval, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
- njs_value_assign(njs_prop_value(prop), retval);
- prop->enumerable = 0;
-
- lhq.value = prop;
lhq.key_hash = atom_id;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
return NJS_ERROR;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 0;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = *retval;
+
return NJS_OK;
}
}
}
- prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
- njs_set_array(njs_prop_value(prop), argv);
-
- lhq.value = prop;
lhq.key_hash = NJS_ATOM_STRING_argv;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
lhq.proto = &njs_object_hash_proto;
ret = njs_flathsh_unique_insert(njs_object_hash(process), &lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- njs_value_assign(retval, njs_prop_value(prop));
- return NJS_OK;
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
+ return NJS_ERROR;
}
- njs_internal_error(vm, "lvlhsh insert failed");
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+
+ njs_set_array(njs_prop_value(prop), argv);
+
+ njs_value_assign(retval, njs_prop_value(prop));
+ return NJS_OK;
- return NJS_ERROR;
}
ep = environment;
while (*ep != NULL) {
- prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
entry = (u_char *) *ep++;
val++;
- ret = njs_string_create(vm, njs_prop_value(prop), val, njs_strlen(val));
- if (njs_slow_path(ret != NJS_OK)) {
- return NJS_ERROR;
- }
-
ret = njs_atom_atomize_key(vm, &prop_name);
if (ret != NJS_OK) {
return ret;
}
- lhq.value = prop;
lhq.key_hash = prop_name.atom_id;
ret = njs_flathsh_unique_insert(hash, &lhq);
* Always using the first element among the duplicates
* and ignoring the rest.
*/
+ continue;
+ }
+
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+
+ ret = njs_string_create(vm, njs_prop_value(prop), val, njs_strlen(val));
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
}
}
env->shared_hash = vm->shared->env_hash;
- prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
- njs_set_object(njs_prop_value(prop), env);
-
lhq.replace = 1;
lhq.pool = vm->mem_pool;
lhq.proto = &njs_object_hash_proto;
- lhq.value = prop;
lhq.key_hash = NJS_ATOM_STRING_env;
ret = njs_flathsh_unique_insert(njs_object_hash(process), &lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- njs_value_assign(retval, njs_prop_value(prop));
- return NJS_OK;
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
+ return NJS_ERROR;
}
- njs_internal_error(vm, "lvlhsh insert failed");
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
- return NJS_ERROR;
+ njs_set_object(njs_prop_value(prop), env);
+
+ njs_value_assign(retval, njs_prop_value(prop));
+
+ return NJS_OK;
}
lhq.proto = &njs_object_hash_proto;
if (name != NULL) {
- prop = njs_object_prop_alloc(vm, name, 1);
- if (njs_slow_path(prop == NULL)) {
- goto memory_error;
- }
-
- lhq.value = prop;
lhq.key_hash = NJS_ATOM_STRING_name;
ret = njs_flathsh_unique_insert(&error->hash, &lhq);
njs_internal_error(vm, "lvlhsh insert failed");
return NULL;
}
- }
- if (message!= NULL) {
- prop = njs_object_prop_alloc(vm, message, 1);
- if (njs_slow_path(prop == NULL)) {
- goto memory_error;
- }
+ prop = lhq.value;
- prop->enumerable = 0;
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+
+ prop->u.value = *name;
+ }
- lhq.value = prop;
+ if (message!= NULL) {
lhq.key_hash = NJS_ATOM_STRING_message;
ret = njs_flathsh_unique_insert(&error->hash, &lhq);
njs_internal_error(vm, "lvlhsh insert failed");
return NULL;
}
- }
- if (errors != NULL) {
- prop = njs_object_prop_alloc(vm, errors, 1);
- if (njs_slow_path(prop == NULL)) {
- goto memory_error;
- }
+ prop = lhq.value;
+ prop->type = NJS_PROPERTY;
prop->enumerable = 0;
+ prop->configurable = 1;
+ prop->writable = 1;
- lhq.value = prop;
+ prop->u.value = *message;
+ }
+
+ if (errors != NULL) {
lhq.key_hash = NJS_ATOM_STRING_errors;
ret = njs_flathsh_unique_insert(&error->hash, &lhq);
njs_internal_error(vm, "lvlhsh insert failed");
return NULL;
}
+
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 0;
+ prop->configurable = 1;
+ prop->writable = 1;
+
+ prop->u.value = *errors;
}
return error;
continue;
}
- prop = njs_object_prop_alloc(vm, &njs_value_invalid, 1);
- if (njs_slow_path(prop == NULL)) {
- goto memory_error;
- }
-
- prop->writable = external->writable;
- prop->configurable = external->configurable;
- prop->enumerable = external->enumerable;
-
if (external->flags & NJS_EXTERN_SYMBOL) {
lhq.key_hash = external->name.symbol;
lhq.key_hash = prop_name.atom_id;
}
- lhq.value = prop;
+ ret = njs_flathsh_unique_insert(hash, &lhq);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
+ return NJS_ERROR;
+ }
+
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = external->enumerable;
+ prop->configurable = external->configurable;
+ prop->writable = external->writable;
+ prop->u.value = njs_value_invalid;
+
switch (external->flags & NJS_EXTERN_TYPE_MASK) {
case NJS_EXTERN_METHOD:
break;
}
- ret = njs_flathsh_unique_insert(hash, &lhq);
- if (njs_slow_path(ret != NJS_OK)) {
- njs_internal_error(vm, "lvlhsh insert failed");
- return NJS_ERROR;
- }
-
external++;
}
njs_set_object_value(retval, ov);
}
- prop = njs_object_prop_alloc(vm, retval, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
- prop->writable = self->writable;
- prop->configurable = self->configurable;
- prop->enumerable = self->enumerable;
-
- lhq.value = prop;
lhq.key_hash = atom_id;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
return NJS_ERROR;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = self->enumerable;
+ prop->configurable = self->configurable;
+ prop->writable = self->writable;
+
+ prop->u.value = *retval;
+
return NJS_OK;
}
elts = njs_hash_elts(h);
elt = &elts[h->elts_count++];
- elt->value = fhq->value;
elt->key_hash = fhq->key_hash;
cell_num = fhq->key_hash & h->hash_mask;
elt->next_elt = njs_hash_cells_end(h)[-cell_num - 1];
njs_hash_cells_end(h)[-cell_num - 1] = h->elts_count;
+ elt->type = NJS_PROPERTY;
+
return elt;
}
njs_memzero(chunk, sizeof(uint32_t) * new_hash_size);
for (i = 0, elt = njs_hash_elts(h); i < h->elts_count; i++, elt++) {
- if (elt->value != NULL) {
+ if (elt->type != NJS_FREE_FLATHSH_ELEMENT) {
cell_num = elt->key_hash & new_hash_mask;
elt->next_elt = njs_hash_cells_end(h)[-cell_num - 1];
njs_hash_cells_end(h)[-cell_num - 1] = i + 1;
if (e->key_hash == fhq->key_hash &&
fhq->proto->test(fhq, e->value) == NJS_OK)
{
- fhq->value = e->value;
+ fhq->value = e;
return NJS_OK;
}
e = &elts[elt_num - 1];
if (e->key_hash == fhq->key_hash) {
- fhq->value = e->value;
+ fhq->value = e;
return NJS_OK;
}
fhq->proto->test(fhq, elt->value) == NJS_OK)
{
if (fhq->replace) {
- elt->value = fhq->value;
-
+ fhq->value = elt;
return NJS_OK;
} else {
return NJS_ERROR;
}
- elt->value = fhq->value;
+ fhq->value = elt;
return NJS_OK;
}
njs_int_t
njs_flathsh_unique_insert(njs_flathsh_t *fh, njs_flathsh_query_t *fhq)
{
- void *tmp;
njs_int_t cell_num, elt_num;
njs_flathsh_elt_t *elt, *elts;
njs_flathsh_descr_t *h;
if (elt->key_hash == fhq->key_hash) {
if (fhq->replace) {
- tmp = fhq->value;
- fhq->value = elt->value;
- elt->value = tmp;
-
+ fhq->value = elt;
return NJS_OK;
} else {
- fhq->value = elt->value;
-
return NJS_DECLINED;
}
}
return NJS_ERROR;
}
- elt->value = fhq->value;
+ fhq->value = elt;
return NJS_OK;
}
elt_src = njs_hash_elts(h_src);
for (i = 0, j = 0, elt = njs_hash_elts(h); i < h->elts_count; i++) {
- if (elt_src->value != NULL) {
- elt->value = elt_src->value;
+ if (elt_src->type != NJS_FREE_FLATHSH_ELEMENT) {
+ *elt = *elt_src;
elt->key_hash = elt_src->key_hash;
cell_num = elt_src->key_hash & new_hash_mask;
if (elt->key_hash == fhq->key_hash &&
fhq->proto->test(fhq, elt->value) == NJS_OK)
{
- fhq->value = elt->value;
+ fhq->value = elt;
if (elt_prev != NULL) {
elt_prev->next_elt = elt->next_elt;
h->elts_deleted_count++;
- elt->value = NULL;
+ elt->type = NJS_FREE_FLATHSH_ELEMENT;
/* Shrink elts if elts_deleted_count is eligible. */
elt = &elts[elt_num - 1];
if (elt->key_hash == fhq->key_hash) {
- fhq->value = elt->value;
+ fhq->value = elt;
if (elt_prev != NULL) {
elt_prev->next_elt = elt->next_elt;
h->elts_deleted_count++;
- elt->value = NULL;
+ elt->type = NJS_FREE_FLATHSH_ELEMENT;
/* Shrink elts if elts_deleted_count is eligible. */
while (fhe->cp < h->elts_count) {
e = &elt[fhe->cp++];
- if (e->value != NULL) {
+ if (e->type != NJS_FREE_FLATHSH_ELEMENT) {
return e;
}
}
typedef struct {
- uint32_t next_elt;
+ /* next_elt + property descriptor : 32 bits */
+
+ uint32_t next_elt:26;
+
+ uint32_t type:3;
+ uint32_t writable:1;
+ uint32_t enumerable:1;
+ uint32_t configurable:1;
+
uint32_t key_hash;
- void *value;
+
+ void *value[16 / sizeof(void *)];
} njs_flathsh_elt_t;
#define njs_lvlhsh_delete(lh, lhq) njs_flathsh_delete(lh, lhq)
#define njs_lvlhsh_each_init(lhe, _proto) njs_flathsh_each_init(lhe, _proto)
-njs_inline void *
+njs_inline njs_flathsh_elt_t *
njs_lvlhsh_each(const njs_flathsh_t *lh, njs_flathsh_each_t *lhe)
{
njs_flathsh_elt_t *e;
return NULL;
}
- return e->value;
+ return e;
}
njs_object_prop_t *prop;
njs_flathsh_query_t lhq;
- prop = njs_object_prop_alloc(vm, name, 0);
- if (njs_slow_path(prop == NULL)) {
+ lhq.key_hash = NJS_ATOM_STRING_name;
+ lhq.replace = 0;
+ lhq.pool = vm->mem_pool;
+ lhq.proto = &njs_object_hash_proto;
+
+ ret = njs_flathsh_unique_insert(&function->object.hash, &lhq);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
return NJS_ERROR;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 0;
+ prop->configurable = 1;
+ prop->writable = 0;
+ prop->u.value = *name;
+
symbol = 0;
if (njs_is_symbol(njs_prop_value(prop))) {
}
}
- prop->configurable = 1;
-
- lhq.value = prop;
- lhq.key_hash = NJS_ATOM_STRING_name;
- lhq.replace = 0;
- lhq.pool = vm->mem_pool;
- lhq.proto = &njs_object_hash_proto;
-
- ret = njs_flathsh_unique_insert(&function->object.hash, &lhq);
- if (njs_slow_path(ret != NJS_OK)) {
- njs_internal_error(vm, "lvlhsh insert failed");
- return NJS_ERROR;
- }
-
return NJS_OK;
}
const njs_object_prop_init_t njs_arguments_object_instance_properties[] =
{
{
- .atom_id = NJS_ATOM_STRING_callee,
.desc = {
+ .atom_id = NJS_ATOM_STRING_callee,
.type = NJS_ACCESSOR,
.u.accessor = njs_accessor(njs_function_prototype_thrower, 0,
njs_function_prototype_thrower, 0),
- .writable = NJS_ATTRIBUTE_UNSET,
+ .writable = 0,
},
},
};
njs_object_prop_t *prop;
njs_flathsh_query_t lhq;
- prop = njs_object_prop_alloc(vm, prototype, 0);
- if (njs_slow_path(prop == NULL)) {
- return NULL;
- }
-
- prop->writable = 1;
-
- lhq.value = prop;
lhq.key_hash = NJS_ATOM_STRING_prototype;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
ret = njs_flathsh_unique_insert(hash, &lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- return njs_prop_value(prop);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
+ return NULL;
}
- njs_internal_error(vm, "lvlhsh insert failed");
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 0;
+ prop->configurable = 0;
+ prop->writable = 1;
+ prop->u.value = *prototype;
+
+ return njs_prop_value(prop);
- return NULL;
}
NJS_DECLARE_PROP_NATIVE(STRING_bind, njs_function_prototype_bind, 1, 0),
{
- .atom_id = NJS_ATOM_STRING_caller,
.desc = {
+ .atom_id = NJS_ATOM_STRING_caller,
.type = NJS_ACCESSOR,
.u.accessor = njs_accessor(njs_function_prototype_thrower, 0,
njs_function_prototype_thrower, 0),
- .writable = NJS_ATTRIBUTE_UNSET,
+ .writable = 0,
.configurable = 1,
},
},
{
- .atom_id = NJS_ATOM_STRING_arguments,
.desc = {
+ .atom_id = NJS_ATOM_STRING_arguments,
.type = NJS_ACCESSOR,
.u.accessor = njs_accessor(njs_function_prototype_thrower, 0,
njs_function_prototype_thrower, 0),
- .writable = NJS_ATTRIBUTE_UNSET,
+ .writable = 0,
.configurable = 1,
},
},
return NULL;
}
- prop = njs_object_prop_alloc(ctx->vm, &prop_value, 1);
- if (njs_slow_path(prop == NULL)) {
- goto memory_error;
- }
-
- lhq.value = prop;
lhq.key_hash = prop_name.atom_id;
lhq.replace = 1;
lhq.pool = ctx->pool;
return NULL;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = prop_value;
+
p = njs_json_skip_space(p, ctx->end);
if (njs_slow_path(p == ctx->end)) {
goto error_end;
wrapper->type = NJS_OBJECT;
wrapper->data.truth = 1;
- prop = njs_object_prop_alloc(vm, value, 1);
- if (njs_slow_path(prop == NULL)) {
- return NULL;
- }
-
- lhq.value = prop;
lhq.key_hash = NJS_ATOM_STRING_empty;
lhq.replace = 0;
lhq.pool = vm->mem_pool;
return NULL;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = *value;
+
return wrapper->data.u.object;
}
{
njs_mod_t *module;
- module = data;
+ module = *(njs_mod_t **) data;
if (njs_strstr_eq(&lhq->key, &module->name)) {
return NJS_OK;
njs_int_t ret;
njs_mod_t *shrd, *module;
njs_object_t *object;
+ njs_object_prop_t *prop;
njs_lvlhsh_query_t lhq;
lhq.key = *name;
lhq.proto = &njs_modules_hash_proto;
if (njs_lvlhsh_find(&vm->modules_hash, &lhq) == NJS_OK) {
- return lhq.value;
+ return njs_prop_module(lhq.value);
}
if (njs_lvlhsh_find(&vm->shared->modules_hash, &lhq) == NJS_OK) {
- shrd = lhq.value;
+ shrd = njs_prop_module(lhq.value);
if (shared) {
return shrd;
}
lhq.replace = 0;
- lhq.value = module;
lhq.pool = vm->mem_pool;
ret = njs_lvlhsh_insert(&vm->modules_hash, &lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- return module;
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NULL;
}
+
+ prop = lhq.value;
+
+ prop->u.mod = module;
+
+ return module;
+
}
return NULL;
{
njs_int_t ret;
njs_mod_t *module;
+ njs_object_prop_t *prop;
njs_lvlhsh_query_t lhq;
module = njs_mp_zalloc(vm->mem_pool, sizeof(njs_mod_t));
lhq.replace = 0;
lhq.key = *name;
lhq.key_hash = njs_djb_hash(name->start, name->length);
- lhq.value = module;
lhq.pool = vm->mem_pool;
lhq.proto = &njs_modules_hash_proto;
return NULL;
}
+ prop = lhq.value;
+
+ prop->u.mod = module;
+
if (value != NULL) {
njs_value_assign(&module->value, value);
module->function.native = 1;
const njs_object_prop_init_t *prop, njs_uint_t n)
{
njs_int_t ret;
+ njs_object_prop_t *obj_prop;
njs_flathsh_query_t lhq;
lhq.replace = 0;
lhq.pool = vm->mem_pool;
while (n != 0) {
- lhq.key_hash = prop->atom_id;
+ lhq.key_hash = prop->desc.atom_id;
lhq.value = (void *) prop;
ret = njs_flathsh_unique_insert(hash, &lhq);
return NJS_ERROR;
}
+ obj_prop = lhq.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--;
}
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) {
} else {
- if (!(((njs_object_prop_t *)(lhq.value))->enumerable
+ if (!(((njs_object_prop_t *) (lhq.value))->enumerable
|| !(flags & NJS_ENUM_ENUMERABLE_ONLY)))
{
continue;
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) {
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;
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) {
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;
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];
return NJS_ERROR;
}
+ obj_prop = pq.lhq.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)
njs_array_t *names;
njs_value_t descriptor, *value, *key;
njs_object_t *descriptors;
- njs_object_prop_t *pr;
+ njs_object_prop_t *prop;
njs_flathsh_query_t lhq;
value = njs_arg(args, nargs, 1);
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;
ret = njs_flathsh_unique_insert(&descriptors->hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
njs_internal_error(vm, "lvlhsh insert failed");
goto done;
}
+
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+
+ prop->u.value = descriptor;
}
ret = NJS_OK;
break;
}
- prop = elt->value;
+ prop = (njs_object_prop_t *) elt;
if (level == NJS_OBJECT_INTEGRITY_FROZEN
&& !njs_is_accessor_descriptor(prop))
break;
}
- prop = elt->value;
+ prop = (njs_object_prop_t *) elt;
if (prop->configurable) {
goto done;
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;
- }
-
- lhq.value = prop;
-
- njs_set_type_object(njs_prop_value(prop), prototype, prototype->type);
-
lhq.key_hash = NJS_ATOM_STRING_prototype;
lhq.replace = 1;
ret = njs_flathsh_unique_insert(hash, &lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- return njs_prop_value(prop);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
+ return NULL;
}
- njs_internal_error(vm, "lvlhsh insert failed");
+ prop = lhq.value;
- return NULL;
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 0;
+ prop->configurable = 0;
+ prop->writable = 0;
+
+ njs_set_type_object(njs_prop_value(prop), prototype, prototype->type);
+
+ return njs_prop_value(prop);
}
njs_object_prop_t *prop;
njs_flathsh_query_t lhq;
- prop = njs_object_prop_alloc(vm, constructor, 1);
- if (njs_slow_path(prop == NULL)) {
- return NULL;
- }
-
- prop->enumerable = 0;
-
- lhq.value = prop;
-
lhq.key_hash = NJS_ATOM_STRING_constructor;
lhq.replace = 1;
lhq.proto = &njs_object_hash_proto;
ret = njs_flathsh_unique_insert(hash, &lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- return njs_prop_value(prop);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert/replace failed");
+ return NULL;
}
- njs_internal_error(vm, "lvlhsh insert/replace failed");
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 0;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = *constructor;
+
+ return njs_prop_value(prop);
- return NULL;
}
njs_int_t njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t *pq,
njs_object_t *proto);
-njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm,
- const njs_value_t *value, uint8_t attributes);
+void njs_object_prop_init(njs_object_prop_t *prop, njs_object_prop_type_t type,
+ uint8_t attributes);
njs_int_t njs_object_property(njs_vm_t *vm, njs_object_t *object,
njs_flathsh_query_t *lhq, njs_value_t *retval);
njs_object_prop_t *njs_object_property_add(njs_vm_t *vm, njs_value_t *object,
njs_int_t njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused, njs_value_t *retval);
const char *njs_prop_type_string(njs_object_prop_type_t type);
-njs_int_t njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init,
+njs_int_t njs_object_props_init(njs_vm_t *vm, const njs_object_init_t* init,
njs_object_prop_t *base, uint32_t atom_id, njs_value_t *value,
njs_value_t *retval);
njs_inline njs_bool_t
njs_is_data_descriptor(njs_object_prop_t *prop)
{
- return prop->writable != NJS_ATTRIBUTE_UNSET
- || (prop->type != NJS_ACCESSOR && njs_is_valid(njs_prop_value(prop)))
+ return (prop->type == NJS_PROPERTY && njs_is_valid(njs_prop_value(prop)))
+ || prop->type == NJS_PROPERTY_REF
+ || prop->type == NJS_PROPERTY_PLACE_REF
|| prop->type == NJS_PROPERTY_HANDLER;
-
}
}
-njs_inline njs_bool_t
-njs_is_generic_descriptor(njs_object_prop_t *prop)
-{
- return !njs_is_data_descriptor(prop) && !njs_is_accessor_descriptor(prop);
-}
-
-
njs_inline njs_int_t
njs_primitive_value_to_key(njs_vm_t *vm, njs_value_t *dst,
const njs_value_t *src)
#include <njs_main.h>
-static njs_object_prop_t *njs_object_prop_alloc2(njs_vm_t *vm,
- njs_object_prop_type_t type, unsigned flags);
static njs_object_prop_t *njs_descriptor_prop(njs_vm_t *vm,
- const njs_value_t *desc);
+ const njs_value_t *desc, njs_object_prop_t *prop,
+ uint32_t *unset_enumerable, uint32_t *unset_configuarble,
+ uint32_t *enum_writable);
-njs_object_prop_t *
-njs_object_prop_alloc(njs_vm_t *vm,
- const njs_value_t *value, uint8_t attributes)
-{
- unsigned flags;
- njs_object_prop_t *prop;
-
- switch (attributes) {
- case NJS_ATTRIBUTE_FALSE:
- case NJS_ATTRIBUTE_TRUE:
- flags = attributes ? NJS_OBJECT_PROP_VALUE_ECW : 0;
- break;
-
- case NJS_ATTRIBUTE_UNSET:
- default:
- flags = NJS_OBJECT_PROP_UNSET;
- break;
- }
-
- prop = njs_object_prop_alloc2(vm, NJS_PROPERTY, flags);
- if (njs_slow_path(prop == NULL)) {
- return NULL;
- }
-
- njs_value_assign(njs_prop_value(prop), value);
-
- return prop;
-}
-
-
-static njs_object_prop_t *
-njs_object_prop_alloc2(njs_vm_t *vm,
- njs_object_prop_type_t type, unsigned flags)
+void
+njs_object_prop_init(njs_object_prop_t *prop, njs_object_prop_type_t type,
+ uint8_t flags)
{
- njs_object_prop_t *prop;
-
- prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t),
- sizeof(njs_object_prop_t));
- if (njs_slow_path(prop == NULL)) {
- njs_memory_error(vm);
- return NULL;
- }
+ prop->next_elt = 0;
+ prop->atom_id = 0;
prop->type = type;
prop->writable = !!(flags & NJS_OBJECT_PROP_WRITABLE);
} else {
- prop->writable = NJS_ATTRIBUTE_UNSET;
+ prop->writable = 0;
}
} else {
- prop->enumerable = NJS_ATTRIBUTE_UNSET;
- prop->configurable = NJS_ATTRIBUTE_UNSET;
- prop->writable = NJS_ATTRIBUTE_UNSET;
+ prop->enumerable = 0;
+ prop->configurable = 0;
+ prop->writable = 0;
}
-
- return prop;
}
njs_object_prop_t *prop;
njs_flathsh_query_t lhq;
- prop = njs_object_prop_alloc(vm, &njs_value_invalid, 1);
- if (njs_slow_path(prop == NULL)) {
- return NULL;
- }
-
- lhq.value = prop;
lhq.key_hash = atom_id;
lhq.replace = replace;
lhq.pool = vm->mem_pool;
return NULL;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = njs_value_invalid;
+
return prop;
}
njs_object_prop_define(njs_vm_t *vm, njs_value_t *object, unsigned atom_id,
njs_value_t *value, unsigned flags)
{
- uint32_t length, index;
+ uint32_t length, index, set_enumerable, set_configurable,
+ set_writable;
njs_int_t ret;
njs_array_t *array;
njs_value_t key, retval;
- njs_object_prop_t *prop, *prev;
+ njs_object_prop_t _prop;
+ njs_object_prop_t *prop = &_prop, *prev, *obj_prop;
njs_property_query_t pq;
again:
+ set_enumerable = 1;
+ set_configurable = 1;
+ set_writable = 1;
+
njs_property_query_init(&pq, NJS_PROPERTY_QUERY_SET, 1);
ret = (flags & NJS_OBJECT_PROP_CREATE)
switch (njs_prop_type(flags)) {
case NJS_OBJECT_PROP_DESCRIPTOR:
- prop = njs_descriptor_prop(vm, value);
+ prop = njs_descriptor_prop(vm, value, prop, &set_enumerable,
+ &set_configurable, &set_writable);
if (njs_slow_path(prop == NULL)) {
return NJS_ERROR;
}
}
}
- prop = njs_object_prop_alloc2(vm, NJS_PROPERTY,
- flags & NJS_OBJECT_PROP_VALUE_ECW);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
+ njs_object_prop_init(prop, NJS_PROPERTY,
+ flags & NJS_OBJECT_PROP_VALUE_ECW);
njs_value_assign(njs_prop_value(prop), value);
break;
default:
njs_assert(njs_is_function(value));
- prop = njs_object_prop_alloc2(vm, NJS_ACCESSOR,
- NJS_OBJECT_PROP_VALUE_EC);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
+ njs_object_prop_init(prop, NJS_ACCESSOR, NJS_OBJECT_PROP_VALUE_EC);
+
+ set_writable = 0;
if (njs_prop_type(flags) == NJS_OBJECT_PROP_GETTER) {
njs_prop_getter(prop) = njs_function(value);
}
} else {
- if (prop->writable == NJS_ATTRIBUTE_UNSET) {
+ if (!set_writable) {
prop->writable = 0;
}
}
}
- if (prop->enumerable == NJS_ATTRIBUTE_UNSET) {
+ if (!set_enumerable) {
prop->enumerable = 0;
}
- if (prop->configurable == NJS_ATTRIBUTE_UNSET) {
+ if (!set_configurable) {
prop->configurable = 0;
}
if (njs_slow_path(prev->type == NJS_WHITEOUT)) {
/* Previously deleted property. */
+ prop->atom_id = prev->atom_id;
+ prop->next_elt = prev->next_elt;
*prev = *prop;
}
pq.lhq.key_hash = atom_id;
pq.lhq.proto = &njs_object_hash_proto;
- pq.lhq.value = prop;
pq.lhq.replace = 0;
pq.lhq.pool = vm->mem_pool;
njs_internal_error(vm, "lvlhsh insert failed");
return NJS_ERROR;
}
+
+ obj_prop = pq.lhq.value;
+ obj_prop->enumerable = prop->enumerable;
+ obj_prop->configurable = prop->configurable;
+ obj_prop->writable = prop->writable;
+ obj_prop->type = prop->type;
+ obj_prop->u.value = prop->u.value;
}
return NJS_OK;
case NJS_PROPERTY_PLACE_REF:
if (prev->type == NJS_PROPERTY_REF
&& !njs_is_accessor_descriptor(prop)
- && prop->configurable != NJS_ATTRIBUTE_FALSE
- && prop->enumerable != NJS_ATTRIBUTE_FALSE
- && prop->writable != NJS_ATTRIBUTE_FALSE)
+ && (!set_configurable || prop->configurable)
+ && (!set_enumerable || prop->enumerable)
+ && (!set_writable || prop->writable))
{
if (njs_is_valid(njs_prop_value(prop))) {
njs_value_assign(njs_prop_ref(prev), njs_prop_value(prop));
goto exception;
}
- if (prop->configurable == NJS_ATTRIBUTE_TRUE ||
- prop->enumerable == NJS_ATTRIBUTE_FALSE ||
- prop->writable == NJS_ATTRIBUTE_FALSE)
+ if ((set_configurable && prop->configurable)
+ || (set_enumerable && !prop->enumerable)
+ || (set_writable && !prop->writable))
{
goto exception;
}
if (!prev->configurable) {
- if (prop->configurable == NJS_ATTRIBUTE_TRUE) {
+ if (prop->configurable) {
goto exception;
}
- if (prop->enumerable != NJS_ATTRIBUTE_UNSET
- && prev->enumerable != prop->enumerable)
- {
+ if (set_enumerable && prev->enumerable != prop->enumerable) {
goto exception;
}
}
- if (njs_is_generic_descriptor(prop)) {
+ if (!(set_writable || njs_is_data_descriptor(prop))
+ && !njs_is_accessor_descriptor(prop))
+ {
goto done;
}
- if (njs_is_data_descriptor(prev) != njs_is_data_descriptor(prop)) {
+ if (njs_is_data_descriptor(prev)
+ != (set_writable || njs_is_data_descriptor(prop)))
+ {
if (!prev->configurable) {
goto exception;
}
}
if (njs_is_data_descriptor(prev)) {
- prev->writable = NJS_ATTRIBUTE_UNSET;
+ set_writable = 0;
njs_prop_getter(prev) = NULL;
njs_prop_setter(prev) = NULL;
} else {
- prev->writable = NJS_ATTRIBUTE_FALSE;
+ prev->writable = 0;
njs_set_undefined(njs_prop_value(prev));
}
prev->type = prop->type;
} else if (njs_is_data_descriptor(prev)
- && njs_is_data_descriptor(prop))
+ && (set_writable || njs_is_data_descriptor(prop)))
{
if (!prev->configurable && !prev->writable) {
- if (prop->writable == NJS_ATTRIBUTE_TRUE) {
+ if (prop->writable) {
goto exception;
}
if (njs_slow_path(njs_is_fast_array(object)
&& pq.lhq.key_hash == NJS_ATOM_STRING_length)
- && prop->writable == NJS_ATTRIBUTE_FALSE)
+ && (set_writable && !prop->writable))
{
array = njs_array(object);
length = array->length;
if (njs_slow_path(njs_is_array(object)
&& pq.lhq.key_hash == NJS_ATOM_STRING_length))
{
- if (prev->configurable != NJS_ATTRIBUTE_TRUE
- && prev->writable != NJS_ATTRIBUTE_TRUE
+ if (!prev->configurable
+ && !prev->writable
&& !njs_values_strict_equal(vm, njs_prop_value(prev),
njs_prop_value(prop)))
{
return NJS_ERROR;
}
- if (prop->writable != NJS_ATTRIBUTE_UNSET) {
+ if (set_writable) {
prev->writable = prop->writable;
}
* attribute of the property named P of object O to the value of the field.
*/
- if (prop->writable != NJS_ATTRIBUTE_UNSET) {
+ if (set_writable) {
prev->writable = prop->writable;
}
- if (prop->enumerable != NJS_ATTRIBUTE_UNSET) {
+ if (set_enumerable) {
prev->enumerable = prop->enumerable;
}
- if (prop->configurable != NJS_ATTRIBUTE_UNSET) {
+ if (set_configurable) {
prev->configurable = prop->configurable;
}
njs_function_t *function;
njs_object_prop_t *prop, *shared;
- prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t),
- sizeof(njs_object_prop_t));
- if (njs_slow_path(prop == NULL)) {
- njs_memory_error(vm);
- return NJS_ERROR;
- }
-
shared = pq->lhq.value;
- *prop = *shared;
pq->lhq.replace = 0;
- pq->lhq.value = prop;
pq->lhq.pool = vm->mem_pool;
ret = njs_flathsh_unique_insert(&proto->hash, &pq->lhq);
return NJS_ERROR;
}
+ prop = pq->lhq.value;
+ prop->enumerable = shared->enumerable;
+ prop->configurable = shared->configurable;
+ prop->writable = shared->writable;
+ prop->type = shared->type;
+ prop->u.value = shared->u.value;
+
if (njs_is_accessor_descriptor(prop)) {
if (njs_prop_getter(prop) != NULL) {
function = njs_function_copy(vm, njs_prop_getter(prop));
static njs_object_prop_t *
-njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc)
+njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc,
+ njs_object_prop_t *prop, uint32_t *set_enumerable,
+ uint32_t *set_configurable, uint32_t *set_writable)
{
njs_int_t ret;
njs_bool_t data, accessor;
njs_value_t value;
njs_object_t *desc_object;
njs_function_t *getter, *setter;
- njs_object_prop_t *prop;
njs_flathsh_query_t lhq;
if (!njs_is_object(desc)) {
return NULL;
}
- prop = njs_object_prop_alloc(vm, &njs_value_invalid,
- NJS_ATTRIBUTE_UNSET);
- if (njs_slow_path(prop == NULL)) {
- return NULL;
- }
+ njs_object_prop_init(prop, NJS_PROPERTY, NJS_OBJECT_PROP_UNSET);
+ *njs_prop_value(prop) = njs_value_invalid;
+
+ *set_enumerable = 0;
+ *set_configurable = 0;
+ *set_writable = 0;
data = 0;
accessor = 0;
if (ret == NJS_OK) {
data = 1;
prop->writable = njs_is_true(&value);
+ *set_writable = 1;
}
if (accessor && data) {
if (ret == NJS_OK) {
prop->enumerable = njs_is_true(&value);
+ *set_enumerable = 1;
}
lhq.key_hash = NJS_ATOM_STRING_configurable;
if (ret == NJS_OK) {
prop->configurable = njs_is_true(&value);
+ *set_configurable = 1;
}
if (accessor) {
if (njs_is_data_descriptor(prop)) {
lhq.key_hash = NJS_ATOM_STRING_value;
- pr = njs_object_prop_alloc(vm, njs_prop_value(prop), 1);
- if (njs_slow_path(pr == NULL)) {
- return NJS_ERROR;
- }
-
- lhq.value = pr;
-
ret = njs_flathsh_unique_insert(&desc->hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
njs_internal_error(vm, "lvlhsh insert failed");
return NJS_ERROR;
}
- lhq.key_hash = NJS_ATOM_STRING_writable;
+ pr = lhq.value;
- setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false;
+ pr->type = NJS_PROPERTY;
+ pr->enumerable = 1;
+ pr->configurable = 1;
+ pr->writable = 1;
+ pr->u.value = *(njs_prop_value(prop));
- pr = njs_object_prop_alloc(vm, setval, 1);
- if (njs_slow_path(pr == NULL)) {
- return NJS_ERROR;
- }
+ lhq.key_hash = NJS_ATOM_STRING_writable;
- lhq.value = pr;
+ setval = (prop->writable == 1) ? &njs_value_true : &njs_value_false;
ret = njs_flathsh_unique_insert(&desc->hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
+ pr = lhq.value;
+
+ pr->type = NJS_PROPERTY;
+ pr->enumerable = 1;
+ pr->configurable = 1;
+ pr->writable = 1;
+ pr->u.value = *setval;
+
} else {
lhq.key_hash = NJS_ATOM_STRING_get;
- pr = njs_object_prop_alloc(vm, &njs_value_undefined, 1);
- if (njs_slow_path(pr == NULL)) {
+ ret = njs_flathsh_unique_insert(&desc->hash, &lhq);
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
return NJS_ERROR;
}
+ pr = lhq.value;
+
+ pr->type = NJS_PROPERTY;
+ pr->enumerable = 1;
+ pr->configurable = 1;
+ pr->writable = 1;
+ pr->u.value = njs_value_undefined;
+
if (njs_prop_getter(prop) != NULL) {
njs_set_function(njs_prop_value(pr), njs_prop_getter(prop));
}
- lhq.value = pr;
+ lhq.key_hash = NJS_ATOM_STRING_set;
ret = njs_flathsh_unique_insert(&desc->hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
- lhq.key_hash = NJS_ATOM_STRING_set;
+ pr = lhq.value;
- pr = njs_object_prop_alloc(vm, &njs_value_undefined, 1);
- if (njs_slow_path(pr == NULL)) {
- return NJS_ERROR;
- }
+ pr->type = NJS_PROPERTY;
+ pr->enumerable = 1;
+ pr->configurable = 1;
+ pr->writable = 1;
+ pr->u.value = njs_value_undefined;
if (njs_prop_setter(prop) != NULL) {
njs_set_function(njs_prop_value(pr), njs_prop_setter(prop));
}
-
- lhq.value = pr;
-
- ret = njs_flathsh_unique_insert(&desc->hash, &lhq);
- if (njs_slow_path(ret != NJS_OK)) {
- njs_internal_error(vm, "lvlhsh insert failed");
- return NJS_ERROR;
- }
}
lhq.key_hash = NJS_ATOM_STRING_enumerable;
setval = (prop->enumerable == 1) ? &njs_value_true : &njs_value_false;
- pr = njs_object_prop_alloc(vm, setval, 1);
- if (njs_slow_path(pr == NULL)) {
- return NJS_ERROR;
- }
-
- lhq.value = pr;
-
ret = njs_flathsh_unique_insert(&desc->hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
njs_internal_error(vm, "lvlhsh insert failed");
return NJS_ERROR;
}
- lhq.key_hash = NJS_ATOM_STRING_configurable;
+ pr = lhq.value;
- setval = (prop->configurable == 1) ? &njs_value_true : &njs_value_false;
+ pr->type = NJS_PROPERTY;
+ pr->enumerable = 1;
+ pr->configurable = 1;
+ pr->writable = 1;
+ pr->u.value = *setval;
- pr = njs_object_prop_alloc(vm, setval, 1);
- if (njs_slow_path(pr == NULL)) {
- return NJS_ERROR;
- }
+ lhq.key_hash = NJS_ATOM_STRING_configurable;
- lhq.value = pr;
+ setval = (prop->configurable == 1) ? &njs_value_true : &njs_value_false;
ret = njs_flathsh_unique_insert(&desc->hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
+ pr = lhq.value;
+
+ pr->type = NJS_PROPERTY;
+ pr->enumerable = 1;
+ pr->configurable = 1;
+ pr->writable = 1;
+ pr->u.value = *setval;
+
njs_set_object(dest, desc);
return NJS_OK;
case NJS_PROPERTY:
return "property";
+ case NJS_FREE_FLATHSH_ELEMENT:
+ return "free hash element";
+
default:
return "unknown";
}
njs_int_t
-njs_object_prop_init(njs_vm_t *vm, const njs_object_init_t* init,
+njs_object_props_init(njs_vm_t *vm, const njs_object_init_t* init,
njs_object_prop_t *base, uint32_t atom_id, njs_value_t *value,
njs_value_t *retval)
{
return NJS_ERROR;
}
- prop = njs_mp_align(vm->mem_pool, sizeof(njs_value_t),
- sizeof(njs_object_prop_t));
- if (njs_slow_path(prop == NULL)) {
- njs_memory_error(vm);
- return NJS_ERROR;
- }
-
- *prop = *base;
-
- prop->type = NJS_PROPERTY;
- njs_set_object(njs_prop_value(prop), object);
-
- lhq.value = prop;
lhq.key_hash = atom_id;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
lhq.proto = &njs_object_hash_proto;
ret = njs_flathsh_unique_insert(njs_object_hash(value), &lhq);
- if (njs_fast_path(ret == NJS_OK)) {
- njs_value_assign(retval, njs_prop_value(prop));
- return NJS_OK;
+ if (njs_slow_path(ret != NJS_OK)) {
+ njs_internal_error(vm, "lvlhsh insert failed");
+ return NJS_ERROR;
}
- njs_internal_error(vm, "lvlhsh insert failed");
+ prop = lhq.value;
- return NJS_ERROR;
+ prop->enumerable = base->enumerable;
+ prop->configurable = base->configurable;
+ prop->writable = base->writable;
+ prop->type = NJS_PROPERTY;
+ njs_set_object(njs_prop_value(prop), object);
+
+ njs_value_assign(retval, njs_prop_value(prop));
+
+ return NJS_OK;
}
#define NJS_DECLARE_PROP_VALUE(_name, _v, _fl) \
{ \
- .atom_id = NJS_ATOM_ ## _name, \
.desc = { \
+ .atom_id = NJS_ATOM_ ## _name, \
.type = NJS_PROPERTY, \
.u.value = _v, \
.enumerable = !!(_fl & NJS_OBJECT_PROP_ENUMERABLE), \
#define NJS_DECLARE_PROP_HANDLER(_name, _native, _m16, _fl) \
{ \
- .atom_id = NJS_ATOM_ ## _name, \
.desc = { \
+ .atom_id = NJS_ATOM_ ## _name, \
.type = NJS_PROPERTY_HANDLER, \
.u.value = njs_prop_handler2(_native, _m16), \
.enumerable = !!(_fl & NJS_OBJECT_PROP_ENUMERABLE), \
#define NJS_DECLARE_PROP_GETTER(_name, _native, _magic) \
{ \
- .atom_id = NJS_ATOM_ ## _name, \
.desc = { \
+ .atom_id = NJS_ATOM_ ## _name, \
.type = NJS_ACCESSOR, \
.u.accessor = njs_getter(_native, _magic), \
- .writable = NJS_ATTRIBUTE_UNSET, \
+ .writable = 0, \
.configurable = 1, \
}, \
}
}
/* FIXME: implement fast CreateDataPropertyOrThrow(). */
- prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1);
- if (njs_slow_path(prop == NULL)) {
- goto fail;
- }
-
- c = njs_regex_capture(match_data, 0);
-
- if (utf8 == NJS_STRING_UTF8) {
- index = njs_string_index(string, c);
-
- } else {
- index = c;
- }
-
- njs_set_number(&prop->u.value, index);
lhq.key_hash = NJS_ATOM_STRING_index;
lhq.replace = 0;
- lhq.value = prop;
lhq.pool = vm->mem_pool;
lhq.proto = &njs_object_hash_proto;
goto insert_fail;
}
- prop = njs_object_prop_alloc(vm, ®exp->string, 1);
- if (njs_slow_path(prop == NULL)) {
- goto fail;
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+
+ c = njs_regex_capture(match_data, 0);
+
+ if (utf8 == NJS_STRING_UTF8) {
+ index = njs_string_index(string, c);
+
+ } else {
+ index = c;
}
+ njs_set_number(&prop->u.value, index);
+
lhq.key_hash = NJS_ATOM_STRING_input;
- lhq.value = prop;
ret = njs_flathsh_unique_insert(&array->object.hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
goto insert_fail;
}
- prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1);
- if (njs_slow_path(prop == NULL)) {
- goto fail;
- }
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = regexp->string;
lhq.key_hash = NJS_ATOM_STRING_groups;
- lhq.value = prop;
ret = njs_flathsh_unique_insert(&array->object.hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
goto insert_fail;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = njs_value_undefined;
+
if (pattern->ngroups != 0) {
groups = njs_object_alloc(vm);
if (njs_slow_path(groups == NULL)) {
goto fail;
}
- prop = njs_object_prop_alloc(vm, &array->start[group->capture], 1);
- if (njs_slow_path(prop == NULL)) {
- goto fail;
- }
-
lhq.key_hash = name.atom_id;
- lhq.value = prop;
ret = njs_flathsh_unique_insert(&groups->hash, &lhq);
if (njs_slow_path(ret != NJS_OK)) {
goto insert_fail;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = array->start[group->capture];
+
i++;
} while (i < pattern->ngroups);
njs_regexp_exec_result_free(njs_vm_t *vm, njs_array_t *result)
{
njs_flathsh_t *hash;
- njs_object_prop_t *prop;
- njs_flathsh_elt_t *elt;
- njs_flathsh_each_t lhe;
njs_flathsh_query_t lhq;
- njs_flathsh_each_init(&lhe, &njs_object_hash_proto);
-
hash = &result->object.hash;
- for ( ;; ) {
- elt = njs_flathsh_each(hash, &lhe);
- if (elt == NULL) {
- break;
- }
-
- prop = elt->value;
-
- njs_mp_free(vm->mem_pool, prop);
- }
-
lhq.pool = vm->mem_pool;
lhq.proto = &njs_object_hash_proto;
njs_str_t string;
njs_value_t *value;
- value = data;
+ value = *(njs_value_t **) data;
if (njs_is_string(value)) {
/* parser strings are always initialized. */
njs_value_t *value;
njs_string_t *string;
njs_lvlhsh_t *values_hash;
+ njs_object_prop_t *pr;
njs_lvlhsh_query_t lhq;
is_string = 0;
lhq.proto = &njs_values_hash_proto;
if (njs_lvlhsh_find(&vm->shared->values_hash, &lhq) == NJS_OK) {
- value = lhq.value;
+ value = ((njs_object_prop_t *) lhq.value)->u.val;
*index = (njs_index_t *) ((u_char *) value + sizeof(njs_value_t));
} else if (runtime && njs_lvlhsh_find(&vm->values_hash, &lhq) == NJS_OK) {
- value = lhq.value;
+ value = ((njs_object_prop_t *) lhq.value)->u.val;
*index = (njs_index_t *) ((u_char *) value + sizeof(njs_value_t));
**index = NJS_INDEX_ERROR;
lhq.replace = 0;
- lhq.value = value;
lhq.pool = vm->mem_pool;
values_hash = runtime ? &vm->values_hash : &vm->shared->values_hash;
if (njs_slow_path(ret != NJS_OK)) {
return NULL;
}
+
+ pr = lhq.value;
+ pr->u.val = value;
}
if (start != (u_char *) src) {
pq->lhq.value = prop;
+ prop->type = NJS_PROPERTY;
prop->writable = slots->writable;
prop->configurable = slots->configurable;
prop->enumerable = slots->enumerable;
return NJS_ERROR;
}
- elt->value = (&pq.lhq)->value;
-
- prop = (njs_object_prop_t *) elt->value;
-
+ prop = (njs_object_prop_t *) elt;
prop->type = NJS_PROPERTY;
prop->enumerable = 1;
prop->configurable = 1;
goto fail;
}
- prop = njs_object_prop_alloc(vm, &njs_value_undefined, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
pq.lhq.replace = 0;
- pq.lhq.value = prop;
pq.lhq.key_hash = atom_id;
pq.lhq.pool = vm->mem_pool;
return NJS_ERROR;
}
+ prop = pq.lhq.value;
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+
found:
njs_value_assign(njs_prop_value(prop), setval);
typedef enum {
- NJS_PROPERTY = 0,
+ NJS_FREE_FLATHSH_ELEMENT = 0,
+ NJS_PROPERTY,
NJS_ACCESSOR,
NJS_PROPERTY_HANDLER,
} njs_prop_query_t;
-/*
- * Attributes are generally used as Boolean values.
- * The UNSET value is can be seen:
- * for newly created property descriptors in njs_define_property(),
- * for writable attribute of accessor descriptors (desc->writable
- * cannot be used as a boolean value).
- */
-typedef enum {
- NJS_ATTRIBUTE_FALSE = 0,
- NJS_ATTRIBUTE_TRUE = 1,
- NJS_ATTRIBUTE_UNSET,
-} njs_object_attribute_t;
-
+/* njs_object_prop_s: same structure and length as njs_flathsh_elt_t. */
struct njs_object_prop_s {
+ /* next_elt + property descriptor : 32 bits */
+
+ uint32_t next_elt:26;
+
+ uint32_t type:3;
+ uint32_t writable:1;
+ uint32_t enumerable:1;
+ uint32_t configurable:1;
+
+ uint32_t atom_id;
+
union {
+ njs_value_t *val;
+ njs_mod_t *mod;
njs_value_t value;
struct {
njs_function_t *getter;
} accessor;
} u;
-#define njs_prop_value(_p) (&(_p)->u.value)
+#define njs_prop_value(_p) (&((njs_object_prop_t *) (_p))->u.value)
+#define njs_prop_module(_p) (((njs_object_prop_t *) (_p))->u.mod)
#define njs_prop_handler(_p) (_p)->u.value.data.u.prop_handler
#define njs_prop_ref(_p) (_p)->u.value.data.u.value
#define njs_prop_typed_ref(_p) (_p)->u.value.data.u.typed_array
#define njs_prop_getter(_p) (_p)->u.accessor.getter
#define njs_prop_setter(_p) (_p)->u.accessor.setter
- njs_object_prop_type_t type:8; /* 3 bits */
-
- njs_object_attribute_t writable:8; /* 2 bits */
- njs_object_attribute_t enumerable:8; /* 2 bits */
- njs_object_attribute_t configurable:8; /* 2 bits */
};
struct njs_object_prop_init_s {
struct njs_object_prop_s desc;
- uint32_t atom_id;
};
njs_value_t prop_name;
njs_object_t *global;
njs_flathsh_t *hash;
+ njs_object_prop_t *obj_prop;
njs_flathsh_query_t lhq;
ret = njs_atom_string_create(vm, &prop_name, var_name->start,
return NJS_ERROR;
}
- lhq.value = prop;
lhq.key_hash = prop_name.atom_id;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
return ret;
}
+ obj_prop = lhq.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;
+
return NJS_OK;
}
njs_vm_bind(njs_vm_t *vm, const njs_str_t *var_name, const njs_value_t *value,
njs_bool_t shared)
{
- njs_object_prop_t *prop;
+ njs_object_prop_t prop;
- prop = njs_object_prop_alloc(vm, value, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
+ njs_object_prop_init(&prop, NJS_PROPERTY,
+ NJS_OBJECT_PROP_VALUE_ECW);
+ *njs_prop_value(&prop) = *value;
- return njs_vm_bind2(vm, var_name, prop, shared);
+ return njs_vm_bind2(vm, var_name, &prop, shared);
}
njs_prop_handler_t handler, uint16_t magic16, uint32_t magic32,
njs_bool_t shared)
{
- njs_object_prop_t *prop;
+ njs_object_prop_t prop;
- prop = njs_object_prop_alloc(vm, &njs_value_invalid, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
+ njs_object_prop_init(&prop, NJS_PROPERTY_HANDLER,
+ NJS_OBJECT_PROP_VALUE_ECW);
- prop->type = NJS_PROPERTY_HANDLER;
- prop->u.value.type = NJS_INVALID;
- prop->u.value.data.truth = 1;
- njs_prop_magic16(prop) = magic16;
- njs_prop_magic32(prop) = magic32;
- njs_prop_handler(prop) = handler;
+ prop.u.value.type = NJS_INVALID;
+ prop.u.value.data.truth = 1;
+ njs_prop_magic16(&prop) = magic16;
+ njs_prop_magic32(&prop) = magic32;
+ njs_prop_handler(&prop) = handler;
- return njs_vm_bind2(vm, var_name, prop, shared);
+ return njs_vm_bind2(vm, var_name, &prop, shared);
}
goto done;
}
- prop = njs_object_prop_alloc(vm, value, 1);
- if (njs_slow_path(prop == NULL)) {
- goto done;
- }
-
if (name->atom_id == NJS_ATOM_STRING_unknown) {
ret = njs_atom_atomize_key(vm, name);
if (ret != NJS_OK) {
}
}
- lhq.value = prop;
lhq.key_hash = name->atom_id;
lhq.replace = 0;
lhq.pool = vm->mem_pool;
njs_internal_error(vm, NULL);
goto done;
}
+
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = *value;
}
ret = NJS_OK;
}
}
- prop = njs_object_prop_alloc(vm, init, 1);
- if (njs_slow_path(prop == NULL)) {
- return NJS_ERROR;
- }
-
- lhq.value = prop;
lhq.key_hash = name.atom_id;
lhq.replace = 1;
lhq.pool = vm->mem_pool;
return NJS_ERROR;
}
+ prop = lhq.value;
+
+ prop->type = NJS_PROPERTY;
+ prop->enumerable = 1;
+ prop->configurable = 1;
+ prop->writable = 1;
+ prop->u.value = *init;
+
break;
default:
static njs_int_t
lvlhsh_unit_test_key_test(njs_lvlhsh_query_t *lhq, void *data)
{
- if (*(uintptr_t *) lhq->key.start == (uintptr_t) data) {
+ if (*(uintptr_t *) lhq->key.start == *(uintptr_t *) data) {
return NJS_OK;
}
lhq.replace = 0;
lhq.key.length = sizeof(uintptr_t);
lhq.key.start = (u_char *) &key;
- lhq.value = (void *) key;
lhq.proto = proto;
lhq.pool = pool;
switch (njs_lvlhsh_insert(lh, &lhq)) {
case NJS_OK:
+ ((njs_flathsh_elt_t *) lhq.value)->value[0] = (void *) key;
return NJS_OK;
case NJS_DECLINED:
if (njs_lvlhsh_find(lh, &lhq) == NJS_OK) {
- if (key == (uintptr_t) lhq.value) {
+ if (key == (uintptr_t) ((njs_flathsh_elt_t *) lhq.value)->value[0]) {
return NJS_OK;
}
}
njs_str_t name;
njs_unit_test_prop_t *prop;
- prop = data;
+ prop = *(njs_unit_test_prop_t **) data;
name = prop->name;
if (name.length != lhq->key.length) {
lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length);
lhq.replace = 1;
- lhq.value = (void *) prop;
lhq.proto = &lvlhsh_proto;
lhq.pool = pool;
switch (njs_lvlhsh_insert(&r->hash, &lhq)) {
case NJS_OK:
+ ((njs_flathsh_elt_t *) lhq.value)->value[0] = (void *) prop;
return NJS_OK;
case NJS_DECLINED:
ret = njs_lvlhsh_find(&r->hash, &lhq);
- prop = lhq.value;
-
if (ret == NJS_OK) {
+ prop = ((njs_flathsh_elt_t *) lhq.value)->value[0];
+
if (retval == NULL) {
njs_value_invalid_set(njs_value_arg(&prop->value));
return NJS_OK;