Skip to content

Instantly share code, notes, and snippets.

@xeioex
Created January 7, 2019 18:34
Show Gist options
  • Save xeioex/a0da47724c4066cf118b6bb756323457 to your computer and use it in GitHub Desktop.
Save xeioex/a0da47724c4066cf118b6bb756323457 to your computer and use it in GitHub Desktop.
# 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