From 15ed3ce9e9e3d53f5028ea1668e0331fbe9a292d Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Sat, 28 Nov 2015 12:18:10 +0300 Subject: [PATCH] Builtin objects refactored. --- Makefile | 13 ++- njs/njs_array.c | 30 ++--- njs/njs_array.h | 7 +- njs/njs_boolean.c | 27 ++--- njs/njs_boolean.h | 7 +- njs/njs_builtin.c | 175 +++++++++++++++++++++++++++ njs/njs_function.c | 39 +++---- njs/njs_function.h | 30 +---- njs/njs_generator.c | 14 +-- njs/njs_lexer_keyword.c | 14 +-- njs/njs_number.c | 27 ++--- njs/njs_number.h | 7 +- njs/njs_object.c | 227 +++++++++++++++++------------------- njs/njs_object.h | 30 ++--- njs/njs_parser.c | 16 ++- njs/njs_parser.h | 19 +-- njs/njs_parser_expression.c | 14 +-- njs/njs_regexp.c | 29 ++--- njs/njs_regexp.h | 7 +- njs/njs_shared.c | 198 ------------------------------- njs/njs_string.c | 41 +++---- njs/njs_string.h | 7 +- njs/njs_vm.c | 23 +--- njs/njs_vm.h | 96 +++++++++------ njs/njscript.c | 85 ++++++-------- 25 files changed, 547 insertions(+), 635 deletions(-) create mode 100644 njs/njs_builtin.c delete mode 100644 njs/njs_shared.c diff --git a/Makefile b/Makefile index baad353d..d13489a1 100644 --- 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 \ diff --git a/njs/njs_array.c b/njs/njs_array.c index 41b45334..87d9a323 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -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), +}; diff --git a/njs/njs_array.h b/njs/njs_array.h index 7aa3db7f..d6e0bd71 100644 --- a/njs/njs_array.h +++ b/njs/njs_array.h @@ -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_ */ diff --git a/njs/njs_boolean.c b/njs/njs_boolean.c index 86ddcaa7..05c0e649 100644 --- a/njs/njs_boolean.c +++ b/njs/njs_boolean.c @@ -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), +}; diff --git a/njs/njs_boolean.h b/njs/njs_boolean.h index ec0652f7..04180222 100644 --- a/njs/njs_boolean.h +++ b/njs/njs_boolean.h @@ -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 index 00000000..9c627572 --- /dev/null +++ b/njs/njs_builtin.c @@ -0,0 +1,175 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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; +} diff --git a/njs/njs_function.c b/njs/njs_function.c index 5411fc4f..2ec1856e 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -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), +}; diff --git a/njs/njs_function.h b/njs/njs_function.h index 720f467e..51db59b5 100644 --- a/njs/njs_function.h +++ b/njs/njs_function.h @@ -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_ */ diff --git a/njs/njs_generator.c b/njs/njs_generator.c index 6e6ac440..1c232009 100644 --- a/njs/njs_generator.c +++ b/njs/njs_generator.c @@ -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; diff --git a/njs/njs_lexer_keyword.c b/njs/njs_lexer_keyword.c index 0c00ae8a..a632b6c3 100644 --- a/njs/njs_lexer_keyword.c +++ b/njs/njs_lexer_keyword.c @@ -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. */ diff --git a/njs/njs_number.c b/njs/njs_number.c index 15d8bdb9..a8687a03 100644 --- a/njs/njs_number.c +++ b/njs/njs_number.c @@ -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), +}; diff --git a/njs/njs_number.h b/njs/njs_number.h index d59d2284..26f23905 100644 --- a/njs/njs_number.h +++ b/njs/njs_number.h @@ -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_ */ diff --git a/njs/njs_object.c b/njs/njs_object.c index 27265867..9f01f4c4 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -21,44 +21,44 @@ 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), +}; diff --git a/njs/njs_object.h b/njs/njs_object.h index bdb79684..a645494a 100644 --- a/njs/njs_object.h +++ b/njs/njs_object.h @@ -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_ */ diff --git a/njs/njs_parser.c b/njs/njs_parser.c index 753292b1..93b16477 100644 --- a/njs/njs_parser.c +++ b/njs/njs_parser.c @@ -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; diff --git a/njs/njs_parser.h b/njs/njs_parser.h index 4eb84807..69ca4556 100644 --- a/njs/njs_parser.h +++ b/njs/njs_parser.h @@ -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. */ diff --git a/njs/njs_parser_expression.c b/njs/njs_parser_expression.c index 2f93f350..e50f55f6 100644 --- a/njs/njs_parser_expression.c +++ b/njs/njs_parser_expression.c @@ -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)) { diff --git a/njs/njs_regexp.c b/njs/njs_regexp.c index 3829fd20..c9c3f403 100644 --- a/njs/njs_regexp.c +++ b/njs/njs_regexp.c @@ -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(®exp->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 diff --git a/njs/njs_regexp.h b/njs/njs_regexp.h index 62361337..86a24475 100644 --- a/njs/njs_regexp.h +++ b/njs/njs_regexp.h @@ -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 index b01bfcb5..00000000 --- a/njs/njs_shared.c +++ /dev/null @@ -1,198 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) NGINX, Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -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; -} diff --git a/njs/njs_string.c b/njs/njs_string.c index e3c28eaf..bdc45b72 100644 --- a/njs/njs_string.c +++ b/njs/njs_string.c @@ -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; diff --git a/njs/njs_string.h b/njs/njs_string.h index 01199202..38372453 100644 --- a/njs/njs_string.h +++ b/njs/njs_string.h @@ -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_ */ diff --git a/njs/njs_vm.c b/njs/njs_vm.c index 41c973f6..ae99d454 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -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: diff --git a/njs/njs_vm.h b/njs/njs_vm.h index 4ff1a302..133feeaf 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -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; diff --git a/njs/njscript.c b/njs/njscript.c index 81038306..49eef4b0 100644 --- a/njs/njscript.c +++ b/njs/njscript.c @@ -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; } -- 2.47.3