details:   
https://github.com/nginx/njs/commit/2f288a9c6f5db62e34709ad9380cd2f27bbf07c5
branches:  master
commit:    2f288a9c6f5db62e34709ad9380cd2f27bbf07c5
user:      Vadim Zhestikov <v.zhesti...@f5.com>
date:      Fri, 6 Jun 2025 16:52:57 -0700
description:
Optimized memory consumption by object hash.

The new hash takes 42% less memory per element.

---
 src/njs_array.c               |   6 +-
 src/njs_atom.c                |  78 +++++++---
 src/njs_buffer.c              |   8 +-
 src/njs_builtin.c             | 150 ++++++++++---------
 src/njs_error.c               |  47 +++---
 src/njs_extern.c              |  49 +++----
 src/njs_flathsh.c             |  38 ++---
 src/njs_flathsh.h             |  17 ++-
 src/njs_function.c            |  68 ++++-----
 src/njs_json.c                |  28 ++--
 src/njs_module.c              |  25 +++-
 src/njs_object.c              | 113 ++++++++------
 src/njs_object.h              |  19 +--
 src/njs_object_prop.c         | 334 ++++++++++++++++++++----------------------
 src/njs_object_prop_declare.h |   8 +-
 src/njs_regexp.c              |  86 +++++------
 src/njs_scope.c               |  11 +-
 src/njs_value.c               |  17 +--
 src/njs_value.h               |  39 +++--
 src/njs_vm.c                  |  56 +++----
 src/njs_vmcode.c              |  14 +-
 src/test/lvlhsh_unit_test.c   |   6 +-
 src/test/njs_externals_test.c |   8 +-
 23 files changed, 646 insertions(+), 579 deletions(-)

diff --git a/src/njs_array.c b/src/njs_array.c
index e6f8ed83..3f424bc4 100644
--- a/src/njs_array.c
+++ b/src/njs_array.c
@@ -702,8 +702,10 @@ njs_array_length(njs_vm_t *vm,njs_object_prop_t *prop, 
uint32_t unused,
         }
     }
 
-    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);
 
diff --git a/src/njs_atom.c b/src/njs_atom.c
index 24e6dc17..dc66f886 100644
--- a/src/njs_atom.c
+++ b/src/njs_atom.c
@@ -82,7 +82,7 @@ njs_atom_find_or_add(njs_vm_t *vm, u_char *key, size_t size, 
size_t length,
     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;
@@ -92,33 +92,65 @@ njs_atom_find_or_add(njs_vm_t *vm, u_char *key, size_t 
size, size_t length,
 
     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);
@@ -126,7 +158,19 @@ njs_atom_find_or_add(njs_vm_t *vm, u_char *key, size_t 
size, size_t length,
         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;
 }
 
 
@@ -190,7 +234,6 @@ njs_atom_hash_init(njs_vm_t *vm)
 
         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)) {
@@ -206,7 +249,6 @@ njs_atom_hash_init(njs_vm_t *vm)
             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)) {
@@ -214,6 +256,8 @@ njs_atom_hash_init(njs_vm_t *vm)
                 return 0xffffffff;
             }
         }
+
+        *njs_prop_value(lhq.value) = *value;
     }
 
     vm->atom_hash_current = &vm->atom_hash_shared;
@@ -247,10 +291,7 @@ njs_atom_atomize_key(njs_vm_t *vm, njs_value_t *value)
             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;
             }
@@ -320,13 +361,14 @@ njs_atom_symbol_add(njs_vm_t *vm, njs_value_t *value)
 
     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;
diff --git a/src/njs_buffer.c b/src/njs_buffer.c
index 3f0469e7..dbe9447a 100644
--- a/src/njs_buffer.c
+++ b/src/njs_buffer.c
@@ -2732,8 +2732,8 @@ static njs_int_t
 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);
 }
 
 
@@ -2741,8 +2741,8 @@ static njs_int_t
 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);
 }
 
 
diff --git a/src/njs_builtin.c b/src/njs_builtin.c
index c960fe1f..5ce2ec7e 100644
--- a/src/njs_builtin.c
+++ b/src/njs_builtin.c
@@ -433,17 +433,11 @@ njs_builtin_traverse(njs_vm_t *vm, njs_traverse_t 
*traverse, void *data)
 
     /* 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;
@@ -455,6 +449,14 @@ njs_builtin_traverse(njs_vm_t *vm, njs_traverse_t 
*traverse, void *data)
         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;
 }
 
@@ -477,6 +479,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, 
njs_function_t *function,
     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;
@@ -538,12 +541,13 @@ njs_builtin_match_native_function(njs_vm_t *vm, 
njs_function_t *function,
     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)
         {
@@ -815,15 +819,6 @@ njs_global_this_object(njs_vm_t *vm, njs_object_prop_t 
*self, uint32_t atom_id,
         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;
@@ -835,6 +830,14 @@ njs_global_this_object(njs_vm_t *vm, njs_object_prop_t 
*self, uint32_t atom_id,
         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;
 }
 
@@ -866,15 +869,6 @@ njs_top_level_object(njs_vm_t *vm, njs_object_prop_t 
*self, uint32_t atom_id,
         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;
@@ -886,6 +880,14 @@ njs_top_level_object(njs_vm_t *vm, njs_object_prop_t 
*self, uint32_t atom_id,
         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;
 }
 
@@ -915,15 +917,6 @@ njs_top_level_constructor(njs_vm_t *vm, njs_object_prop_t 
*self,
         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;
@@ -935,6 +928,14 @@ njs_top_level_constructor(njs_vm_t *vm, njs_object_prop_t 
*self,
         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;
 }
 
@@ -1205,28 +1206,29 @@ njs_process_object_argv(njs_vm_t *vm, njs_object_prop_t 
*pr, uint32_t unused,
         }
     }
 
-    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;
 }
 
 
@@ -1251,10 +1253,6 @@ njs_env_hash_init(njs_vm_t *vm, njs_flathsh_t *hash, 
char **environment)
     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++;
 
@@ -1283,17 +1281,11 @@ njs_env_hash_init(njs_vm_t *vm, njs_flathsh_t *hash, 
char **environment)
 
         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);
@@ -1309,6 +1301,19 @@ njs_env_hash_init(njs_vm_t *vm, njs_flathsh_t *hash, 
char **environment)
              * 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;
         }
     }
 
@@ -1332,28 +1337,29 @@ njs_process_object_env(njs_vm_t *vm, njs_object_prop_t 
*pr, uint32_t unused,
 
     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;
 }
 
 
diff --git a/src/njs_error.c b/src/njs_error.c
index 6e12aa61..d19e0e22 100644
--- a/src/njs_error.c
+++ b/src/njs_error.c
@@ -212,12 +212,6 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const 
njs_value_t *name,
     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);
@@ -225,17 +219,18 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const 
njs_value_t *name,
             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);
@@ -243,17 +238,18 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const 
njs_value_t *name,
             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);
@@ -261,6 +257,15 @@ njs_error_alloc(njs_vm_t *vm, njs_object_t *proto, const 
njs_value_t *name,
             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;
diff --git a/src/njs_extern.c b/src/njs_extern.c
index 077d2a5f..adc8cd67 100644
--- a/src/njs_extern.c
+++ b/src/njs_extern.c
@@ -58,15 +58,6 @@ njs_external_add(njs_vm_t *vm, njs_arr_t *protos,
             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;
 
@@ -81,7 +72,20 @@ njs_external_add(njs_vm_t *vm, njs_arr_t *protos,
             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:
@@ -167,12 +171,6 @@ njs_external_add(njs_vm_t *vm, njs_arr_t *protos,
             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++;
     }
 
@@ -224,16 +222,6 @@ njs_external_prop_handler(njs_vm_t *vm, njs_object_prop_t 
*self,
         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;
@@ -245,6 +233,15 @@ njs_external_prop_handler(njs_vm_t *vm, njs_object_prop_t 
*self,
         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;
 }
 
diff --git a/src/njs_flathsh.c b/src/njs_flathsh.c
index 5a4efaa5..7e374c62 100644
--- a/src/njs_flathsh.c
+++ b/src/njs_flathsh.c
@@ -210,13 +210,14 @@ njs_flathsh_add_elt(njs_flathsh_t *fh, 
njs_flathsh_query_t *fhq)
     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;
 }
 
@@ -269,7 +270,7 @@ njs_expand_elts(njs_flathsh_query_t *fhq, 
njs_flathsh_descr_t *h)
         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;
@@ -331,7 +332,7 @@ njs_flathsh_find(const njs_flathsh_t *fh, 
njs_flathsh_query_t *fhq)
         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;
         }
 
@@ -362,7 +363,7 @@ njs_flathsh_unique_find(const njs_flathsh_t *fh, 
njs_flathsh_query_t *fhq)
         e = &elts[elt_num - 1];
 
         if (e->key_hash == fhq->key_hash) {
-            fhq->value = e->value;
+            fhq->value = e;
             return NJS_OK;
         }
 
@@ -402,8 +403,7 @@ njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t 
*fhq)
             fhq->proto->test(fhq, elt->value) == NJS_OK)
         {
             if (fhq->replace) {
-                elt->value = fhq->value;
-
+                fhq->value = elt;
                 return NJS_OK;
 
             } else {
@@ -419,7 +419,7 @@ njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t 
*fhq)
         return NJS_ERROR;
     }
 
-    elt->value = fhq->value;
+    fhq->value = elt;
 
     return NJS_OK;
 }
@@ -428,7 +428,6 @@ njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t 
*fhq)
 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;
@@ -453,15 +452,10 @@ njs_flathsh_unique_insert(njs_flathsh_t *fh, 
njs_flathsh_query_t *fhq)
 
         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;
             }
         }
@@ -474,7 +468,7 @@ njs_flathsh_unique_insert(njs_flathsh_t *fh, 
njs_flathsh_query_t *fhq)
         return NJS_ERROR;
     }
 
-    elt->value = fhq->value;
+    fhq->value = elt;
 
     return NJS_OK;
 }
@@ -516,8 +510,8 @@ njs_shrink_elts(njs_flathsh_query_t *fhq, 
njs_flathsh_descr_t *h)
 
     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;
@@ -567,7 +561,7 @@ njs_flathsh_delete(njs_flathsh_t *fh, njs_flathsh_query_t 
*fhq)
         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;
@@ -578,7 +572,7 @@ njs_flathsh_delete(njs_flathsh_t *fh, njs_flathsh_query_t 
*fhq)
 
             h->elts_deleted_count++;
 
-            elt->value = NULL;
+            elt->type = NJS_FREE_FLATHSH_ELEMENT;
 
             /* Shrink elts if elts_deleted_count is eligible. */
 
@@ -632,7 +626,7 @@ njs_flathsh_unique_delete(njs_flathsh_t *fh, 
njs_flathsh_query_t *fhq)
         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;
@@ -643,7 +637,7 @@ njs_flathsh_unique_delete(njs_flathsh_t *fh, 
njs_flathsh_query_t *fhq)
 
             h->elts_deleted_count++;
 
-            elt->value = NULL;
+            elt->type = NJS_FREE_FLATHSH_ELEMENT;
 
             /* Shrink elts if elts_deleted_count is eligible. */
 
@@ -690,7 +684,7 @@ njs_flathsh_each(const njs_flathsh_t *fh, 
njs_flathsh_each_t *fhe)
 
     while (fhe->cp < h->elts_count) {
         e = &elt[fhe->cp++];
-        if (e->value != NULL) {
+        if (e->type != NJS_FREE_FLATHSH_ELEMENT) {
             return e;
         }
     }
diff --git a/src/njs_flathsh.h b/src/njs_flathsh.h
index 38a9c56e..06fd00c0 100644
--- a/src/njs_flathsh.h
+++ b/src/njs_flathsh.h
@@ -13,9 +13,18 @@ typedef struct {
 
 
 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;
 
 
@@ -174,7 +183,7 @@ typedef struct njs_flathsh_proto_s  njs_lvlhsh_proto_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;
@@ -184,7 +193,7 @@ njs_lvlhsh_each(const njs_flathsh_t *lh, njs_flathsh_each_t 
*lhe)
         return NULL;
     }
 
-    return e->value;
+    return e;
 }
 
 
diff --git a/src/njs_function.c b/src/njs_function.c
index 7db342f6..09bc2ebb 100644
--- a/src/njs_function.c
+++ b/src/njs_function.c
@@ -126,11 +126,25 @@ njs_function_name_set(njs_vm_t *vm, njs_function_t 
*function,
     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))) {
@@ -172,20 +186,6 @@ njs_function_name_set(njs_vm_t *vm, njs_function_t 
*function,
         }
     }
 
-    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;
 }
 
@@ -327,12 +327,12 @@ njs_function_prototype_thrower(njs_vm_t *vm, njs_value_t 
*args,
 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,
         },
     },
 };
@@ -894,14 +894,6 @@ njs_function_property_prototype_set(njs_vm_t *vm, 
njs_flathsh_t *hash,
     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;
@@ -909,13 +901,21 @@ njs_function_property_prototype_set(njs_vm_t *vm, 
njs_flathsh_t *hash,
 
     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;
 }
 
 
@@ -1432,23 +1432,23 @@ static const njs_object_prop_init_t  
njs_function_prototype_properties[] =
     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,
         },
     },
diff --git a/src/njs_json.c b/src/njs_json.c
index e79b1eb4..49c2b7e7 100644
--- a/src/njs_json.c
+++ b/src/njs_json.c
@@ -394,12 +394,6 @@ njs_json_parse_object(njs_json_parse_ctx_t *ctx, 
njs_value_t *value,
             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;
@@ -411,6 +405,14 @@ njs_json_parse_object(njs_json_parse_ctx_t *ctx, 
njs_value_t *value,
             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;
@@ -1609,12 +1611,6 @@ njs_json_wrap_value(njs_vm_t *vm, njs_value_t *wrapper,
     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;
@@ -1625,6 +1621,14 @@ njs_json_wrap_value(njs_vm_t *vm, njs_value_t *wrapper,
         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;
 }
 
diff --git a/src/njs_module.c b/src/njs_module.c
index 5af174f3..7d58972c 100644
--- a/src/njs_module.c
+++ b/src/njs_module.c
@@ -13,7 +13,7 @@ njs_module_hash_test(njs_lvlhsh_query_t *lhq, void *data)
 {
     njs_mod_t  *module;
 
-    module = data;
+    module = *(njs_mod_t **) data;
 
     if (njs_strstr_eq(&lhq->key, &module->name)) {
         return NJS_OK;
@@ -39,6 +39,7 @@ njs_module_find(njs_vm_t *vm, njs_str_t *name, njs_bool_t 
shared)
     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;
@@ -46,11 +47,11 @@ njs_module_find(njs_vm_t *vm, njs_str_t *name, njs_bool_t 
shared)
     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;
@@ -70,13 +71,19 @@ njs_module_find(njs_vm_t *vm, njs_str_t *name, njs_bool_t 
shared)
         }
 
         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;
@@ -88,6 +95,7 @@ njs_module_add(njs_vm_t *vm, njs_str_t *name, njs_value_t 
*value)
 {
     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));
@@ -105,7 +113,6 @@ njs_module_add(njs_vm_t *vm, njs_str_t *name, njs_value_t 
*value)
     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;
 
@@ -115,6 +122,10 @@ njs_module_add(njs_vm_t *vm, njs_str_t *name, njs_value_t 
*value)
         return NULL;
     }
 
+    prop = lhq.value;
+
+    prop->u.mod = module;
+
     if (value != NULL) {
         njs_value_assign(&module->value, value);
         module->function.native = 1;
diff --git a/src/njs_object.c b/src/njs_object.c
index b842b1ab..0c592176 100644
--- a/src/njs_object.c
+++ b/src/njs_object.c
@@ -157,6 +157,7 @@ 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_object_prop_t    *obj_prop;
     njs_flathsh_query_t  lhq;
 
     lhq.replace = 0;
@@ -164,7 +165,7 @@ njs_object_hash_create(njs_vm_t *vm, njs_flathsh_t *hash,
     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);
@@ -173,6 +174,14 @@ njs_object_hash_create(njs_vm_t *vm, njs_flathsh_t *hash,
             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--;
     }
@@ -939,7 +948,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) {
@@ -980,7 +989,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 *) (lhq.value))->enumerable
                   || !(flags & NJS_ENUM_ENUMERABLE_ONLY)))
             {
                 continue;
@@ -1012,7 +1021,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) {
@@ -1215,7 +1224,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;
@@ -1235,7 +1244,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) {
@@ -1251,13 +1260,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;
@@ -1274,7 +1289,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];
 
@@ -1353,6 +1368,14 @@ njs_object_make_shared(njs_vm_t *vm, njs_object_t 
*object)
             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)
@@ -1652,7 +1675,7 @@ 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_object_prop_t    *prop;
     njs_flathsh_query_t  lhq;
 
     value = njs_arg(args, nargs, 1);
@@ -1690,20 +1713,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;
 
         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;
@@ -1882,7 +1907,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))
@@ -1942,7 +1967,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;
@@ -2165,15 +2190,6 @@ njs_property_prototype_create(njs_vm_t *vm, 
njs_flathsh_t *hash,
     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;
@@ -2182,13 +2198,21 @@ njs_property_prototype_create(njs_vm_t *vm, 
njs_flathsh_t *hash,
 
     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);
 }
 
 
@@ -2426,15 +2450,6 @@ njs_property_constructor_set(njs_vm_t *vm, njs_flathsh_t 
*hash,
     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;
@@ -2442,13 +2457,21 @@ njs_property_constructor_set(njs_vm_t *vm, 
njs_flathsh_t *hash,
     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;
 }
 
 
diff --git a/src/njs_object.h b/src/njs_object.h
index 85e914d4..fac49aa8 100644
--- a/src/njs_object.h
+++ b/src/njs_object.h
@@ -101,8 +101,8 @@ njs_int_t njs_object_length(njs_vm_t *vm, njs_value_t 
*value, int64_t *dst);
 
 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,
@@ -114,7 +114,7 @@ njs_int_t njs_object_prop_descriptor(njs_vm_t *vm, 
njs_value_t *dest,
 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);
 
@@ -122,10 +122,10 @@ njs_int_t njs_object_prop_init(njs_vm_t *vm, const 
njs_object_init_t* init,
 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;
-
 }
 
 
@@ -136,13 +136,6 @@ njs_is_accessor_descriptor(njs_object_prop_t *prop)
 }
 
 
-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)
diff --git a/src/njs_object_prop.c b/src/njs_object_prop.c
index 275cd9ac..6b93960c 100644
--- a/src/njs_object_prop.c
+++ b/src/njs_object_prop.c
@@ -8,54 +8,18 @@
 #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;
 
@@ -67,16 +31,14 @@ njs_object_prop_alloc2(njs_vm_t *vm,
             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;
 }
 
 
@@ -141,12 +103,6 @@ njs_object_property_add(njs_vm_t *vm, njs_value_t *object, 
unsigned atom_id,
     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;
@@ -158,6 +114,14 @@ njs_object_property_add(njs_vm_t *vm, njs_value_t *object, 
unsigned atom_id,
         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;
 }
 
@@ -169,15 +133,21 @@ njs_int_t
 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)
@@ -190,7 +160,8 @@ again:
 
     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;
         }
@@ -211,12 +182,8 @@ again:
             }
         }
 
-        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;
 
@@ -225,11 +192,9 @@ again:
     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);
@@ -282,7 +247,7 @@ set_prop:
             }
 
         } else {
-            if (prop->writable == NJS_ATTRIBUTE_UNSET) {
+            if (!set_writable) {
                 prop->writable = 0;
             }
 
@@ -291,11 +256,11 @@ set_prop:
             }
         }
 
-        if (prop->enumerable == NJS_ATTRIBUTE_UNSET) {
+        if (!set_enumerable) {
             prop->enumerable = 0;
         }
 
-        if (prop->configurable == NJS_ATTRIBUTE_UNSET) {
+        if (!set_configurable) {
             prop->configurable = 0;
         }
 
@@ -304,6 +269,8 @@ set_prop:
 
             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;
             }
 
@@ -311,7 +278,6 @@ set_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;
 
@@ -320,6 +286,13 @@ set_prop:
                 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;
@@ -339,9 +312,9 @@ set_prop:
     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));
@@ -372,9 +345,9 @@ set_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;
         }
@@ -400,22 +373,24 @@ set_prop:
 
     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;
         }
@@ -434,12 +409,12 @@ set_prop:
         }
 
         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));
         }
@@ -447,10 +422,10 @@ set_prop:
         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;
             }
 
@@ -483,7 +458,7 @@ done:
 
     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;
@@ -538,8 +513,8 @@ done:
             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)))
                 {
@@ -547,7 +522,7 @@ done:
                     return NJS_ERROR;
                 }
 
-                if (prop->writable != NJS_ATTRIBUTE_UNSET) {
+                if (set_writable) {
                     prev->writable = prop->writable;
                 }
 
@@ -564,15 +539,15 @@ done:
      * 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;
     }
 
@@ -597,18 +572,9 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t 
*pq,
     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);
@@ -617,6 +583,13 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t 
*pq,
         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));
@@ -683,14 +656,15 @@ njs_prop_private_copy(njs_vm_t *vm, njs_property_query_t 
*pq,
 
 
 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)) {
@@ -698,11 +672,12 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *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;
@@ -767,6 +742,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc)
     if (ret == NJS_OK) {
         data = 1;
         prop->writable = njs_is_true(&value);
+        *set_writable = 1;
     }
 
     if (accessor && data) {
@@ -784,6 +760,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc)
 
     if (ret == NJS_OK) {
         prop->enumerable = njs_is_true(&value);
+        *set_enumerable = 1;
     }
 
     lhq.key_hash = NJS_ATOM_STRING_configurable;
@@ -795,6 +772,7 @@ njs_descriptor_prop(njs_vm_t *vm, const njs_value_t *desc)
 
     if (ret == NJS_OK) {
         prop->configurable = njs_is_true(&value);
+        *set_configurable = 1;
     }
 
     if (accessor) {
@@ -878,29 +856,23 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t 
*dest,
     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)) {
@@ -908,20 +880,37 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t 
*dest,
             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)) {
@@ -929,53 +918,40 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t 
*dest,
             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)) {
@@ -983,6 +959,14 @@ njs_object_prop_descriptor(njs_vm_t *vm, njs_value_t *dest,
         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;
@@ -1006,6 +990,9 @@ njs_prop_type_string(njs_object_prop_type_t type)
     case NJS_PROPERTY:
         return "property";
 
+    case NJS_FREE_FLATHSH_ELEMENT:
+        return "free hash element";
+
     default:
         return "unknown";
     }
@@ -1013,7 +1000,7 @@ 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_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)
 {
@@ -1033,31 +1020,26 @@ njs_object_prop_init(njs_vm_t *vm, const 
njs_object_init_t* init,
         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;
 }
diff --git a/src/njs_object_prop_declare.h b/src/njs_object_prop_declare.h
index f2f7a5eb..3c991c50 100644
--- a/src/njs_object_prop_declare.h
+++ b/src/njs_object_prop_declare.h
@@ -9,8 +9,8 @@
 
 #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),               \
@@ -28,8 +28,8 @@
 
 #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),               \
@@ -41,11 +41,11 @@
 
 #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,                                                \
         },                                                                    \
     }
diff --git a/src/njs_regexp.c b/src/njs_regexp.c
index ed560b18..d958e2af 100644
--- a/src/njs_regexp.c
+++ b/src/njs_regexp.c
@@ -1038,25 +1038,9 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, 
njs_utf8_t utf8,
     }
 
     /* 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;
 
@@ -1065,32 +1049,54 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, 
njs_utf8_t utf8,
         goto insert_fail;
     }
 
-    prop = njs_object_prop_alloc(vm, &regexp->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)) {
@@ -1110,19 +1116,21 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_value_t *r, 
njs_utf8_t utf8,
                 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);
@@ -1149,26 +1157,10 @@ static void
 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;
 
diff --git a/src/njs_scope.c b/src/njs_scope.c
index b95d3979..7959849a 100644
--- a/src/njs_scope.c
+++ b/src/njs_scope.c
@@ -108,7 +108,7 @@ njs_scope_values_hash_test(njs_lvlhsh_query_t *lhq, void 
*data)
     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. */
@@ -156,6 +156,7 @@ njs_scope_value_index(njs_vm_t *vm, const njs_value_t *src, 
njs_uint_t runtime,
     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;
@@ -181,12 +182,12 @@ njs_scope_value_index(njs_vm_t *vm, const njs_value_t 
*src, njs_uint_t runtime,
     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));
 
@@ -228,7 +229,6 @@ njs_scope_value_index(njs_vm_t *vm, const njs_value_t *src, 
njs_uint_t runtime,
         **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;
@@ -237,6 +237,9 @@ njs_scope_value_index(njs_vm_t *vm, const njs_value_t *src, 
njs_uint_t runtime,
         if (njs_slow_path(ret != NJS_OK)) {
             return NULL;
         }
+
+        pr = lhq.value;
+        pr->u.val = value;
     }
 
     if (start != (u_char *) src) {
diff --git a/src/njs_value.c b/src/njs_value.c
index 92c87e85..78f03821 100644
--- a/src/njs_value.c
+++ b/src/njs_value.c
@@ -960,6 +960,7 @@ njs_external_property_query(njs_vm_t *vm, 
njs_property_query_t *pq,
 
     pq->lhq.value = prop;
 
+    prop->type = NJS_PROPERTY;
     prop->writable = slots->writable;
     prop->configurable = slots->configurable;
     prop->enumerable = slots->enumerable;
@@ -1279,10 +1280,7 @@ slow_path:
                 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;
@@ -1318,13 +1316,8 @@ slow_path:
         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;
 
@@ -1334,6 +1327,12 @@ slow_path:
         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);
diff --git a/src/njs_value.h b/src/njs_value.h
index da53f158..3fba344b 100644
--- a/src/njs_value.h
+++ b/src/njs_value.h
@@ -287,7 +287,8 @@ struct njs_object_type_init_s {
 
 
 typedef enum {
-    NJS_PROPERTY = 0,
+    NJS_FREE_FLATHSH_ELEMENT = 0,
+    NJS_PROPERTY,
     NJS_ACCESSOR,
     NJS_PROPERTY_HANDLER,
 
@@ -305,22 +306,23 @@ typedef enum {
 } 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;
@@ -328,7 +330,8 @@ struct njs_object_prop_s {
         } 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
@@ -338,17 +341,11 @@ struct njs_object_prop_s {
 #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;
 };
 
 
diff --git a/src/njs_vm.c b/src/njs_vm.c
index 18a1c8e6..e6aac927 100644
--- a/src/njs_vm.c
+++ b/src/njs_vm.c
@@ -903,6 +903,7 @@ njs_vm_bind2(njs_vm_t *vm, const njs_str_t *var_name, 
njs_object_prop_t *prop,
     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,
@@ -911,7 +912,6 @@ njs_vm_bind2(njs_vm_t *vm, const njs_str_t *var_name, 
njs_object_prop_t *prop,
         return NJS_ERROR;
     }
 
-    lhq.value = prop;
     lhq.key_hash = prop_name.atom_id;
     lhq.replace = 1;
     lhq.pool = vm->mem_pool;
@@ -926,6 +926,14 @@ njs_vm_bind2(njs_vm_t *vm, const njs_str_t *var_name, 
njs_object_prop_t *prop,
         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;
 }
 
@@ -934,14 +942,13 @@ njs_int_t
 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);
 }
 
 
@@ -950,21 +957,18 @@ njs_vm_bind_handler(njs_vm_t *vm, const njs_str_t 
*var_name,
     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);
 }
 
 
@@ -1242,11 +1246,6 @@ njs_vm_object_alloc(njs_vm_t *vm, njs_value_t *retval, 
...)
             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) {
@@ -1254,7 +1253,6 @@ njs_vm_object_alloc(njs_vm_t *vm, njs_value_t *retval, 
...)
             }
         }
 
-        lhq.value = prop;
         lhq.key_hash = name->atom_id;
         lhq.replace = 0;
         lhq.pool = vm->mem_pool;
@@ -1265,6 +1263,14 @@ njs_vm_object_alloc(njs_vm_t *vm, njs_value_t *retval, 
...)
             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;
diff --git a/src/njs_vmcode.c b/src/njs_vmcode.c
index ba6df7d8..727dc6d0 100644
--- a/src/njs_vmcode.c
+++ b/src/njs_vmcode.c
@@ -2123,12 +2123,6 @@ njs_vmcode_property_init(njs_vm_t *vm, njs_value_t 
*value, njs_value_t *key,
             }
         }
 
-        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;
@@ -2140,6 +2134,14 @@ njs_vmcode_property_init(njs_vm_t *vm, njs_value_t 
*value, njs_value_t *key,
             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:
diff --git a/src/test/lvlhsh_unit_test.c b/src/test/lvlhsh_unit_test.c
index 6172c1c7..0e334c5d 100644
--- a/src/test/lvlhsh_unit_test.c
+++ b/src/test/lvlhsh_unit_test.c
@@ -11,7 +11,7 @@
 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;
     }
 
@@ -51,13 +51,13 @@ lvlhsh_unit_test_add(njs_lvlhsh_t *lh, const 
njs_lvlhsh_proto_t *proto,
     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:
@@ -84,7 +84,7 @@ lvlhsh_unit_test_get(njs_lvlhsh_t *lh, const 
njs_lvlhsh_proto_t *proto,
 
     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;
         }
     }
diff --git a/src/test/njs_externals_test.c b/src/test/njs_externals_test.c
index 8d71aae7..d3d3f1c1 100644
--- a/src/test/njs_externals_test.c
+++ b/src/test/njs_externals_test.c
@@ -61,7 +61,7 @@ lvlhsh_unit_test_key_test(njs_lvlhsh_query_t *lhq, void *data)
     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) {
@@ -129,13 +129,13 @@ lvlhsh_unit_test_add(njs_mp_t *pool, njs_unit_test_req_t 
*r,
     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:
@@ -291,9 +291,9 @@ njs_unit_test_r_vars(njs_vm_t *vm, njs_object_prop_t *self, 
uint32_t atom_id,
 
     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;
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
https://mailman.nginx.org/mailman/listinfo/nginx-devel

Reply via email to