]> git.kaiwu.me - njs.git/commitdiff
Builtin objects refactored.
authorIgor Sysoev <igor@sysoev.ru>
Sat, 28 Nov 2015 09:18:10 +0000 (12:18 +0300)
committerIgor Sysoev <igor@sysoev.ru>
Sat, 28 Nov 2015 09:18:10 +0000 (12:18 +0300)
25 files changed:
Makefile
njs/njs_array.c
njs/njs_array.h
njs/njs_boolean.c
njs/njs_boolean.h
njs/njs_builtin.c [new file with mode: 0644]
njs/njs_function.c
njs/njs_function.h
njs/njs_generator.c
njs/njs_lexer_keyword.c
njs/njs_number.c
njs/njs_number.h
njs/njs_object.c
njs/njs_object.h
njs/njs_parser.c
njs/njs_parser.h
njs/njs_parser_expression.c
njs/njs_regexp.c
njs/njs_regexp.h
njs/njs_shared.c [deleted file]
njs/njs_string.c
njs/njs_string.h
njs/njs_vm.c
njs/njs_vm.h
njs/njscript.c

index baad353dfb6e08dcd1c2a5936778ef3e6386f366..d13489a168bd7da74881db18b91cef0223bf9c02 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ $(NXT_BUILDDIR)/libnjs.a: \
        $(NXT_BUILDDIR)/njs_regexp.o \
        $(NXT_BUILDDIR)/njs_extern.o \
        $(NXT_BUILDDIR)/njs_variable.o \
-       $(NXT_BUILDDIR)/njs_shared.o \
+       $(NXT_BUILDDIR)/njs_builtin.o \
        $(NXT_BUILDDIR)/njs_lexer.o \
        $(NXT_BUILDDIR)/njs_lexer_keyword.o \
        $(NXT_BUILDDIR)/njs_nonrecursive_parser.o \
@@ -48,7 +48,7 @@ $(NXT_BUILDDIR)/libnjs.a: \
                $(NXT_BUILDDIR)/njs_regexp.o \
                $(NXT_BUILDDIR)/njs_extern.o \
                $(NXT_BUILDDIR)/njs_variable.o \
-               $(NXT_BUILDDIR)/njs_shared.o \
+               $(NXT_BUILDDIR)/njs_builtin.o \
                $(NXT_BUILDDIR)/njs_lexer.o \
                $(NXT_BUILDDIR)/njs_lexer_keyword.o \
                $(NXT_BUILDDIR)/njs_nonrecursive_parser.o \
@@ -244,7 +244,7 @@ $(NXT_BUILDDIR)/njs_variable.o: \
                -I$(NXT_LIB) -Injs \
                njs/njs_variable.c
 
-$(NXT_BUILDDIR)/njs_shared.o: \
+$(NXT_BUILDDIR)/njs_builtin.o: \
        $(NXT_BUILDDIR)/libnxt.a \
        njs/njscript.h \
        njs/njs_vm.h \
@@ -254,12 +254,13 @@ $(NXT_BUILDDIR)/njs_shared.o: \
        njs/njs_object.h \
        njs/njs_array.h \
        njs/njs_function.h \
+       njs/njs_regexp.h \
        njs/njs_parser.h \
-       njs/njs_shared.c \
+       njs/njs_builtin.c \
 
-       $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_shared.o $(NXT_CFLAGS) \
+       $(NXT_CC) -c -o $(NXT_BUILDDIR)/njs_builtin.o $(NXT_CFLAGS) \
                -I$(NXT_LIB) -Injs \
-               njs/njs_shared.c
+               njs/njs_builtin.c
 
 $(NXT_BUILDDIR)/njs_lexer.o: \
        $(NXT_BUILDDIR)/libnxt.a \
index 41b453347f39e73ec936a9a79211b6044955bf27..87d9a3235b83a61eea60c8aa48f6503cedd1b370 100644 (file)
@@ -86,9 +86,7 @@ njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare)
     uint32_t     size;
     njs_array_t  *array;
 
-    array = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
-                                sizeof(njs_array_t));
-
+    array = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_array_t));
     if (nxt_slow_path(array == NULL)) {
         return NULL;
     }
@@ -166,7 +164,7 @@ njs_array_realloc(njs_vm_t *vm, njs_array_t *array, uint32_t prepend,
 
 
 njs_ret_t
-njs_array_function(njs_vm_t *vm, njs_param_t *param)
+njs_array_constructor(njs_vm_t *vm, njs_param_t *param)
 {
     double       num;
     uint32_t     size;
@@ -220,7 +218,7 @@ njs_array_function(njs_vm_t *vm, njs_param_t *param)
 }
 
 
-static const njs_object_prop_t  njs_array_function_properties[] =
+static const njs_object_prop_t  njs_array_constructor_properties[] =
 {
     /* Array.name == "Array". */
     { njs_string("Array"),
@@ -233,18 +231,16 @@ static const njs_object_prop_t  njs_array_function_properties[] =
       NJS_PROPERTY, 0, 0, 0, },
 
     /* Array.prototype. */
-    { njs_getter(njs_object_prototype_create_prototype),
+    { njs_getter(njs_object_prototype_create),
       njs_string("prototype"),
       NJS_NATIVE_GETTER, 0, 0, 0, },
 };
 
 
-nxt_int_t
-njs_array_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_array_function_properties,
-                                  nxt_nitems(njs_array_function_properties));
-}
+const njs_object_init_t  njs_array_constructor_init = {
+     njs_array_constructor_properties,
+     nxt_nitems(njs_array_constructor_properties),
+};
 
 
 static njs_ret_t
@@ -946,9 +942,7 @@ static const njs_object_prop_t  njs_array_prototype_properties[] =
 };
 
 
-nxt_int_t
-njs_array_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_array_prototype_properties,
-                                  nxt_nitems(njs_array_prototype_properties));
-}
+const njs_object_init_t  njs_array_prototype_init = {
+     njs_array_prototype_properties,
+     nxt_nitems(njs_array_prototype_properties),
+};
index 7aa3db7f1ba7cf42a77160671d18ea0fddb76d20..d6e0bd71db5bbf804cd7248bd480d758306ee1c2 100644 (file)
@@ -23,9 +23,10 @@ struct njs_array_s {
 njs_array_t *njs_array_alloc(njs_vm_t *vm, uint32_t length, uint32_t spare);
 njs_ret_t njs_array_realloc(njs_vm_t *vm, njs_array_t *array, uint32_t prepend,
     uint32_t size);
-njs_ret_t njs_array_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_array_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_array_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_array_constructor(njs_vm_t *vm, njs_param_t *param);
+
+extern const njs_object_init_t  njs_array_constructor_init;
+extern const njs_object_init_t  njs_array_prototype_init;
 
 
 #endif /* _NJS_ARRAY_H_INCLUDED_ */
index 86ddcaa7463ab22b4cd3b39c4f9451b10cf799fc..05c0e64980d7fd4f2b6051598c10edb39a9ebb47 100644 (file)
@@ -18,7 +18,7 @@
 
 
 njs_ret_t
-njs_boolean_function(njs_vm_t *vm, njs_param_t *param)
+njs_boolean_constructor(njs_vm_t *vm, njs_param_t *param)
 {
     njs_object_t       *object;
     const njs_value_t  *value;
@@ -32,7 +32,6 @@ njs_boolean_function(njs_vm_t *vm, njs_param_t *param)
     }
 
     if (vm->frame->ctor) {
-        /* value->type is the same as prototype offset. */
         object = njs_object_value_alloc(vm, value, value->type);
         if (nxt_slow_path(object == NULL)) {
             return NXT_ERROR;
@@ -50,7 +49,7 @@ njs_boolean_function(njs_vm_t *vm, njs_param_t *param)
 }
 
 
-static const njs_object_prop_t  njs_boolean_function_properties[] =
+static const njs_object_prop_t  njs_boolean_constructor_properties[] =
 {
     /* Boolean.name == "Boolean". */
     { njs_string("Boolean"),
@@ -63,18 +62,16 @@ static const njs_object_prop_t  njs_boolean_function_properties[] =
       NJS_PROPERTY, 0, 0, 0, },
 
     /* Boolean.prototype. */
-    { njs_getter(njs_object_prototype_create_prototype),
+    { njs_getter(njs_object_prototype_create),
       njs_string("prototype"),
       NJS_NATIVE_GETTER, 0, 0, 0, },
 };
 
 
-nxt_int_t
-njs_boolean_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_boolean_function_properties,
-                                  nxt_nitems(njs_boolean_function_properties));
-}
+const njs_object_init_t  njs_boolean_constructor_init = {
+     njs_boolean_constructor_properties,
+     nxt_nitems(njs_boolean_constructor_properties),
+};
 
 
 static njs_ret_t
@@ -141,9 +138,7 @@ static const njs_object_prop_t  njs_boolean_prototype_properties[] =
 };
 
 
-nxt_int_t
-njs_boolean_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_boolean_prototype_properties,
-                                  nxt_nitems(njs_boolean_prototype_properties));
-}
+const njs_object_init_t  njs_boolean_prototype_init = {
+     njs_boolean_prototype_properties,
+     nxt_nitems(njs_boolean_prototype_properties),
+};
index ec0652f76d2f5c17bcd207eef25382bd1a30d92e..041802224691ccc6ed1b324765efd5dd7edfed50 100644 (file)
@@ -8,9 +8,10 @@
 #define _NJS_BOOLEAN_H_INCLUDED_
 
 
-njs_ret_t njs_boolean_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_boolean_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_boolean_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_boolean_constructor(njs_vm_t *vm, njs_param_t *param);
+
+extern const njs_object_init_t  njs_boolean_constructor_init;
+extern const njs_object_init_t  njs_boolean_prototype_init;
 
 
 #endif /* _NJS_BOOLEAN_H_INCLUDED_ */
diff --git a/njs/njs_builtin.c b/njs/njs_builtin.c
new file mode 100644 (file)
index 0000000..9c62757
--- /dev/null
@@ -0,0 +1,175 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_stub.h>
+#include <nxt_array.h>
+#include <nxt_lvlhsh.h>
+#include <nxt_mem_cache_pool.h>
+#include <njscript.h>
+#include <njs_vm.h>
+#include <njs_boolean.h>
+#include <njs_number.h>
+#include <njs_string.h>
+#include <njs_object.h>
+#include <njs_array.h>
+#include <njs_function.h>
+#include <njs_regexp.h>
+#include <string.h>
+
+
+nxt_int_t
+njs_builtin_objects_create(njs_vm_t *vm)
+{
+    nxt_int_t                       ret;
+    nxt_uint_t                      i;
+    njs_object_t                    *prototypes;
+    njs_function_t                  *functions;
+
+    static const njs_object_init_t  *prototype_init[] = {
+        &njs_object_prototype_init,
+        &njs_array_prototype_init,
+        &njs_boolean_prototype_init,
+        &njs_number_prototype_init,
+        &njs_string_prototype_init,
+        &njs_function_prototype_init,
+        &njs_regexp_prototype_init,
+    };
+
+    static const njs_object_init_t  *function_init[] = {
+        &njs_object_constructor_init,
+        &njs_array_constructor_init,
+        &njs_boolean_constructor_init,
+        &njs_number_constructor_init,
+        &njs_string_constructor_init,
+        &njs_function_constructor_init,
+        &njs_regexp_constructor_init,
+
+        &njs_eval_function_init,
+    };
+
+    static const njs_native_t       native_functions[] = {
+        njs_object_constructor,
+        njs_array_constructor,
+        njs_boolean_constructor,
+        njs_number_constructor,
+        njs_string_constructor,
+        njs_function_constructor,
+        njs_regexp_constructor,
+
+        njs_eval_function,
+    };
+
+    static const njs_object_prop_t  null_proto_property = {
+        njs_value(NJS_NULL, 0, 0.0),
+        njs_string("__proto__"),
+        NJS_WHITEOUT, 0, 0, 0,
+    };
+
+    ret = njs_object_hash_create(vm, &vm->shared->null_proto_hash,
+                                 &null_proto_property, 1);
+    if (nxt_slow_path(ret != NXT_OK)) {
+        return NXT_ERROR;
+    }
+
+    prototypes = vm->shared->prototypes;
+
+    for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
+        /* TODO: shared hash: prototype & constructor getters, methods */
+
+        ret = njs_object_hash_create(vm, &prototypes[i].shared_hash,
+                                     prototype_init[i]->properties,
+                                     prototype_init[i]->items);
+        if (nxt_slow_path(ret != NXT_OK)) {
+            return NXT_ERROR;
+        }
+    }
+
+    functions = vm->shared->functions;
+
+    for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
+        functions[i].native = 1;
+        functions[i].args_offset = 1;
+        functions[i].code.native = native_functions[i];
+
+        ret = njs_object_hash_create(vm, &functions[i].object.shared_hash,
+                                     function_init[i]->properties,
+                                     function_init[i]->items);
+        if (nxt_slow_path(ret != NXT_OK)) {
+            return NXT_ERROR;
+        }
+    }
+
+    /* TODO: create function shared hash: prototype+contructor getter */
+
+    return NXT_OK;
+}
+
+
+/*
+ * Object(),
+ * Object.__proto__             -> Function_Prototype,
+ * Object_Prototype.__proto__   -> null,
+ *   the null value is handled by njs_object_prototype_get_proto(),
+ *
+ * Array(),
+ * Array.__proto__              -> Function_Prototype,
+ * Array_Prototype.__proto__    -> Object_Prototype,
+ *
+ * Boolean(),
+ * Boolean.__proto__            -> Function_Prototype,
+ * Boolean_Prototype.__proto__  -> Object_Prototype,
+ *
+ * Number(),
+ * Number.__proto__             -> Function_Prototype,
+ * Number_Prototype.__proto__   -> Object_Prototype,
+ *
+ * String(),
+ * String.__proto__             -> Function_Prototype,
+ * String_Prototype.__proto__   -> Object_Prototype,
+ *
+ * Function(),
+ * Function.__proto__           -> Function_Prototype,
+ * Function_Prototype.__proto__ -> Object_Prototype,
+ *
+ * RegExp(),
+ * RegExp.__proto__             -> Function_Prototype,
+ * RegExp_Prototype.__proto__   -> Object_Prototype,
+ *
+ * eval(),
+ * eval.__proto__               -> Function_Prototype.
+ */
+
+nxt_int_t
+njs_builtin_objects_clone(njs_vm_t *vm)
+{
+    size_t        size;
+    nxt_uint_t    i;
+    njs_value_t   *values;
+    njs_object_t  *function_prototype;
+
+    size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t)
+           + NJS_FUNCTION_MAX * sizeof(njs_function_t);
+
+    memcpy(vm->prototypes, vm->shared->prototypes, size);
+
+    for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_MAX; i++) {
+        vm->prototypes[i].__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+    }
+
+    function_prototype = &vm->prototypes[NJS_FUNCTION_FUNCTION];
+    values = vm->scopes[NJS_SCOPE_GLOBAL];
+
+    for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
+        values[i].type = NJS_FUNCTION;
+        values[i].data.truth = 1;
+        values[i].data.u.function = &vm->functions[i];
+        vm->functions[i].object.__proto__ = function_prototype;
+    }
+
+    return NXT_OK;
+}
index 5411fc4f822328bdeeedadf2922c7aab22275c46..2ec1856ef10ba10c57c5d0b22660ff4c31d61c39 100644 (file)
@@ -75,8 +75,7 @@ njs_function_alloc(njs_vm_t *vm)
     njs_function_t         *func;
     njs_function_script_t  *script;
 
-    func = nxt_mem_cache_zalign(vm->mem_cache_pool, sizeof(njs_value_t),
-                                sizeof(njs_function_t));
+    func = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_function_t));
 
     if (nxt_fast_path(func != NULL)) {
         func->object.__proto__ = &vm->prototypes[NJS_PROTOTYPE_FUNCTION];
@@ -204,7 +203,7 @@ njs_vmcode_trap(njs_vm_t *vm, nxt_uint_t trap, njs_value_t *value1,
 
 
 njs_ret_t
-njs_function_function(njs_vm_t *vm, njs_param_t *param)
+njs_function_constructor(njs_vm_t *vm, njs_param_t *param)
 {
     return NXT_ERROR;
 }
@@ -348,7 +347,7 @@ njs_function_call(njs_vm_t *vm, njs_function_t *func, njs_index_t retval)
 }
 
 
-static const njs_object_prop_t  njs_function_function_properties[] =
+static const njs_object_prop_t  njs_function_constructor_properties[] =
 {
     /* Function.name == "Function". */
     { njs_string("Function"),
@@ -361,18 +360,16 @@ static const njs_object_prop_t  njs_function_function_properties[] =
       NJS_PROPERTY, 0, 0, 0, },
 
     /* Function.prototype. */
-    { njs_getter(njs_object_prototype_create_prototype),
+    { njs_getter(njs_object_prototype_create),
       njs_string("prototype"),
       NJS_NATIVE_GETTER, 0, 0, 0, },
 };
 
 
-nxt_int_t
-njs_function_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_function_function_properties,
-                                  nxt_nitems(njs_function_function_properties));
-}
+const njs_object_init_t  njs_function_constructor_init = {
+     njs_function_constructor_properties,
+     nxt_nitems(njs_function_constructor_properties),
+};
 
 
 static njs_ret_t
@@ -575,12 +572,10 @@ static const njs_object_prop_t  njs_function_prototype_properties[] =
 };
 
 
-nxt_int_t
-njs_function_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_function_prototype_properties,
-                           nxt_nitems(njs_function_prototype_properties));
-}
+const njs_object_init_t  njs_function_prototype_init = {
+     njs_function_prototype_properties,
+     nxt_nitems(njs_function_prototype_properties),
+};
 
 
 njs_ret_t
@@ -604,9 +599,7 @@ static const njs_object_prop_t  njs_eval_function_properties[] =
 };
 
 
-nxt_int_t
-njs_eval_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_eval_function_properties,
-                                  nxt_nitems(njs_eval_function_properties));
-}
+const njs_object_init_t  njs_eval_function_init = {
+     njs_eval_function_properties,
+     nxt_nitems(njs_eval_function_properties),
+};
index 720f467ed31dcc685aa87e3abdcfaf745cc34f79..51db59b5c2104486e38496ab80d4b58e2d4367be 100644 (file)
@@ -27,26 +27,6 @@ struct njs_function_script_s {
 };
 
 
-struct njs_function_s {
-    njs_object_t                   object;
-
-#if (NXT_64BIT)
-    uint32_t                       native;
-    uint32_t                       args_offset;
-#else
-    uint8_t                        native;
-    uint16_t                       args_offset;
-#endif
-
-    union {
-        njs_function_script_t      *script;
-        njs_native_t               native;
-    } code;
-
-    njs_value_t                    *args;
-};
-
-
 /* The frame size must be aligned to njs_value_t. */
 #define NJS_NATIVE_FRAME_SIZE                                                 \
     nxt_align_size(sizeof(njs_native_frame_t), sizeof(njs_value_t))
@@ -113,7 +93,7 @@ typedef struct {
 
 
 njs_function_t *njs_function_alloc(njs_vm_t *vm);
-njs_ret_t njs_function_function(njs_vm_t *vm, njs_param_t *param);
+njs_ret_t njs_function_constructor(njs_vm_t *vm, njs_param_t *param);
 njs_ret_t njs_function_apply(njs_vm_t *vm, njs_value_t *name,
     njs_param_t *param);
 njs_value_t *njs_vmcode_native_frame(njs_vm_t *vm, njs_value_t *method,
@@ -124,11 +104,13 @@ njs_ret_t njs_vmcode_function_frame(njs_vm_t *vm, njs_value_t *name,
     njs_param_t *param, nxt_bool_t ctor);
 njs_ret_t njs_function_call(njs_vm_t *vm, njs_function_t *func,
     njs_index_t retval);
-nxt_int_t njs_function_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_function_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+
+extern const njs_object_init_t  njs_function_constructor_init;
+extern const njs_object_init_t  njs_function_prototype_init;
 
 njs_ret_t njs_eval_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_eval_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+
+extern const njs_object_init_t  njs_eval_function_init;
 
 
 #endif /* _NJS_FUNCTION_H_INCLUDED_ */
index 6e6ac44044022ef17fa1bee1249364484fcfa399..1c23200921730258010b732ecf1165cc3a2018bb 100644 (file)
@@ -242,13 +242,13 @@ njs_generator(njs_vm_t *vm, njs_parser_t *parser, njs_parser_node_t *node)
         return njs_generate_regexp(vm, parser, node);
 
     case NJS_TOKEN_THIS:
-    case NJS_TOKEN_OBJECT_FUNCTION:
-    case NJS_TOKEN_ARRAY_FUNCTION:
-    case NJS_TOKEN_NUMBER_FUNCTION:
-    case NJS_TOKEN_BOOLEAN_FUNCTION:
-    case NJS_TOKEN_STRING_FUNCTION:
-    case NJS_TOKEN_FUNCTION_FUNCTION:
-    case NJS_TOKEN_REGEXP_FUNCTION:
+    case NJS_TOKEN_OBJECT_CONSTRUCTOR:
+    case NJS_TOKEN_ARRAY_CONSTRUCTOR:
+    case NJS_TOKEN_NUMBER_CONSTRUCTOR:
+    case NJS_TOKEN_BOOLEAN_CONSTRUCTOR:
+    case NJS_TOKEN_STRING_CONSTRUCTOR:
+    case NJS_TOKEN_FUNCTION_CONSTRUCTOR:
+    case NJS_TOKEN_REGEXP_CONSTRUCTOR:
     case NJS_TOKEN_EVAL:
     case NJS_TOKEN_EXTERNAL:
         return NXT_OK;
index 0c00ae8ab3712f8501323a52d7e55744cf605db6..a632b6c3d57bd6f0ce3e3dafb8a4579757b85fba 100644 (file)
@@ -76,13 +76,13 @@ static const njs_keyword_t  njs_keywords[] = {
 
     /* Builtin functions. */
 
-    { nxt_string("Object"),        NJS_TOKEN_OBJECT_FUNCTION, 0 },
-    { nxt_string("Array"),         NJS_TOKEN_ARRAY_FUNCTION, 0 },
-    { nxt_string("Boolean"),       NJS_TOKEN_BOOLEAN_FUNCTION, 0 },
-    { nxt_string("Number"),        NJS_TOKEN_NUMBER_FUNCTION, 0 },
-    { nxt_string("String"),        NJS_TOKEN_STRING_FUNCTION, 0 },
-    { nxt_string("Function"),      NJS_TOKEN_FUNCTION_FUNCTION, 0 },
-    { nxt_string("RegExp"),        NJS_TOKEN_REGEXP_FUNCTION, 0 },
+    { nxt_string("Object"),        NJS_TOKEN_OBJECT_CONSTRUCTOR, 0 },
+    { nxt_string("Array"),         NJS_TOKEN_ARRAY_CONSTRUCTOR, 0 },
+    { nxt_string("Boolean"),       NJS_TOKEN_BOOLEAN_CONSTRUCTOR, 0 },
+    { nxt_string("Number"),        NJS_TOKEN_NUMBER_CONSTRUCTOR, 0 },
+    { nxt_string("String"),        NJS_TOKEN_STRING_CONSTRUCTOR, 0 },
+    { nxt_string("Function"),      NJS_TOKEN_FUNCTION_CONSTRUCTOR, 0 },
+    { nxt_string("RegExp"),        NJS_TOKEN_REGEXP_CONSTRUCTOR, 0 },
     { nxt_string("eval"),          NJS_TOKEN_EVAL, 0 },
 
     /* Reserved words. */
index 15d8bdb9e77783f5da53750a3aa5a1d73bf7da53..a8687a0308316ff288ac40893233b8957844c69d 100644 (file)
@@ -213,7 +213,7 @@ njs_number_to_string(njs_vm_t *vm, njs_value_t *string,
 
 
 njs_ret_t
-njs_number_function(njs_vm_t *vm, njs_param_t *param)
+njs_number_constructor(njs_vm_t *vm, njs_param_t *param)
 {
     njs_object_t       *object;
     const njs_value_t  *value;
@@ -227,7 +227,6 @@ njs_number_function(njs_vm_t *vm, njs_param_t *param)
     }
 
     if (vm->frame->ctor) {
-        /* value->type is the same as prototype offset. */
         object = njs_object_value_alloc(vm, value, value->type);
         if (nxt_slow_path(object == NULL)) {
             return NXT_ERROR;
@@ -245,7 +244,7 @@ njs_number_function(njs_vm_t *vm, njs_param_t *param)
 }
 
 
-static const njs_object_prop_t  njs_number_function_properties[] =
+static const njs_object_prop_t  njs_number_constructor_properties[] =
 {
     /* Number.name == "Number". */
     { njs_string("Number"),
@@ -258,18 +257,16 @@ static const njs_object_prop_t  njs_number_function_properties[] =
       NJS_PROPERTY, 0, 0, 0, },
 
     /* Number.prototype. */
-    { njs_getter(njs_object_prototype_create_prototype),
+    { njs_getter(njs_object_prototype_create),
       njs_string("prototype"),
       NJS_NATIVE_GETTER, 0, 0, 0, },
 };
 
 
-nxt_int_t
-njs_number_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_number_function_properties,
-                                  nxt_nitems(njs_number_function_properties));
-}
+const njs_object_init_t  njs_number_constructor_init = {
+     njs_number_constructor_properties,
+     nxt_nitems(njs_number_constructor_properties),
+};
 
 
 static njs_ret_t
@@ -334,9 +331,7 @@ static const njs_object_prop_t  njs_number_prototype_properties[] =
 };
 
 
-nxt_int_t
-njs_number_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_number_prototype_properties,
-                                  nxt_nitems(njs_number_prototype_properties));
-}
+const njs_object_init_t  njs_number_prototype_init = {
+     njs_number_prototype_properties,
+     nxt_nitems(njs_number_prototype_properties),
+};
index d59d22843b9a14bb433cde6a60d45bd47be7dfd8..26f23905074885a96b23ca9e05e428c9d35b686c 100644 (file)
@@ -28,9 +28,10 @@ double njs_number_parse(const u_char **start, const u_char *end);
 int64_t njs_hex_number_parse(u_char *p, u_char *end);
 njs_ret_t njs_number_to_string(njs_vm_t *vm, njs_value_t *string,
     const njs_value_t *number);
-njs_ret_t njs_number_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_number_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_number_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_number_constructor(njs_vm_t *vm, njs_param_t *param);
+
+extern const njs_object_init_t  njs_number_constructor_init;
+extern const njs_object_init_t  njs_number_prototype_init;
 
 
 #endif /* _NJS_NUMBER_H_INCLUDED_ */
index 2726586705a203b3329babb8751d4fc69cda8c1e..9f01f4c4903fe5bc09cb4e43898ab7b36e0c47fe 100644 (file)
 
 
 static nxt_int_t njs_object_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
-static nxt_int_t njs_object_null_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
 
 
 nxt_noinline njs_object_t *
 njs_object_alloc(njs_vm_t *vm)
 {
-    njs_object_t  *obj;
+    njs_object_t  *object;
 
-    obj = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
-                              sizeof(njs_object_t));
+    object = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_t));
 
-    if (nxt_fast_path(obj != NULL)) {
-        nxt_lvlhsh_init(&obj->hash);
-        nxt_lvlhsh_init(&obj->shared_hash);
-        obj->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
+    if (nxt_fast_path(object != NULL)) {
+        nxt_lvlhsh_init(&object->hash);
+        nxt_lvlhsh_init(&object->shared_hash);
+        object->__proto__ = &vm->prototypes[NJS_PROTOTYPE_OBJECT];
     }
 
-    return obj;
+    return object;
 }
 
 
 nxt_noinline njs_object_t *
-njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value,
-    nxt_uint_t prototype)
+njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value, nxt_uint_t type)
 {
-    njs_object_value_t  *obj;
+    nxt_uint_t          index;
+    njs_object_value_t  *ov;
+
+    ov = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_object_value_t));
+
+    if (nxt_fast_path(ov != NULL)) {
+        nxt_lvlhsh_init(&ov->object.hash);
+        nxt_lvlhsh_init(&ov->object.shared_hash);
 
-    obj = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
-                              sizeof(njs_object_value_t));
+        index = njs_primitive_prototype_index(type);
+        ov->object.__proto__ = &vm->prototypes[index];
 
-    if (nxt_fast_path(obj != NULL)) {
-        nxt_lvlhsh_init(&obj->object.hash);
-        nxt_lvlhsh_init(&obj->object.shared_hash);
-        obj->object.__proto__ = &vm->prototypes[prototype];
-        obj->value = *value;
+        ov->value = *value;
     }
 
-    return &obj->object;
+    return &ov->object;
 }
 
 
@@ -185,28 +185,28 @@ njs_object_method(njs_vm_t *vm, njs_param_t *param, nxt_lvlhsh_query_t *lhq)
 
 
 nxt_noinline njs_object_prop_t *
-njs_object_property(njs_vm_t *vm, njs_object_t *obj, nxt_lvlhsh_query_t *lhq)
+njs_object_property(njs_vm_t *vm, njs_object_t *object, nxt_lvlhsh_query_t *lhq)
 {
     nxt_int_t  ret;
 
     lhq->proto = &njs_object_hash_proto;
 
     do {
-        ret = nxt_lvlhsh_find(&obj->hash, lhq);
+        ret = nxt_lvlhsh_find(&object->hash, lhq);
 
         if (nxt_fast_path(ret == NXT_OK)) {
             return lhq->value;
         }
 
-        ret = nxt_lvlhsh_find(&obj->shared_hash, lhq);
+        ret = nxt_lvlhsh_find(&object->shared_hash, lhq);
 
         if (nxt_fast_path(ret == NXT_OK)) {
             return lhq->value;
         }
 
-        obj = obj->__proto__;
+        object = object->__proto__;
 
-    } while (obj != NULL);
+    } while (object != NULL);
 
     vm->exception = &njs_exception_type_error;
 
@@ -215,7 +215,7 @@ njs_object_property(njs_vm_t *vm, njs_object_t *obj, nxt_lvlhsh_query_t *lhq)
 
 
 njs_ret_t
-njs_object_function(njs_vm_t *vm, njs_param_t *param)
+njs_object_constructor(njs_vm_t *vm, njs_param_t *param)
 {
     nxt_uint_t    type;
     njs_value_t   *value;
@@ -267,36 +267,28 @@ static njs_ret_t
 njs_object_create(njs_vm_t *vm, njs_param_t *param)
 {
     njs_value_t   *args;
-    njs_object_t  *obj;
-
-    /* STUB: move to shared create to avoid threads locks. */
-    static nxt_lvlhsh_t  njs_null_proto_shared_hash;
+    njs_object_t  *object;
 
     if (param->nargs != 0) {
         args = param->args;
 
         if (njs_is_object(&args[0]) || njs_is_null(&args[0])) {
 
-            obj = njs_object_alloc(vm);
-            if (nxt_slow_path(obj == NULL)) {
+            object = njs_object_alloc(vm);
+            if (nxt_slow_path(object == NULL)) {
                 return NXT_ERROR;
             }
 
-            if (njs_is_null(&args[0])) {
-                if (nxt_lvlhsh_is_empty(&njs_null_proto_shared_hash)) {
-                    /* STUB */
-                    njs_object_null_hash(vm, &njs_null_proto_shared_hash);
-                }
-
-                obj->shared_hash = njs_null_proto_shared_hash;
-                obj->__proto__ = NULL;
+            if (!njs_is_null(&args[0])) {
+                /* GC */
+                object->__proto__ = args[0].data.u.object;
 
             } else {
-                /* GC */
-                obj->__proto__ = args[0].data.u.object;
+                object->shared_hash = vm->shared->null_proto_hash;
+                object->__proto__ = NULL;
             }
 
-            vm->retval.data.u.object = obj;
+            vm->retval.data.u.object = object;
             vm->retval.type = NJS_OBJECT;
             vm->retval.data.truth = 1;
 
@@ -310,22 +302,6 @@ njs_object_create(njs_vm_t *vm, njs_param_t *param)
 }
 
 
-static const njs_object_prop_t  njs_object_null_properties[] =
-{
-    { njs_value(NJS_NULL, 0, 0.0),
-      njs_string("__proto__"),
-      NJS_WHITEOUT, 0, 0, 0, },
-};
-
-
-static nxt_int_t
-njs_object_null_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_object_null_properties,
-                                  nxt_nitems(njs_object_null_properties));
-}
-
-
 /*
  * The __proto__ property of booleans, numbers and strings primitives
  * and Boolean.prototype, Number.prototype, and String.prototype objects.
@@ -334,20 +310,19 @@ njs_object_null_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
 njs_ret_t
 njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
 {
-    vm->retval.type = NJS_OBJECT;
-    vm->retval.data.truth = 1;
+    nxt_uint_t  index;
 
     /*
-     * The __proto__ getters reside in object prototypes of primitive
-     * types.  "AND 0x7" maps type of value to prototype offset:
-     *     NJS_BOOLEAN > NJS_PROTOTYPE_BOOLEAN,
-     *     NJS_NUMBER  > NJS_PROTOTYPE_NUMBER,
-     *     NJS_STRING  > NJS_PROTOTYPE_STRING,
-     *     NJS_OBJECT  > NJS_PROTOTYPE_OBJECT.
-     * So "".__proto__ points to String.prototype while
-     * String.prototype.__proto__ points to Object.prototype.
+     * The __proto__ getters reside in object prototypes of primitive types
+     * and have to return different results for primitive type and for object
+     * prototype.
      */
-    vm->retval.data.u.object = &vm->prototypes[value->type & 7];
+    index = njs_is_object(value) ? NJS_PROTOTYPE_OBJECT:
+                                   njs_primitive_prototype_index(value->type);
+
+    vm->retval.data.u.object = &vm->prototypes[index];
+    vm->retval.type = NJS_OBJECT;
+    vm->retval.data.truth = 1;
 
     return NXT_OK;
 }
@@ -360,14 +335,15 @@ njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
  */
 
 njs_ret_t
-njs_object_prototype_create_prototype(njs_vm_t *vm, njs_value_t *value)
+njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value)
 {
-    int32_t            index;
-    nxt_int_t          ret;
-    njs_object_t       *prototype;
-    njs_function_t     *function;
-    njs_object_prop_t  *prop;
-    nxt_lvlhsh_query_t  lhq;
+    int32_t                    index;
+    nxt_int_t                  ret;
+    njs_function_t             *function;
+    njs_object_prop_t          *prop;
+    nxt_lvlhsh_query_t         lhq;
+
+    static const njs_value_t   prototype = njs_string("prototype");
 
     function = value->data.u.function;
     index = function - vm->functions;
@@ -377,14 +353,12 @@ njs_object_prototype_create_prototype(njs_vm_t *vm, njs_value_t *value)
         return NXT_OK;
     }
 
-    prop = njs_object_prop_alloc(vm, &njs_string_prototype);
+    prop = njs_object_prop_alloc(vm, &prototype);
     if (nxt_slow_path(prop == NULL)) {
         return NXT_ERROR;
     }
 
-    prototype = &vm->prototypes[index];
-
-    prop->value.data.u.object = prototype;
+    prop->value.data.u.object = &vm->prototypes[index];
     prop->value.type = NJS_OBJECT;
     prop->value.data.truth = 1;
 
@@ -412,7 +386,7 @@ njs_object_prototype_create_prototype(njs_vm_t *vm, njs_value_t *value)
 }
 
 
-static const njs_object_prop_t  njs_object_function_properties[] =
+static const njs_object_prop_t  njs_object_constructor_properties[] =
 {
     /* Object.name == "name". */
     { njs_string("Object"),
@@ -425,7 +399,7 @@ static const njs_object_prop_t  njs_object_function_properties[] =
       NJS_PROPERTY, 0, 0, 0, },
 
     /* Object.prototype. */
-    { njs_getter(njs_object_prototype_create_prototype),
+    { njs_getter(njs_object_prototype_create),
       njs_string("prototype"),
       NJS_NATIVE_GETTER, 0, 0, 0, },
 
@@ -436,12 +410,10 @@ static const njs_object_prop_t  njs_object_function_properties[] =
 };
 
 
-nxt_int_t
-njs_object_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_object_function_properties,
-                                  nxt_nitems(njs_object_function_properties));
-}
+const njs_object_init_t  njs_object_constructor_init = {
+     njs_object_constructor_properties,
+     nxt_nitems(njs_object_constructor_properties),
+};
 
 
 static njs_ret_t
@@ -473,12 +445,14 @@ njs_object_prototype_get_proto(njs_vm_t *vm, njs_value_t *value)
 static njs_ret_t
 njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value)
 {
-    int32_t             index;
-    nxt_int_t           ret;
-    njs_value_t         *constructor;
-    njs_object_t        *prototype;
-    njs_object_prop_t   *prop;
-    nxt_lvlhsh_query_t  lhq;
+    int32_t                   index;
+    nxt_int_t                 ret;
+    njs_value_t               *constructor;
+    njs_object_t              *prototype;
+    njs_object_prop_t         *prop;
+    nxt_lvlhsh_query_t        lhq;
+
+    static const njs_value_t  constructor_string = njs_string("constructor");
 
     if (njs_is_object(value)) {
         prototype = value->data.u.object;
@@ -499,13 +473,13 @@ njs_object_prototype_create_constructor(njs_vm_t *vm, njs_value_t *value)
         return NXT_ERROR;
 
     } else {
-        index = NJS_PROTOTYPE_BOOLEAN + (value->type - NJS_BOOLEAN);
+        index = njs_primitive_prototype_index(value->type);
         prototype = &vm->prototypes[index];
     }
 
 found:
 
-    prop = njs_object_prop_alloc(vm, &njs_string_constructor);
+    prop = njs_object_prop_alloc(vm, &constructor_string);
     if (nxt_slow_path(prop == NULL)) {
         return NXT_ERROR;
     }
@@ -544,6 +518,25 @@ njs_object_prototype_value_of(njs_vm_t *vm, njs_param_t *param)
 }
 
 
+static const njs_value_t  njs_object_null_string = njs_string("[object Null]");
+static const njs_value_t  njs_object_undefined_string =
+                                     njs_long_string("[object Undefined]");
+static const njs_value_t  njs_object_boolean_string =
+                                     njs_long_string("[object Boolean]");
+static const njs_value_t  njs_object_number_string =
+                                     njs_long_string("[object Number]");
+static const njs_value_t  njs_object_string_string =
+                                     njs_long_string("[object String]");
+static const njs_value_t  njs_object_object_string =
+                                     njs_long_string("[object Object]");
+static const njs_value_t  njs_object_array_string =
+                                     njs_string("[object Array]");
+static const njs_value_t  njs_object_function_string =
+                                     njs_long_string("[object Function]");
+static const njs_value_t  njs_object_regexp_string =
+                                     njs_long_string("[object RegExp]");
+
+
 static njs_ret_t
 njs_object_prototype_to_string(njs_vm_t *vm, njs_param_t *param)
 {
@@ -553,24 +546,24 @@ njs_object_prototype_to_string(njs_vm_t *vm, njs_param_t *param)
 
     static const njs_value_t  *class_name[] = {
         /* Primitives. */
-        &njs_string_object_null,
-        &njs_string_object_undefined,
-        &njs_string_object_boolean,
-        &njs_string_object_number,
-        &njs_string_object_string,
-
-        &njs_string_object_function,
-        &njs_string_object_function,
+        &njs_object_null_string,
+        &njs_object_undefined_string,
+        &njs_object_boolean_string,
+        &njs_object_number_string,
+        &njs_object_string_string,
+
+        &njs_object_function_string,
+        &njs_object_function_string,
         &njs_string_empty,
 
         /* Objects. */
-        &njs_string_object_object,
-        &njs_string_object_array,
-        &njs_string_object_boolean,
-        &njs_string_object_number,
-        &njs_string_object_string,
-        &njs_string_object_function,
-        &njs_string_object_regexp,
+        &njs_object_object_string,
+        &njs_object_array_string,
+        &njs_object_boolean_string,
+        &njs_object_number_string,
+        &njs_object_string_string,
+        &njs_object_function_string,
+        &njs_object_regexp_string,
     };
 
     value = param->object;
@@ -624,9 +617,7 @@ static const njs_object_prop_t  njs_object_prototype_properties[] =
 };
 
 
-nxt_int_t
-njs_object_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_object_prototype_properties,
-                                  nxt_nitems(njs_object_prototype_properties));
-}
+const njs_object_init_t  njs_object_prototype_init = {
+     njs_object_prototype_properties,
+     nxt_nitems(njs_object_prototype_properties),
+};
index bdb7968444b47c97500da25f899e805d21806c8c..a645494aca54fda17de90f535423593a4cb80cce 100644 (file)
@@ -8,18 +8,6 @@
 #define _NJS_OBJECT_H_INCLUDED_
 
 
-struct njs_object_s {
-    /* A private hash of njs_object_prop_t. */
-    nxt_lvlhsh_t                hash;
-
-    /* A shared hash of njs_object_prop_t. */
-    nxt_lvlhsh_t                shared_hash;
-
-    /* An object __proto__. */
-    njs_object_t                *__proto__;
-};
-
-
 struct njs_object_value_s {
     njs_object_t                object;
     njs_value_t                 value;
@@ -49,22 +37,28 @@ typedef struct {
 } njs_object_prop_t;
 
 
+struct njs_object_init_s {
+    const njs_object_prop_t     *properties;
+    nxt_uint_t                  items;
+};
+
+
 njs_object_t *njs_object_alloc(njs_vm_t *vm);
 njs_object_t *njs_object_value_alloc(njs_vm_t *vm, const njs_value_t *value,
-    nxt_uint_t prototype);
+    nxt_uint_t type);
 njs_ret_t njs_object_method(njs_vm_t *vm, njs_param_t *param,
     nxt_lvlhsh_query_t *lhq);
 njs_object_prop_t *njs_object_property(njs_vm_t *vm, njs_object_t *obj,
     nxt_lvlhsh_query_t *lhq);
 nxt_int_t njs_object_hash_create(njs_vm_t *vm, nxt_lvlhsh_t *hash,
     const njs_object_prop_t *prop, nxt_uint_t n);
-njs_ret_t njs_object_function(njs_vm_t *vm, njs_param_t *param);
+njs_ret_t njs_object_constructor(njs_vm_t *vm, njs_param_t *param);
 njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name);
 njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value);
-njs_ret_t njs_object_prototype_create_prototype(njs_vm_t *vm,
-    njs_value_t *value);
-nxt_int_t njs_object_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_object_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value);
+
+extern const njs_object_init_t  njs_object_constructor_init;
+extern const njs_object_init_t  njs_object_prototype_init;
 
 
 #endif /* _NJS_OBJECT_H_INCLUDED_ */
index 753292b10a2a91285bf6c51fbd964c99855ff926..93b1647761289e8cb38dbfcc1c9645c1e7bb2f2a 100644 (file)
@@ -329,7 +329,6 @@ njs_parser_function_statement(njs_vm_t *vm, njs_parser_t *parser)
     value->data.u.function->code.script->u.parser = fn_parser;
 
     fn_parser->lexer = parser->lexer;
-    fn_parser->values_hash = vm->shared->values_hash;
 
     /* njs_vmcode_return() size. */
     fn_parser->code_size = sizeof(njs_vmcode_stop_t);
@@ -485,7 +484,6 @@ njs_parser_function_expression(njs_vm_t *vm, njs_parser_t *parser)
     func->u.parser = fn_parser;
 
     fn_parser->lexer = parser->lexer;
-    fn_parser->values_hash = vm->shared->values_hash;
 
     /* njs_vmcode_return() size. */
     fn_parser->code_size = sizeof(njs_vmcode_stop_t);
@@ -1410,31 +1408,31 @@ njs_parser_terminal(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token)
         node->index = NJS_INDEX_THIS;
         break;
 
-    case NJS_TOKEN_OBJECT_FUNCTION:
+    case NJS_TOKEN_OBJECT_CONSTRUCTOR:
         node->index = NJS_INDEX_OBJECT;
         break;
 
-    case NJS_TOKEN_ARRAY_FUNCTION:
+    case NJS_TOKEN_ARRAY_CONSTRUCTOR:
         node->index = NJS_INDEX_ARRAY;
         break;
 
-    case NJS_TOKEN_BOOLEAN_FUNCTION:
+    case NJS_TOKEN_BOOLEAN_CONSTRUCTOR:
         node->index = NJS_INDEX_BOOLEAN;
         break;
 
-    case NJS_TOKEN_NUMBER_FUNCTION:
+    case NJS_TOKEN_NUMBER_CONSTRUCTOR:
         node->index = NJS_INDEX_NUMBER;
         break;
 
-    case NJS_TOKEN_STRING_FUNCTION:
+    case NJS_TOKEN_STRING_CONSTRUCTOR:
         node->index = NJS_INDEX_STRING;
         break;
 
-    case NJS_TOKEN_FUNCTION_FUNCTION:
+    case NJS_TOKEN_FUNCTION_CONSTRUCTOR:
         node->index = NJS_INDEX_FUNCTION;
         break;
 
-    case NJS_TOKEN_REGEXP_FUNCTION:
+    case NJS_TOKEN_REGEXP_CONSTRUCTOR:
         node->index = NJS_INDEX_REGEXP;
         break;
 
index 4eb8480703a332b44282613d30dad1486201c468..69ca45562292893eda1fff2d9955e5b40b32d4e4 100644 (file)
@@ -160,13 +160,13 @@ typedef enum {
 
     NJS_TOKEN_THIS,
 
-    NJS_TOKEN_OBJECT_FUNCTION,
-    NJS_TOKEN_ARRAY_FUNCTION,
-    NJS_TOKEN_FUNCTION_FUNCTION,
-    NJS_TOKEN_REGEXP_FUNCTION,
-    NJS_TOKEN_BOOLEAN_FUNCTION,
-    NJS_TOKEN_NUMBER_FUNCTION,
-    NJS_TOKEN_STRING_FUNCTION,
+    NJS_TOKEN_OBJECT_CONSTRUCTOR,
+    NJS_TOKEN_ARRAY_CONSTRUCTOR,
+    NJS_TOKEN_FUNCTION_CONSTRUCTOR,
+    NJS_TOKEN_REGEXP_CONSTRUCTOR,
+    NJS_TOKEN_BOOLEAN_CONSTRUCTOR,
+    NJS_TOKEN_NUMBER_CONSTRUCTOR,
+    NJS_TOKEN_STRING_CONSTRUCTOR,
     NJS_TOKEN_EVAL,
 
     NJS_TOKEN_RESERVED,
@@ -241,8 +241,6 @@ struct njs_parser_s {
     nxt_array_t                     *arguments;
 
     nxt_lvlhsh_t                    variables_hash;
-    nxt_lvlhsh_t                    values_hash;
-    nxt_lvlhsh_t                    functions_hash;
 
     nxt_array_t                     *index_cache;
     njs_index_t                     index[NJS_SCOPES - NJS_INDEX_CACHE];
@@ -252,6 +250,9 @@ struct njs_parser_s {
     uint8_t                         scope;        /* 4 bits */
     uint8_t                         branch;       /* 1 bit */
 
+    /* Parsing Function() or eval(). */
+    uint8_t                         runtime;      /* 1 bit */
+
     size_t                          code_size;
 
     /* Generator. */
index 2f93f3509f47a0419824d4d240483d725157e157..e50f55f61eb292be4818b51fbaf27c799380fd10 100644 (file)
@@ -916,13 +916,13 @@ njs_parser_call_expression(njs_vm_t *vm, njs_parser_t *parser,
                                  + sizeof(njs_vmcode_call_t);
             break;
 
-        case NJS_TOKEN_OBJECT_FUNCTION:
-        case NJS_TOKEN_ARRAY_FUNCTION:
-        case NJS_TOKEN_BOOLEAN_FUNCTION:
-        case NJS_TOKEN_NUMBER_FUNCTION:
-        case NJS_TOKEN_STRING_FUNCTION:
-        case NJS_TOKEN_FUNCTION_FUNCTION:
-        case NJS_TOKEN_REGEXP_FUNCTION:
+        case NJS_TOKEN_OBJECT_CONSTRUCTOR:
+        case NJS_TOKEN_ARRAY_CONSTRUCTOR:
+        case NJS_TOKEN_BOOLEAN_CONSTRUCTOR:
+        case NJS_TOKEN_NUMBER_CONSTRUCTOR:
+        case NJS_TOKEN_STRING_CONSTRUCTOR:
+        case NJS_TOKEN_FUNCTION_CONSTRUCTOR:
+        case NJS_TOKEN_REGEXP_CONSTRUCTOR:
         case NJS_TOKEN_EVAL:
             func = njs_parser_node_alloc(vm);
             if (nxt_slow_path(func == NULL)) {
index 3829fd20bc0d5a2b208f6c0fdc8c74f3a91caf24..c9c3f403d418317f27dcdb2ac5aca3b615415263 100644 (file)
@@ -38,7 +38,7 @@ static njs_ret_t njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp,
 
 
 njs_ret_t
-njs_regexp_function(njs_vm_t *vm, njs_param_t *param)
+njs_regexp_constructor(njs_vm_t *vm, njs_param_t *param)
 {
     size_t                length;
     njs_regexp_t          *regexp;
@@ -341,8 +341,7 @@ njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern)
 {
     njs_regexp_t  *regexp;
 
-    regexp = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
-                                 sizeof(njs_regexp_t));
+    regexp = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_regexp_t));
 
     if (nxt_fast_path(regexp != NULL)) {
         nxt_lvlhsh_init(&regexp->object.hash);
@@ -664,7 +663,7 @@ njs_regexp_exec_result(njs_vm_t *vm, njs_regexp_t *regexp, u_char *string,
 }
 
 
-static const njs_object_prop_t  njs_regexp_function_properties[] =
+static const njs_object_prop_t  njs_regexp_constructor_properties[] =
 {
     /* RegExp.name == "RegExp". */
     { njs_string("RegExp"),
@@ -677,18 +676,16 @@ static const njs_object_prop_t  njs_regexp_function_properties[] =
       NJS_PROPERTY, 0, 0, 0, },
 
     /* RegExp.prototype. */
-    { njs_getter(njs_object_prototype_create_prototype),
+    { njs_getter(njs_object_prototype_create),
       njs_string("prototype"),
       NJS_NATIVE_GETTER, 0, 0, 0, },
 };
 
 
-nxt_int_t
-njs_regexp_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_regexp_function_properties,
-                                  nxt_nitems(njs_regexp_function_properties));
-}
+const njs_object_init_t  njs_regexp_constructor_init = {
+     njs_regexp_constructor_properties,
+     nxt_nitems(njs_regexp_constructor_properties),
+};
 
 
 static const njs_object_prop_t  njs_regexp_prototype_properties[] =
@@ -727,12 +724,10 @@ static const njs_object_prop_t  njs_regexp_prototype_properties[] =
 };
 
 
-nxt_int_t
-njs_regexp_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_regexp_prototype_properties,
-                                  nxt_nitems(njs_regexp_prototype_properties));
-}
+const njs_object_init_t  njs_regexp_prototype_init = {
+     njs_regexp_prototype_properties,
+     nxt_nitems(njs_regexp_prototype_properties),
+};
 
 
 void
index 62361337367d19287f0274658653959ebed0f42c..86a24475c826ccee2e89402066847e390f42074f 100644 (file)
@@ -32,16 +32,17 @@ struct njs_regexp_s {
 };
 
 
-njs_ret_t njs_regexp_function(njs_vm_t *vm, njs_param_t *param);
+njs_ret_t njs_regexp_constructor(njs_vm_t *vm, njs_param_t *param);
 nxt_int_t njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser,
     njs_value_t *value);
 njs_regexp_pattern_t *njs_regexp_pattern_create(njs_vm_t *vm,
     u_char *string, size_t length, njs_regexp_flags_t flags);
 njs_regexp_t *njs_regexp_alloc(njs_vm_t *vm, njs_regexp_pattern_t *pattern);
 njs_ret_t njs_regexp_prototype_exec(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_regexp_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
-nxt_int_t njs_regexp_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
 void njs_regexp_pattern_free(njs_regexp_pattern_t *pattern);
 
+extern const njs_object_init_t  njs_regexp_constructor_init;
+extern const njs_object_init_t  njs_regexp_prototype_init;
+
 
 #endif /* _NJS_REGEXP_H_INCLUDED_ */
diff --git a/njs/njs_shared.c b/njs/njs_shared.c
deleted file mode 100644 (file)
index b01bfcb..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-#include <nxt_types.h>
-#include <nxt_clang.h>
-#include <nxt_stub.h>
-#include <nxt_array.h>
-#include <nxt_lvlhsh.h>
-#include <nxt_mem_cache_pool.h>
-#include <njscript.h>
-#include <njs_vm.h>
-#include <njs_boolean.h>
-#include <njs_number.h>
-#include <njs_string.h>
-#include <njs_object.h>
-#include <njs_array.h>
-#include <njs_function.h>
-#include <njs_regexp.h>
-#include <string.h>
-
-
-typedef nxt_int_t (*njs_shared_hash_t) (njs_vm_t *vm, nxt_lvlhsh_t *hash);
-
-
-nxt_int_t
-njs_shared_objects_create(njs_vm_t *vm)
-{
-    size_t          size;
-    nxt_int_t       ret;
-    nxt_uint_t      i;
-    njs_object_t    *prototypes;
-    njs_function_t  *functions;
-
-    static const njs_shared_hash_t  prototype_hash[] = {
-        njs_object_prototype_hash,
-        njs_array_prototype_hash,
-        njs_boolean_prototype_hash,
-        njs_number_prototype_hash,
-        njs_string_prototype_hash,
-        njs_function_prototype_hash,
-        njs_regexp_prototype_hash,
-    };
-
-    static const njs_shared_hash_t  function_hash[] = {
-        njs_object_function_hash,
-        njs_array_function_hash,
-        njs_boolean_function_hash,
-        njs_number_function_hash,
-        njs_string_function_hash,
-        njs_function_function_hash,
-        njs_regexp_function_hash,
-
-        njs_eval_function_hash,
-    };
-
-    static const njs_native_t       native_functions[] = {
-        njs_object_function,
-        njs_array_function,
-        njs_boolean_function,
-        njs_number_function,
-        njs_string_ctor_function,
-        njs_function_function,
-        njs_regexp_function,
-
-        njs_eval_function,
-    };
-
-    size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t);
-
-    prototypes = nxt_mem_cache_zalign(vm->mem_cache_pool, sizeof(njs_value_t),
-                                      size);
-    if (nxt_slow_path(prototypes == NULL)) {
-        return NXT_ERROR;
-    }
-
-    vm->shared->prototypes = prototypes;
-
-    for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
-        /* TODO: shared hash: prototype & constructor getters, methods */
-
-        ret = prototype_hash[i](vm, &prototypes[i].shared_hash);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return NXT_ERROR;
-        }
-    }
-
-    size = NJS_FUNCTION_MAX * sizeof(njs_function_t);
-
-    functions = nxt_mem_cache_zalign(vm->mem_cache_pool, sizeof(njs_value_t),
-                                     size);
-    if (nxt_slow_path(functions == NULL)) {
-        return NXT_ERROR;
-    }
-
-    vm->shared->functions = functions;
-
-    for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
-        functions[i].native = 1;
-        functions[i].args_offset = 1;
-        functions[i].code.native = native_functions[i];
-
-        ret = function_hash[i](vm, &functions[i].object.shared_hash);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return NXT_ERROR;
-        }
-    }
-
-    /* TODO: create function shared hash: prototype+contructor getter */
-
-    return NXT_OK;
-}
-
-
-/*
- * Object(),
- * Object.__proto__             -> Function_Prototype,
- * Object_Prototype.__proto__   -> null,
- *   the null value is handled by njs_object_prototype_get_proto(),
- *
- * Array(),
- * Array.__proto__              -> Function_Prototype,
- * Array_Prototype.__proto__    -> Object_Prototype,
- *
- * Boolean(),
- * Boolean.__proto__            -> Function_Prototype,
- * Boolean_Prototype.__proto__  -> Object_Prototype,
- *
- * Number(),
- * Number.__proto__             -> Function_Prototype,
- * Number_Prototype.__proto__   -> Object_Prototype,
- *
- * String(),
- * String.__proto__             -> Function_Prototype,
- * String_Prototype.__proto__   -> Object_Prototype,
- *
- * Function(),
- * Function.__proto__           -> Function_Prototype,
- * Function_Prototype.__proto__ -> Object_Prototype,
- *
- * RegExp(),
- * RegExp.__proto__             -> Function_Prototype,
- * RegExp_Prototype.__proto__   -> Object_Prototype,
- *
- * eval(),
- * eval.__proto__               -> Function_Prototype.
- */
-
-nxt_int_t
-njs_shared_objects_clone(njs_vm_t *vm)
-{
-    size_t          size;
-    nxt_uint_t      i;
-    njs_value_t     *values;
-    njs_object_t    *prototypes;
-    njs_function_t  *functions;
-
-    size = NJS_PROTOTYPE_MAX * sizeof(njs_object_t);
-
-    prototypes = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
-                                     size);
-    if (nxt_slow_path(prototypes == NULL)) {
-        return NXT_ERROR;
-    }
-
-    vm->prototypes = prototypes;
-
-    memcpy(prototypes, vm->shared->prototypes, size);
-
-    for (i = NJS_PROTOTYPE_ARRAY; i < NJS_PROTOTYPE_MAX; i++) {
-        prototypes[i].__proto__ = &prototypes[NJS_PROTOTYPE_OBJECT];
-    }
-
-    size = NJS_FUNCTION_MAX * sizeof(njs_function_t);
-
-    functions = nxt_mem_cache_align(vm->mem_cache_pool, sizeof(njs_value_t),
-                                    size);
-    if (nxt_slow_path(functions == NULL)) {
-        return NXT_ERROR;
-    }
-
-    vm->functions = functions;
-
-    memcpy(functions, vm->shared->functions, size);
-
-    values = vm->scopes[NJS_SCOPE_GLOBAL];
-
-    for (i = NJS_FUNCTION_OBJECT; i < NJS_FUNCTION_MAX; i++) {
-        values[i].type = NJS_FUNCTION;
-        values[i].data.truth = 1;
-        values[i].data.u.function = &functions[i];
-        functions[i].object.__proto__ = &prototypes[NJS_FUNCTION_FUNCTION];
-    }
-
-    return NXT_OK;
-}
index e3c28eaf13a624cda7d9ca6f83463bdb9a155b5a..bdc45b721c99f49891a617d2b5eaa4dbd8b08746 100644 (file)
@@ -251,7 +251,7 @@ njs_string_prop(njs_string_prop_t *string, njs_value_t *value)
 
 
 njs_ret_t
-njs_string_ctor_function(njs_vm_t *vm, njs_param_t *param)
+njs_string_constructor(njs_vm_t *vm, njs_param_t *param)
 {
     njs_object_t       *object;
     const njs_value_t  *value;
@@ -265,7 +265,6 @@ njs_string_ctor_function(njs_vm_t *vm, njs_param_t *param)
     }
 
     if (vm->frame->ctor) {
-        /* value->type is the same as prototype offset. */
         object = njs_object_value_alloc(vm, value, value->type);
         if (nxt_slow_path(object == NULL)) {
             return NXT_ERROR;
@@ -283,7 +282,7 @@ njs_string_ctor_function(njs_vm_t *vm, njs_param_t *param)
 }
 
 
-static const njs_object_prop_t  njs_string_function_properties[] =
+static const njs_object_prop_t  njs_string_constructor_properties[] =
 {
     /* String.name == "String". */
     { njs_string("String"),
@@ -296,18 +295,16 @@ static const njs_object_prop_t  njs_string_function_properties[] =
       NJS_PROPERTY, 0, 0, 0, },
 
     /* String.prototype. */
-    { njs_getter(njs_object_prototype_create_prototype),
+    { njs_getter(njs_object_prototype_create),
       njs_string("prototype"),
       NJS_NATIVE_GETTER, 0, 0, 0, },
 };
 
 
-nxt_int_t
-njs_string_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_string_function_properties,
-                                  nxt_nitems(njs_string_function_properties));
-}
+const njs_object_init_t  njs_string_constructor_init = {
+     njs_string_constructor_properties,
+     nxt_nitems(njs_string_constructor_properties),
+};
 
 
 static njs_ret_t
@@ -1680,12 +1677,10 @@ static const njs_object_prop_t  njs_string_prototype_properties[] =
 };
 
 
-nxt_int_t
-njs_string_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash)
-{
-    return njs_object_hash_create(vm, hash, njs_string_prototype_properties,
-                                  nxt_nitems(njs_string_prototype_properties));
-}
+const njs_object_init_t  njs_string_prototype_init = {
+     njs_string_prototype_properties,
+     nxt_nitems(njs_string_prototype_properties),
+};
 
 
 static nxt_int_t
@@ -1725,7 +1720,7 @@ static const nxt_lvlhsh_proto_t  njs_values_hash_proto
 
 
 /*
- * Constant values such as njs_value_zero are copied to vm->values_hash during
+ * Constant values such as njs_value_true are copied to values_hash during
  * code generation when them are used as operands to guarantee aligned value.
  */
 
@@ -1737,6 +1732,7 @@ njs_value_index(njs_vm_t *vm, njs_parser_t *parser, const njs_value_t *src)
     nxt_int_t           ret;
     njs_value_t         *value;
     njs_string_t        *string;
+    nxt_lvlhsh_t        *values_hash;
     nxt_lvlhsh_query_t  lhq;
 
     if (src->type != NJS_STRING || src->short_string.size != NJS_STRING_LONG) {
@@ -1753,10 +1749,12 @@ njs_value_index(njs_vm_t *vm, njs_parser_t *parser, const njs_value_t *src)
     lhq.key.data = start;
     lhq.proto = &njs_values_hash_proto;
 
-    if (nxt_lvlhsh_find(&vm->values_hash, &lhq) == NXT_OK) {
+    if (nxt_lvlhsh_find(&vm->shared->values_hash, &lhq) == NXT_OK) {
         value = lhq.value;
 
-    } else if (nxt_lvlhsh_find(&parser->values_hash, &lhq) == NXT_OK) {
+    } else if (parser->runtime
+               && nxt_lvlhsh_find(&vm->values_hash, &lhq) == NXT_OK)
+    {
         value = lhq.value;
 
     } else {
@@ -1798,7 +1796,10 @@ njs_value_index(njs_vm_t *vm, njs_parser_t *parser, const njs_value_t *src)
         lhq.value = value;
         lhq.pool = vm->mem_cache_pool;
 
-        ret = nxt_lvlhsh_insert(&parser->values_hash, &lhq);
+        values_hash = parser->runtime ? &vm->values_hash:
+                                        &vm->shared->values_hash;
+
+        ret = nxt_lvlhsh_insert(values_hash, &lhq);
 
         if (nxt_slow_path(ret != NXT_OK)) {
             return NJS_INDEX_NONE;
index 01199202d7c1542abc840ab2950815ffc64d591d..383724530942f857a27f5eafd1dabafe4e730499 100644 (file)
@@ -88,8 +88,7 @@ njs_ret_t njs_string_validate(njs_vm_t *vm, njs_string_prop_t *string,
     njs_value_t *value);
 nxt_noinline size_t njs_string_prop(njs_string_prop_t *string,
     njs_value_t *value);
-njs_ret_t njs_string_ctor_function(njs_vm_t *vm, njs_param_t *param);
-nxt_int_t njs_string_function_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
+njs_ret_t njs_string_constructor(njs_vm_t *vm, njs_param_t *param);
 void njs_string_offset_map_init(const u_char *start, size_t size);
 nxt_bool_t njs_string_eq(const njs_value_t *val1, const njs_value_t *val2);
 nxt_int_t njs_string_cmp(const njs_value_t *val1, const njs_value_t *val2);
@@ -104,10 +103,12 @@ njs_ret_t njs_value_to_string(njs_vm_t *vm, njs_value_t *dst,
 njs_ret_t njs_value_to_ext_string(njs_vm_t *vm, nxt_str_t *dst,
     const njs_value_t *src);
 double njs_string_to_number(njs_value_t *value);
-nxt_int_t njs_string_prototype_hash(njs_vm_t *vm, nxt_lvlhsh_t *hash);
 
 njs_index_t njs_value_index(njs_vm_t *vm, njs_parser_t *parser,
     const njs_value_t *src);
 
+extern const njs_object_init_t  njs_string_constructor_init;
+extern const njs_object_init_t  njs_string_prototype_init;
+
 
 #endif /* _NJS_STRING_H_INCLUDED_ */
index 41c973f6412009a6ab68247bbc4b51c6004dac3b..ae99d4543816e7038db3ab2c4c4e0bea7a105d7e 100644 (file)
@@ -95,8 +95,8 @@ const njs_value_t  njs_value_nan =          njs_value(NJS_NUMBER, 0, NJS_NAN);
 
 const njs_value_t  njs_string_empty =       njs_string("");
 const njs_value_t  njs_string_comma =       njs_string(",");
-const njs_value_t  njs_string_void =        njs_string("undefined");
 const njs_value_t  njs_string_null =        njs_string("null");
+const njs_value_t  njs_string_void =        njs_string("undefined");
 const njs_value_t  njs_string_boolean =     njs_string("boolean");
 const njs_value_t  njs_string_false =       njs_string("false");
 const njs_value_t  njs_string_true =        njs_string("true");
@@ -110,25 +110,6 @@ const njs_value_t  njs_string_string =      njs_string("string");
 const njs_value_t  njs_string_object =      njs_string("object");
 const njs_value_t  njs_string_function =    njs_string("function");
 const njs_value_t  njs_string_native =      njs_string("[native code]");
-const njs_value_t  njs_string_prototype =   njs_string("prototype");
-const njs_value_t  njs_string_constructor = njs_string("constructor");
-
-const njs_value_t  njs_string_object_null = njs_string("[object Null]");
-const njs_value_t  njs_string_object_undefined =
-                                         njs_long_string("[object Undefined]");
-const njs_value_t  njs_string_object_boolean =
-                                         njs_long_string("[object Boolean]");
-const njs_value_t  njs_string_object_number =
-                                         njs_long_string("[object Number]");
-const njs_value_t  njs_string_object_string =
-                                         njs_long_string("[object String]");
-const njs_value_t  njs_string_object_object =
-                                         njs_long_string("[object Object]");
-const njs_value_t  njs_string_object_array = njs_string("[object Array]");
-const njs_value_t  njs_string_object_function =
-                                         njs_long_string("[object Function]");
-const njs_value_t  njs_string_object_regexp =
-                                         njs_long_string("[object RegExp]");
 
 const njs_value_t  njs_exception_syntax_error =    njs_string("SyntaxError");
 const njs_value_t  njs_exception_reference_error = njs_string("ReferenceError");
@@ -874,7 +855,7 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object,
             return NJS_PRIMITIVE_VALUE;
         }
 
-        obj = &vm->prototypes[object->type];
+        obj = &vm->prototypes[njs_primitive_prototype_index(object->type)];
         break;
 
     case NJS_STRING:
index 4ff1a3024a2173f8fbf58a707193add7c2004dd3..133feeafff98cc6a51fd1877bac034a03f604151 100644 (file)
@@ -58,10 +58,9 @@ typedef enum {
     /*
      * The object types have the third bit set.  It is used in njs_is_object().
      * NJS_OBJECT_BOOLEAN, NJS_OBJECT_NUMBER, and NJS_OBJECT_STRING must be
-     * equal to NJS_BOOLEAN, NJS_NUMBER, and NJS_STRING respectively with
-     * the third bit set.  It is used in njs_primitive_prototype_get_proto()
-     * and in njs_property_query().  The order of object types is used in
-     * vm->prototypes and vm->functions arrays.
+     * in the same order as NJS_BOOLEAN, NJS_NUMBER, and NJS_STRING.  It is
+     * used in njs_primitive_prototype_index().  The order of object types
+     * is used in vm->prototypes and vm->functions arrays.
      */
     NJS_OBJECT          = 0x08,
     NJS_ARRAY           = 0x09,
@@ -80,10 +79,9 @@ typedef njs_ret_t (*njs_native_t) (njs_vm_t *vm, njs_param_t *param);
 
 
 typedef struct njs_string_s           njs_string_t;
-typedef struct njs_object_s           njs_object_t;
-typedef struct njs_array_s            njs_array_t;
+typedef struct njs_object_init_s      njs_object_init_t;
 typedef struct njs_object_value_s     njs_object_value_t;
-typedef struct njs_function_s         njs_function_t;
+typedef struct njs_array_s            njs_array_t;
 typedef struct njs_function_script_s  njs_function_script_t;
 typedef struct njs_regexp_s           njs_regexp_t;
 typedef struct njs_regexp_pattern_s   njs_regexp_pattern_t;
@@ -91,6 +89,40 @@ typedef struct njs_extern_s           njs_extern_t;
 typedef struct njs_native_frame_s     njs_native_frame_t;
 
 
+typedef struct njs_object_s           njs_object_t;
+
+struct njs_object_s {
+    /* A private hash of njs_object_prop_t. */
+    nxt_lvlhsh_t                      hash;
+
+    /* A shared hash of njs_object_prop_t. */
+    nxt_lvlhsh_t                      shared_hash;
+
+    /* An object __proto__. */
+    njs_object_t                      *__proto__;
+};
+
+
+typedef struct {
+    njs_object_t                      object;
+
+#if (NXT_64BIT)
+    uint32_t                          native;
+    uint32_t                          args_offset;
+#else
+    uint8_t                           native;
+    uint16_t                          args_offset;
+#endif
+
+    union {
+        njs_function_script_t         *script;
+        njs_native_t                  native;
+    } code;
+
+    njs_value_t                       *args;
+} njs_function_t;
+
+
 union njs_value_s {
     /*
      * The njs_value_t size is 16 bytes and must be aligned to 16 bytes
@@ -556,28 +588,32 @@ typedef enum {
 
 
 enum njs_prototypes_e {
-    NJS_PROTOTYPE_OBJECT = 0,
+    NJS_PROTOTYPE_OBJECT =   0,
     NJS_PROTOTYPE_ARRAY,
     NJS_PROTOTYPE_BOOLEAN,
     NJS_PROTOTYPE_NUMBER,
     NJS_PROTOTYPE_STRING,
     NJS_PROTOTYPE_FUNCTION,
     NJS_PROTOTYPE_REGEXP,
-#define NJS_PROTOTYPE_MAX  (NJS_PROTOTYPE_REGEXP + 1)
+#define NJS_PROTOTYPE_MAX    (NJS_PROTOTYPE_REGEXP + 1)
 };
 
 
+#define njs_primitive_prototype_index(type)                                   \
+    (NJS_PROTOTYPE_BOOLEAN + ((type) - NJS_BOOLEAN))
+
+
 enum njs_functions_e {
-    NJS_FUNCTION_OBJECT = NJS_PROTOTYPE_OBJECT,
-    NJS_FUNCTION_ARRAY = NJS_PROTOTYPE_ARRAY,
-    NJS_FUNCTION_BOOLEAN = NJS_PROTOTYPE_BOOLEAN,
-    NJS_FUNCTION_NUMBER = NJS_PROTOTYPE_NUMBER,
-    NJS_FUNCTION_STRING = NJS_PROTOTYPE_STRING,
-    NJS_FUNCTION_FUNCTION = NJS_PROTOTYPE_FUNCTION,
-    NJS_FUNCTION_REGEXP = NJS_PROTOTYPE_REGEXP,
+    NJS_FUNCTION_OBJECT =    NJS_PROTOTYPE_OBJECT,
+    NJS_FUNCTION_ARRAY =     NJS_PROTOTYPE_ARRAY,
+    NJS_FUNCTION_BOOLEAN =   NJS_PROTOTYPE_BOOLEAN,
+    NJS_FUNCTION_NUMBER =    NJS_PROTOTYPE_NUMBER,
+    NJS_FUNCTION_STRING =    NJS_PROTOTYPE_STRING,
+    NJS_FUNCTION_FUNCTION =  NJS_PROTOTYPE_FUNCTION,
+    NJS_FUNCTION_REGEXP =    NJS_PROTOTYPE_REGEXP,
 
     NJS_FUNCTION_EVAL,
-#define NJS_FUNCTION_MAX  (NJS_FUNCTION_EVAL + 1)
+#define NJS_FUNCTION_MAX     (NJS_FUNCTION_EVAL + 1)
 };
 
 
@@ -642,11 +678,10 @@ struct njs_vm_s {
 
     nxt_lvlhsh_t             externals_hash;
     nxt_lvlhsh_t             variables_hash;
-    nxt_lvlhsh_t             functions_hash;
     nxt_lvlhsh_t             values_hash;
 
-    njs_object_t             *prototypes;
-    njs_function_t           *functions;
+    njs_object_t             prototypes[NJS_PROTOTYPE_MAX];
+    njs_function_t           functions[NJS_FUNCTION_MAX];
 
     nxt_mem_cache_pool_t     *mem_cache_pool;
 
@@ -670,9 +705,10 @@ typedef struct {
 struct njs_vm_shared_s {
     nxt_lvlhsh_t             keywords_hash;
     nxt_lvlhsh_t             values_hash;
+    nxt_lvlhsh_t             null_proto_hash;
 
-    njs_object_t             *prototypes;
-    njs_function_t           *functions;
+    njs_object_t             prototypes[NJS_PROTOTYPE_MAX];
+    njs_function_t           functions[NJS_FUNCTION_MAX];
 };
 
 
@@ -809,8 +845,8 @@ njs_ret_t njs_vmcode_restart(njs_vm_t *vm, njs_value_t *invld1,
 
 nxt_noinline void njs_number_set(njs_value_t *value, double num);
 
-nxt_int_t njs_shared_objects_create(njs_vm_t *vm);
-nxt_int_t njs_shared_objects_clone(njs_vm_t *vm);
+nxt_int_t njs_builtin_objects_create(njs_vm_t *vm);
+nxt_int_t njs_builtin_objects_clone(njs_vm_t *vm);
 
 
 void *njs_lvlhsh_alloc(void *data, size_t size, nxt_uint_t nalloc);
@@ -834,18 +870,6 @@ extern const njs_value_t  njs_string_native;
 extern const njs_value_t  njs_string_minus_infinity;
 extern const njs_value_t  njs_string_plus_infinity;
 extern const njs_value_t  njs_string_nan;
-extern const njs_value_t  njs_string_prototype;
-extern const njs_value_t  njs_string_constructor;
-
-extern const njs_value_t  njs_string_object_null;
-extern const njs_value_t  njs_string_object_undefined;
-extern const njs_value_t  njs_string_object_boolean;
-extern const njs_value_t  njs_string_object_number;
-extern const njs_value_t  njs_string_object_string;
-extern const njs_value_t  njs_string_object_object;
-extern const njs_value_t  njs_string_object_array;
-extern const njs_value_t  njs_string_object_function;
-extern const njs_value_t  njs_string_object_regexp;
 
 extern const njs_value_t  njs_exception_syntax_error;
 extern const njs_value_t  njs_exception_reference_error;
index 8103830635e2b5c71985301f4cafeebdb0a2ba04..49eef4b0a1c3321b534bc899930fa604392c6b6b 100644 (file)
@@ -99,11 +99,12 @@ njs_vm_t *
 njs_vm_create(nxt_mem_cache_pool_t *mcp, njs_vm_shared_t **shared,
     nxt_lvlhsh_t *externals)
 {
-    njs_vm_t  *vm;
+    njs_vm_t   *vm;
+    nxt_int_t  ret;
 
     if (mcp == NULL) {
         mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL,
-                                       NULL, 2 * nxt_pagesize(), 128, 512, 16);
+                                        NULL, 2 * nxt_pagesize(), 128, 512, 16);
         if (nxt_slow_path(mcp == NULL)) {
             return NULL;
         }
@@ -114,18 +115,39 @@ njs_vm_create(nxt_mem_cache_pool_t *mcp, njs_vm_shared_t **shared,
     if (nxt_fast_path(vm != NULL)) {
         vm->mem_cache_pool = mcp;
 
-        if (shared != NULL) {
+        if (shared != NULL && *shared != NULL) {
+            vm->shared = *shared;
 
-            if (*shared == NULL) {
-                *shared = nxt_mem_cache_zalloc(mcp, sizeof(njs_vm_shared_t));
-                if (nxt_slow_path(*shared == NULL)) {
-                    return NULL;
-                }
+        } else {
+            vm->shared = nxt_mem_cache_zalloc(mcp, sizeof(njs_vm_shared_t));
+
+            if (nxt_slow_path(vm->shared == NULL)) {
+                return NULL;
             }
 
-            vm->shared = *shared;
+            if (shared != NULL) {
+                *shared = vm->shared;
+            }
+
+            nxt_lvlhsh_init(&vm->shared->keywords_hash);
+
+            ret = njs_lexer_keywords_init(mcp, &vm->shared->keywords_hash);
+
+            if (nxt_slow_path(ret != NXT_OK)) {
+                return NULL;
+            }
+
+            nxt_lvlhsh_init(&vm->shared->values_hash);
+
+            ret = njs_builtin_objects_create(vm);
+
+            if (nxt_slow_path(ret != NXT_OK)) {
+                return NULL;
+            }
         }
 
+        nxt_lvlhsh_init(&vm->values_hash);
+
         if (externals != NULL) {
             vm->externals_hash = *externals;
         }
@@ -150,7 +172,6 @@ njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end)
     nxt_int_t          ret;
     njs_lexer_t        *lexer;
     njs_parser_t       *parser;
-    nxt_lvlhsh_t       keywords_hash;
     njs_parser_node_t  *node;
 
     parser = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_parser_t));
@@ -166,39 +187,9 @@ njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end)
     }
 
     parser->lexer = lexer;
-
-    if (vm->shared != NULL) {
-        keywords_hash = vm->shared->keywords_hash;
-        parser->values_hash = vm->shared->values_hash;
-
-        /* STUB */
-        if (vm->shared->prototypes == NULL) {
-            ret = njs_shared_objects_create(vm);
-            if (nxt_slow_path(ret != NXT_OK)) {
-                return NJS_ERROR;
-            }
-        }
-
-    } else {
-        nxt_lvlhsh_init(&keywords_hash);
-    }
-
-    if (nxt_lvlhsh_is_empty(&keywords_hash)) {
-
-        ret = njs_lexer_keywords_init(vm->mem_cache_pool, &keywords_hash);
-        if (nxt_slow_path(ret != NXT_OK)) {
-            return NJS_ERROR;
-        }
-
-        if (vm->shared != NULL) {
-            vm->shared->keywords_hash = keywords_hash;
-        }
-    }
-
-    parser->lexer->keywords_hash = keywords_hash;
-
-    parser->lexer->start = *start;
-    parser->lexer->end = end;
+    lexer->start = *start;
+    lexer->end = end;
+    lexer->keywords_hash = vm->shared->keywords_hash;
 
     parser->code_size = sizeof(njs_vmcode_stop_t);
     parser->scope = NJS_SCOPE_GLOBAL;
@@ -236,13 +227,7 @@ njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end)
 
     vm->global_scope = parser->local_scope;
     vm->scope_size = parser->scope_size;
-
     vm->variables_hash = parser->variables_hash;
-    vm->values_hash = parser->values_hash;
-
-    if (vm->shared != NULL) {
-        vm->shared->values_hash = parser->values_hash;
-    }
 
     vm->parser = NULL;
 
@@ -322,7 +307,7 @@ njs_vm_clone(njs_vm_t *vm, nxt_mem_cache_pool_t *mcp, void **external)
         memcpy(values + NJS_INDEX_GLOBAL_OFFSET, vm->global_scope,
                vm->scope_size);
 
-        ret = njs_shared_objects_clone(nvm);
+        ret = njs_builtin_objects_clone(nvm);
         if (nxt_slow_path(ret != NXT_OK)) {
             goto fail;
         }