From: Dmitry Volyntsev Date: Fri, 6 Dec 2019 11:59:48 +0000 (+0300) Subject: Improved object type initialization structure. X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=a560d69029de31652b84d4c4938fc3ddde87ebc0;p=njs.git Improved object type initialization structure. Allowing predefine magic argument for a type constructor. This allows to write generic constructor functions. --- diff --git a/src/njs_array.c b/src/njs_array.c index a9471ab8..00e34a39 100644 --- a/src/njs_array.c +++ b/src/njs_array.c @@ -3103,8 +3103,8 @@ const njs_object_init_t njs_array_instance_init = { const njs_object_type_init_t njs_array_type_init = { - .constructor = njs_array_constructor, - .prototype_props = &njs_array_prototype_init, + .constructor = njs_native_ctor(njs_array_constructor, 1, 0), .constructor_props = &njs_array_constructor_init, - .value = { .object = { .type = NJS_ARRAY } }, + .prototype_props = &njs_array_prototype_init, + .prototype_value = { .object = { .type = NJS_ARRAY } }, }; diff --git a/src/njs_boolean.c b/src/njs_boolean.c index a9e6e99a..6d328fae 100644 --- a/src/njs_boolean.c +++ b/src/njs_boolean.c @@ -166,9 +166,11 @@ const njs_object_init_t njs_boolean_prototype_init = { const njs_object_type_init_t njs_boolean_type_init = { - .constructor = njs_boolean_constructor, - .prototype_props = &njs_boolean_prototype_init, + .constructor = njs_native_ctor(njs_boolean_constructor, 1, 0), .constructor_props = &njs_boolean_constructor_init, - .value = { .object_value = { .value = njs_value(NJS_BOOLEAN, 0, 0.0), - .object = { .type = NJS_OBJECT_BOOLEAN } } }, + .prototype_props = &njs_boolean_prototype_init, + .prototype_value = { .object_value = { + .value = njs_value(NJS_BOOLEAN, 0, 0.0), + .object = { .type = NJS_OBJECT_BOOLEAN } } + }, }; diff --git a/src/njs_builtin.c b/src/njs_builtin.c index 2f09385f..e429efa3 100644 --- a/src/njs_builtin.c +++ b/src/njs_builtin.c @@ -253,7 +253,7 @@ njs_builtin_objects_create(njs_vm_t *vm) prototype = shared->prototypes; for (i = NJS_OBJ_TYPE_OBJECT; i < NJS_OBJ_TYPE_MAX; i++) { - prototype[i] = njs_object_type_init[i]->value; + prototype[i] = njs_object_type_init[i]->prototype_value; ret = njs_object_hash_init(vm, &prototype[i].object.shared_hash, njs_object_type_init[i]->prototype_props); @@ -270,14 +270,8 @@ njs_builtin_objects_create(njs_vm_t *vm) constructor = shared->constructors; for (i = NJS_OBJ_TYPE_OBJECT; i < NJS_OBJ_TYPE_MAX; i++) { - constructor[i].object.type = NJS_FUNCTION; + constructor[i] = njs_object_type_init[i]->constructor; constructor[i].object.shared = 0; - constructor[i].object.extensible = 1; - constructor[i].native = 1; - constructor[i].ctor = 1; - constructor[i].args_offset = 1; - - constructor[i].u.native = njs_object_type_init[i]->constructor; ret = njs_object_hash_init(vm, &constructor[i].object.shared_hash, njs_object_type_init[i]->constructor_props); diff --git a/src/njs_crypto.c b/src/njs_crypto.c index 322adbd9..e6d66595 100644 --- a/src/njs_crypto.c +++ b/src/njs_crypto.c @@ -386,11 +386,11 @@ const njs_object_init_t njs_hash_constructor_init = { const njs_object_type_init_t njs_hash_type_init = { - .constructor = njs_hash_constructor, - .prototype_props = &njs_hash_prototype_init, + .constructor = njs_native_ctor(njs_hash_constructor, 2, 0), .constructor_props = &njs_hash_constructor_init, - .value = { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0), - .object = { .type = NJS_OBJECT } } }, + .prototype_props = &njs_hash_prototype_init, + .prototype_value = { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0), + .object = { .type = NJS_OBJECT } } }, }; @@ -712,11 +712,11 @@ const njs_object_init_t njs_crypto_object_init = { const njs_object_type_init_t njs_hmac_type_init = { - .constructor = njs_hmac_constructor, - .prototype_props = &njs_hmac_prototype_init, + .constructor = njs_native_ctor(njs_hmac_constructor, 3, 0), .constructor_props = &njs_hmac_constructor_init, - .value = { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0), - .object = { .type = NJS_OBJECT } } }, + .prototype_props = &njs_hmac_prototype_init, + .prototype_value = { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0), + .object = { .type = NJS_OBJECT } } }, }; diff --git a/src/njs_date.c b/src/njs_date.c index 85e5e657..cefe7555 100644 --- a/src/njs_date.c +++ b/src/njs_date.c @@ -1835,8 +1835,8 @@ const njs_object_init_t njs_date_prototype_init = { const njs_object_type_init_t njs_date_type_init = { - .constructor = njs_date_constructor, - .prototype_props = &njs_date_prototype_init, + .constructor = njs_native_ctor(njs_date_constructor, 7, 0), .constructor_props = &njs_date_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_date_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; diff --git a/src/njs_error.c b/src/njs_error.c index 8d317959..433da72c 100644 --- a/src/njs_error.c +++ b/src/njs_error.c @@ -899,10 +899,10 @@ const njs_object_init_t njs_error_prototype_init = { const njs_object_type_init_t njs_error_type_init = { - .constructor = njs_error_constructor, - .prototype_props = &njs_error_prototype_init, + .constructor = njs_native_ctor(njs_error_constructor, 1, 0), .constructor_props = &njs_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; @@ -941,10 +941,10 @@ const njs_object_init_t njs_eval_error_prototype_init = { const njs_object_type_init_t njs_eval_error_type_init = { - .constructor = njs_eval_error_constructor, - .prototype_props = &njs_eval_error_prototype_init, + .constructor = njs_native_ctor(njs_eval_error_constructor, 1, 0), .constructor_props = &njs_eval_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_eval_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; @@ -1003,18 +1003,18 @@ const njs_object_init_t njs_internal_error_prototype_init = { const njs_object_type_init_t njs_internal_error_type_init = { - .constructor = njs_internal_error_constructor, - .prototype_props = &njs_internal_error_prototype_init, + .constructor = njs_native_ctor(njs_internal_error_constructor, 1, 0), .constructor_props = &njs_internal_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_internal_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; const njs_object_type_init_t njs_memory_error_type_init = { - .constructor = njs_memory_error_constructor, - .prototype_props = &njs_internal_error_prototype_init, + .constructor = njs_native_ctor(njs_memory_error_constructor, 1, 0), .constructor_props = &njs_memory_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_internal_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; @@ -1053,10 +1053,10 @@ const njs_object_init_t njs_range_error_prototype_init = { const njs_object_type_init_t njs_range_error_type_init = { - .constructor = njs_range_error_constructor, - .prototype_props = &njs_range_error_prototype_init, + .constructor = njs_native_ctor(njs_range_error_constructor, 1, 0), .constructor_props = &njs_range_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_range_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; @@ -1095,10 +1095,10 @@ const njs_object_init_t njs_reference_error_prototype_init = { const njs_object_type_init_t njs_reference_error_type_init = { - .constructor = njs_reference_error_constructor, - .prototype_props = &njs_reference_error_prototype_init, + .constructor = njs_native_ctor(njs_reference_error_constructor, 1, 0), .constructor_props = &njs_reference_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_reference_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; @@ -1137,10 +1137,10 @@ const njs_object_init_t njs_syntax_error_prototype_init = { const njs_object_type_init_t njs_syntax_error_type_init = { - .constructor = njs_syntax_error_constructor, - .prototype_props = &njs_syntax_error_prototype_init, + .constructor = njs_native_ctor(njs_syntax_error_constructor, 1, 0), .constructor_props = &njs_syntax_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_syntax_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; @@ -1179,10 +1179,10 @@ const njs_object_init_t njs_type_error_prototype_init = { const njs_object_type_init_t njs_type_error_type_init = { - .constructor = njs_type_error_constructor, - .prototype_props = &njs_type_error_prototype_init, + .constructor = njs_native_ctor(njs_type_error_constructor, 1, 0), .constructor_props = &njs_type_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_type_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; @@ -1221,8 +1221,8 @@ const njs_object_init_t njs_uri_error_prototype_init = { const njs_object_type_init_t njs_uri_error_type_init = { - .constructor = njs_uri_error_constructor, - .prototype_props = &njs_uri_error_prototype_init, + .constructor = njs_native_ctor(njs_uri_error_constructor, 1, 0), .constructor_props = &njs_uri_error_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_uri_error_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; diff --git a/src/njs_function.c b/src/njs_function.c index 79b6dbc8..46850e25 100644 --- a/src/njs_function.c +++ b/src/njs_function.c @@ -58,7 +58,7 @@ njs_function_alloc(njs_vm_t *vm, njs_function_lambda_t *lambda, do { /* GC: retain closure. */ - function->closures[n] = closures[n]; + njs_function_closures(function)[n] = closures[n]; n++; } while (n < nesting); } @@ -104,10 +104,10 @@ njs_function_value_copy(njs_vm_t *vm, njs_value_t *value) njs_inline njs_closure_t ** -njs_function_closures(njs_vm_t *vm, njs_function_t *function) +njs_function_active_closures(njs_vm_t *vm, njs_function_t *function) { - return (function->closure) ? function->closures - : vm->active_frame->closures; + return (function->closure) ? njs_function_closures(function) + : njs_frame_closures(vm->active_frame); } @@ -185,13 +185,13 @@ njs_function_copy(njs_vm_t *vm, njs_function_t *function) copy->closure = 1; - closures = njs_function_closures(vm, function); + closures = njs_function_active_closures(vm, function); n = 0; do { /* GC: retain closure. */ - copy->closures[n] = closures[n]; + njs_function_closures(copy)[n] = closures[n]; n++; } while (n < nesting); @@ -596,11 +596,11 @@ njs_function_lambda_call(njs_vm_t *vm) nesting = lambda->nesting; if (nesting != 0) { - closures = njs_function_closures(vm, function); + closures = njs_function_active_closures(vm, function); do { closure = *closures++; - frame->closures[n] = closure; + njs_frame_closures(frame)[n] = closure; vm->scopes[NJS_SCOPE_CLOSURE + n] = &closure->u.values; n++; @@ -633,7 +633,7 @@ njs_function_lambda_call(njs_vm_t *vm) } while (size != 0); } - frame->closures[n] = closure; + njs_frame_closures(frame)[n] = closure; vm->scopes[NJS_SCOPE_CLOSURE + n] = &closure->u.values; } @@ -1351,11 +1351,11 @@ njs_prototype_function(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, const njs_object_type_init_t njs_function_type_init = { - .constructor = njs_function_constructor, - .prototype_props = &njs_function_prototype_init, + .constructor = njs_native_ctor(njs_function_constructor, 1, 0), .constructor_props = &njs_function_constructor_init, - .value = { .function = { .native = 1, - .args_offset = 1, - .u.native = njs_prototype_function, - .object = { .type = NJS_FUNCTION } } }, + .prototype_props = &njs_function_prototype_init, + .prototype_value = { .function = { .native = 1, + .args_offset = 1, + .u.native = njs_prototype_function, + .object = { .type = NJS_FUNCTION } } }, }; diff --git a/src/njs_function.h b/src/njs_function.h index 57443015..a659a452 100644 --- a/src/njs_function.h +++ b/src/njs_function.h @@ -90,11 +90,9 @@ struct njs_frame_s { njs_frame_t *previous_active_frame; njs_value_t *local; -#if (NJS_SUNC) - njs_closure_t *closures[1]; -#else - njs_closure_t *closures[]; -#endif + +#define njs_frame_closures(frame) \ + ((njs_closure_t **) ((u_char *) frame + sizeof(njs_frame_t))) }; diff --git a/src/njs_number.c b/src/njs_number.c index 60a850c7..c737023a 100644 --- a/src/njs_number.c +++ b/src/njs_number.c @@ -1123,9 +1123,11 @@ njs_number_parse_float(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, const njs_object_type_init_t njs_number_type_init = { - .constructor = njs_number_constructor, - .prototype_props = &njs_number_prototype_init, + .constructor = njs_native_ctor(njs_number_constructor, 1, 0), .constructor_props = &njs_number_constructor_init, - .value = { .object_value = { .value = njs_value(NJS_NUMBER, 0, 0.0), - .object = { .type = NJS_OBJECT_NUMBER } } }, + .prototype_props = &njs_number_prototype_init, + .prototype_value = { .object_value = { + .value = njs_value(NJS_NUMBER, 0, 0.0), + .object = { .type = NJS_OBJECT_NUMBER } } + }, }; diff --git a/src/njs_object.c b/src/njs_object.c index 10f7d569..5585b516 100644 --- a/src/njs_object.c +++ b/src/njs_object.c @@ -2670,8 +2670,8 @@ njs_object_length(njs_vm_t *vm, njs_value_t *value, uint32_t *length) const njs_object_type_init_t njs_obj_type_init = { - .constructor = njs_object_constructor, - .prototype_props = &njs_object_prototype_init, + .constructor = njs_native_ctor(njs_object_constructor, 1, 0), .constructor_props = &njs_object_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_object_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; diff --git a/src/njs_regexp.c b/src/njs_regexp.c index bce96dd5..acec4422 100644 --- a/src/njs_regexp.c +++ b/src/njs_regexp.c @@ -1341,8 +1341,8 @@ const njs_object_init_t njs_regexp_prototype_init = { const njs_object_type_init_t njs_regexp_type_init = { - .constructor = njs_regexp_constructor, - .prototype_props = &njs_regexp_prototype_init, + .constructor = njs_native_ctor(njs_regexp_constructor, 2, 0), .constructor_props = &njs_regexp_constructor_init, - .value = { .object = { .type = NJS_REGEXP } }, + .prototype_props = &njs_regexp_prototype_init, + .prototype_value = { .object = { .type = NJS_REGEXP } }, }; diff --git a/src/njs_string.c b/src/njs_string.c index 48c7bb64..8b4818a6 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -5276,9 +5276,11 @@ njs_value_index(njs_vm_t *vm, const njs_value_t *src, njs_uint_t runtime) const njs_object_type_init_t njs_string_type_init = { - .constructor = njs_string_constructor, - .prototype_props = &njs_string_prototype_init, + .constructor = njs_native_ctor(njs_string_constructor, 1, 0), .constructor_props = &njs_string_constructor_init, - .value = { .object_value = { .value = njs_string(""), - .object = { .type = NJS_OBJECT_STRING } } }, + .prototype_props = &njs_string_prototype_init, + .prototype_value = { .object_value = { + .value = njs_string(""), + .object = { .type = NJS_OBJECT_STRING } } + }, }; diff --git a/src/njs_symbol.c b/src/njs_symbol.c index ce94dfd9..8d29ec56 100644 --- a/src/njs_symbol.c +++ b/src/njs_symbol.c @@ -441,8 +441,8 @@ const njs_object_init_t njs_symbol_prototype_init = { const njs_object_type_init_t njs_symbol_type_init = { - .constructor = njs_symbol_constructor, - .prototype_props = &njs_symbol_prototype_init, + .constructor = njs_native_ctor(njs_symbol_constructor, 0, 0), .constructor_props = &njs_symbol_constructor_init, - .value = { .object = { .type = NJS_OBJECT } }, + .prototype_props = &njs_symbol_prototype_init, + .prototype_value = { .object = { .type = NJS_OBJECT } }, }; diff --git a/src/njs_value.h b/src/njs_value.h index 77790ba4..4651fa0d 100644 --- a/src/njs_value.h +++ b/src/njs_value.h @@ -239,6 +239,15 @@ struct njs_function_s { uint8_t args_offset; uint8_t args_count:5; + + /* + * If "closure" is true njs_closure_t[] is available right after the + * njs_function_t and njs_function_closures() may be used to access it. + */ + +#define njs_function_closures(function) \ + ((njs_closure_t **) ((u_char *) function + sizeof(njs_function_t))) + uint8_t closure:1; uint8_t native:1; uint8_t ctor:1; @@ -252,11 +261,6 @@ struct njs_function_s { } u; njs_value_t *bound; -#if (NJS_SUNC) - njs_closure_t *closures[1]; -#else - njs_closure_t *closures[]; -#endif }; @@ -289,10 +293,10 @@ typedef union { typedef struct { - njs_function_native_t constructor; - const njs_object_init_t *prototype_props; + njs_function_t constructor; const njs_object_init_t *constructor_props; - njs_object_prototype_t value; + const njs_object_init_t *prototype_props; + njs_object_prototype_t prototype_value; } njs_object_type_init_t; @@ -411,30 +415,39 @@ typedef struct { } -#define _njs_native_function(_function, _args_count, _magic) { \ +#define _njs_function(_function, _args_count, _ctor, _magic) { \ + .native = 1, \ + .magic = _magic, \ + .args_count = _args_count, \ + .ctor = _ctor, \ + .args_offset = 1, \ + .u.native = _function, \ + .object = { .type = NJS_FUNCTION, \ + .shared = 1, \ + .extensible = 1 }, \ +} + + +#define _njs_native_function(_func, _args, _ctor, _magic) { \ .data = { \ .type = NJS_FUNCTION, \ .truth = 1, \ - .u.function = & (njs_function_t) { \ - .native = 1, \ - .magic = _magic, \ - .args_count = _args_count, \ - .args_offset = 1, \ - .u.native = _function, \ - .object = { .type = NJS_FUNCTION, \ - .shared = 1, \ - .extensible = 1 }, \ - } \ + .u.function = & (njs_function_t) _njs_function(_func, _args, \ + _ctor, _magic) \ } \ } #define njs_native_function(_function, _args_count) \ - _njs_native_function(_function, _args_count, 0) + _njs_native_function(_function, _args_count, 0, 0) #define njs_native_function2(_function, _args_count, _magic) \ - _njs_native_function(_function, _args_count, _magic) + _njs_native_function(_function, _args_count, 0, _magic) + + +#define njs_native_ctor(_function, _args_count, _magic) \ + _njs_function(_function, _args_count, 1, _magic) #define njs_prop_handler(_handler) { \ diff --git a/src/njs_vm.c b/src/njs_vm.c index ea3a72dc..42f7a222 100644 --- a/src/njs_vm.c +++ b/src/njs_vm.c @@ -339,6 +339,7 @@ njs_vm_scopes_restore(njs_vm_t *vm, njs_frame_t *frame, { njs_uint_t n, nesting; njs_value_t *args; + njs_closure_t **closures; njs_function_t *function; vm->top_frame = previous; @@ -373,9 +374,10 @@ njs_vm_scopes_restore(njs_vm_t *vm, njs_frame_t *frame, function = frame->native.function; nesting = (function != NULL) ? function->u.lambda->nesting : 0; + closures = njs_frame_closures(frame); for (n = 0; n <= nesting; n++) { - vm->scopes[NJS_SCOPE_CLOSURE + n] = &frame->closures[n]->u.values; + vm->scopes[NJS_SCOPE_CLOSURE + n] = &closures[n]->u.values; } while (n < NJS_MAX_NESTING) { diff --git a/src/njs_vmcode.c b/src/njs_vmcode.c index 4cddea08..5fdbcf5f 100644 --- a/src/njs_vmcode.c +++ b/src/njs_vmcode.c @@ -1002,7 +1002,8 @@ njs_vmcode_function(njs_vm_t *vm, u_char *pc) code = (njs_vmcode_function_t *) pc; lambda = code->lambda; - function = njs_function_alloc(vm, lambda, vm->active_frame->closures, 0); + function = njs_function_alloc(vm, lambda, + njs_frame_closures(vm->active_frame), 0); if (njs_slow_path(function == NULL)) { return NJS_ERROR; }