Created
January 7, 2019 18:34
-
-
Save xeioex/a0da47724c4066cf118b6bb756323457 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # HG changeset patch | |
| # User hongzhidao <[email protected]> | |
| # Date 1546870457 -28800 | |
| # Mon Jan 07 22:14:17 2019 +0800 | |
| # Node ID f13d10d26346480e73c80cf3e8bb2111d878ace1 | |
| # Parent 07d1e6a4d270dff6c88fb6518488edba7721b295 | |
| Introduced function native call. | |
| diff --git a/njs/njs_function.c b/njs/njs_function.c | |
| --- a/njs/njs_function.c | |
| +++ b/njs/njs_function.c | |
| @@ -392,6 +392,42 @@ njs_function_frame_alloc(njs_vm_t *vm, s | |
| } | |
| +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); | |
| +} | |
| + | |
| + | |
| nxt_noinline njs_ret_t | |
| njs_function_apply(njs_vm_t *vm, njs_function_t *function, njs_value_t *args, | |
| nxt_uint_t nargs, njs_index_t retval) | |
| @@ -532,6 +568,69 @@ njs_function_call(njs_vm_t *vm, njs_inde | |
| /* | |
| + * Calls a native method, on sucess unwinds the current frame, | |
| + * otherwise returns the return code of the native function. | |
| + */ | |
| +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. | |
| + */ | |
| + switch (ret) { | |
| + | |
| + case 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; | |
| + | |
| + default: | |
| + return ret; | |
| + } | |
| +} | |
| + | |
| + | |
| +/* | |
| * The "prototype" property of user defined functions is created on | |
| * demand in private hash of the functions by the "prototype" getter. | |
| * The getter creates a copy of function which is private to nJSVM, | |
| diff --git a/njs/njs_function.h b/njs/njs_function.h | |
| --- a/njs/njs_function.h | |
| +++ b/njs/njs_function.h | |
| @@ -170,7 +170,11 @@ njs_ret_t njs_function_native_frame(njs_ | |
| 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_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); | |
| 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); | |
| 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 | |
| --- a/njs/njs_vm.c | |
| +++ b/njs/njs_vm.c | |
| @@ -36,10 +36,6 @@ static void njs_vm_scopes_restore(njs_vm | |
| 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, n | |
| return 0; | |
| } | |
| - ret = function->u.native(vm, 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; | |
| - | |
| - ret = sizeof(njs_vmcode_function_call_t); | |
| - | |
| - } else if (ret == NJS_APPLIED) { | |
| - /* A user-defined method has been prepared to run. */ | |
| - ret = 0; | |
| + ret = njs_function_native_call(vm, function->u.native, args, nargs, | |
| + (njs_index_t ) retval); | |
| + | |
| + switch (ret) { | |
| + case NXT_OK: | |
| + return sizeof(njs_vmcode_function_call_t); | |
| + | |
| + case NJS_APPLIED: | |
| + return 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, nj | |
| } | |
| -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) | |
| { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment