From f4335d30a6351e2b08d6f572f5066a20cd490290 Mon Sep 17 00:00:00 2001 From: hongzhidao Date: Mon, 7 Jan 2019 22:14:17 +0800 Subject: [PATCH] Introduced njs_function_native_call(). --- njs/njs_function.c | 92 +++++++++++++++++++++++++++++++ njs/njs_function.h | 4 ++ njs/njs_vm.c | 134 +++++---------------------------------------- 3 files changed, 110 insertions(+), 120 deletions(-) diff --git a/njs/njs_function.c b/njs/njs_function.c index a3d860d8..41032d67 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -531,6 +531,98 @@ njs_function_call(njs_vm_t *vm, njs_index_t retval, size_t advance) } +njs_ret_t +njs_function_native_call(njs_vm_t *vm, njs_function_native_t native, + njs_value_t *args, nxt_uint_t nargs, njs_index_t retval) +{ + njs_ret_t ret; + njs_value_t *value; + njs_function_t *function; + njs_native_frame_t *frame; + + ret = native(vm, args, nargs, retval); + + /* + * A native method can return: + * NXT_OK on method success; + * NJS_APPLIED by Function.apply() and Function.call(); + * NXT_AGAIN to postpone nJSVM processing; + * NXT_ERROR. + * + * The callee arguments must be preserved + * for NJS_APPLIED and NXT_AGAIN cases. + */ + if (ret == NXT_OK) { + frame = vm->top_frame; + + vm->top_frame = njs_function_previous_frame(frame); + njs_function_frame_free(vm, frame); + + /* + * If a retval is in a callee arguments scope it + * must be in the previous callee arguments scope. + */ + args = vm->top_frame->arguments; + function = vm->top_frame->function; + + if (function != NULL) { + args += function->args_offset; + } + + vm->scopes[NJS_SCOPE_CALLEE_ARGUMENTS] = args; + + if (!frame->skip) { + value = njs_vmcode_operand(vm, retval); + /* + * GC: value external/internal++ depending + * on vm->retval and retval type + */ + *value = vm->retval; + } + + return NXT_OK; + } + + return ret; +} + + +njs_native_frame_t * +njs_function_previous_frame(njs_native_frame_t *frame) +{ + njs_native_frame_t *previous; + + do { + previous = frame->previous; + frame = previous; + + } while (frame->skip); + + return frame; +} + + +void +njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *frame) +{ + njs_native_frame_t *previous; + + do { + previous = frame->previous; + + /* GC: free frame->local, etc. */ + + if (frame->size != 0) { + vm->stack_size -= frame->size; + nxt_mem_cache_free(vm->mem_cache_pool, frame); + } + + frame = previous; + + } while (frame->skip); +} + + /* * The "prototype" property of user defined functions is created on * demand in private hash of the functions by the "prototype" getter. diff --git a/njs/njs_function.h b/njs/njs_function.h index feb83bc9..77bc0489 100644 --- a/njs/njs_function.h +++ b/njs/njs_function.h @@ -171,6 +171,10 @@ njs_ret_t njs_function_frame(njs_vm_t *vm, njs_function_t *function, const njs_value_t *this, const njs_value_t *args, nxt_uint_t nargs, nxt_bool_t ctor); njs_ret_t njs_function_call(njs_vm_t *vm, njs_index_t retval, size_t advance); +njs_ret_t njs_function_native_call(njs_vm_t *vm, njs_function_native_t native, + njs_value_t *args, nxt_uint_t nargs, njs_index_t retval); +njs_native_frame_t *njs_function_previous_frame(njs_native_frame_t *frame); +void njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *frame); extern const njs_object_init_t njs_function_constructor_init; extern const njs_object_init_t njs_function_prototype_init; diff --git a/njs/njs_vm.c b/njs/njs_vm.c index b94771c1..9c9b6a72 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -36,10 +36,6 @@ static void njs_vm_scopes_restore(njs_vm_t *vm, njs_frame_t *frame, njs_native_frame_t *previous); static njs_ret_t njs_vmcode_continuation(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2); -static njs_native_frame_t * - njs_function_previous_frame(njs_native_frame_t *frame); -static void njs_function_frame_free(njs_vm_t *vm, - njs_native_frame_t *frame); static void njs_vm_trap(njs_vm_t *vm, njs_trap_t trap, njs_value_t *value1, njs_value_t *value2); @@ -2064,52 +2060,19 @@ njs_vmcode_function_call(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval) return 0; } - ret = function->u.native(vm, args, nargs, (njs_index_t) retval); + ret = njs_function_native_call(vm, function->u.native, args, nargs, + (njs_index_t) retval); - /* - * A native method can return: - * NXT_OK on method success; - * NJS_APPLIED by Function.apply() and Function.call(); - * NXT_AGAIN to postpone nJSVM processing; - * NXT_ERROR. - * - * The callee arguments must be preserved - * for NJS_APPLIED and NXT_AGAIN cases. - */ - if (ret == NXT_OK) { - frame = vm->top_frame; - - vm->top_frame = njs_function_previous_frame(frame); - njs_function_frame_free(vm, frame); - - /* - * If a retval is in a callee arguments scope it - * must be in the previous callee arguments scope. - */ - args = vm->top_frame->arguments; - function = vm->top_frame->function; - - if (function != NULL) { - args += function->args_offset; - } - - vm->scopes[NJS_SCOPE_CALLEE_ARGUMENTS] = args; - - retval = njs_vmcode_operand(vm, retval); - /* - * GC: value external/internal++ depending - * on vm->retval and retval type - */ - *retval = vm->retval; + switch (ret) { + case NXT_OK: + return sizeof(njs_vmcode_function_call_t); - ret = sizeof(njs_vmcode_function_call_t); + case NJS_APPLIED: + return 0; - } else if (ret == NJS_APPLIED) { - /* A user-defined method has been prepared to run. */ - ret = 0; + default: + return ret; } - - return ret; } @@ -2467,60 +2430,27 @@ static njs_ret_t njs_vmcode_continuation(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2) { njs_ret_t ret; - nxt_bool_t skip; - njs_value_t *args, *retval; - njs_function_t *function; njs_native_frame_t *frame; njs_continuation_t *cont; cont = njs_vm_continuation(vm); frame = vm->top_frame; - args = frame->arguments; if (cont->args_types != NULL) { - ret = njs_normalize_args(vm, args, cont->args_types, frame->nargs); + ret = njs_normalize_args(vm, frame->arguments, cont->args_types, + frame->nargs); if (ret != NJS_OK) { return ret; } } - ret = cont->function(vm, args, frame->nargs, cont->retval); + ret = njs_function_native_call(vm, cont->function, frame->arguments, + frame->nargs, cont->retval); switch (ret) { - case NXT_OK: - - frame = vm->top_frame; - skip = frame->skip; - - vm->top_frame = njs_function_previous_frame(frame); - - /* - * If a retval is in a callee arguments scope it - * must be in the previous callee arguments scope. - */ - args = vm->top_frame->arguments; - function = vm->top_frame->function; - - if (function != NULL) { - args += function->args_offset; - } - - vm->scopes[NJS_SCOPE_CALLEE_ARGUMENTS] = args; - - if (!skip) { - retval = njs_vmcode_operand(vm, cont->retval); - /* - * GC: value external/internal++ depending - * on vm->retval and retval type - */ - *retval = vm->retval; - } - vm->current = cont->return_address; - (void) njs_function_frame_free(vm, frame); - - return 0; + /* Fall through. */ case NJS_APPLIED: return 0; @@ -2531,42 +2461,6 @@ njs_vmcode_continuation(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2) } -static njs_native_frame_t * -njs_function_previous_frame(njs_native_frame_t *frame) -{ - njs_native_frame_t *previous; - - do { - previous = frame->previous; - frame = previous; - - } while (frame->skip); - - return frame; -} - - -static void -njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *frame) -{ - njs_native_frame_t *previous; - - do { - previous = frame->previous; - - /* GC: free frame->local, etc. */ - - if (frame->size != 0) { - vm->stack_size -= frame->size; - nxt_mem_cache_free(vm->mem_cache_pool, frame); - } - - frame = previous; - - } while (frame->skip); -} - - njs_ret_t njs_vmcode_stop(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval) { -- 2.47.3