From bc3ffc8ef06dcf0e64a1a16623791693c1527834 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Wed, 23 Dec 2015 10:23:45 +0300 Subject: [PATCH] Change of special return values handled by nJSVM interpreter. --- njs/njs_function.c | 2 +- njs/njs_vm.c | 40 ++++++++++++++++++++++++---------------- njs/njs_vm.h | 38 ++++++++++++++++++++++++++++++-------- njs/njscript.c | 2 +- 4 files changed, 56 insertions(+), 26 deletions(-) diff --git a/njs/njs_function.c b/njs/njs_function.c index dfe81863..9c210be8 100644 --- a/njs/njs_function.c +++ b/njs/njs_function.c @@ -229,7 +229,7 @@ njs_function_call(njs_vm_t *vm, njs_index_t retval) frame->prev_local = vm->scopes[NJS_SCOPE_LOCAL]; vm->scopes[NJS_SCOPE_LOCAL] = frame->local; - return NJS_PASS; + return NJS_APPLIED; } diff --git a/njs/njs_vm.c b/njs/njs_vm.c index 3506018e..27b781cd 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -188,11 +188,11 @@ njs_vmcode_interpreter(njs_vm_t *vm) * On success an operation returns size of the bytecode, * a jump offset or zero after the call or return operations. * Jumps can return a negative offset. Compilers can generate - * (ret < 0 && ret >= NJS_PASS) + * (ret < 0 && ret >= NJS_PREEMPT) * as a single unsigned comparision. */ - if (nxt_slow_path(ret < 0 && ret >= NJS_PASS)) { + if (nxt_slow_path(ret < 0 && ret >= NJS_PREEMPT)) { break; } @@ -217,7 +217,7 @@ njs_vmcode_interpreter(njs_vm_t *vm) case NJS_TRAP_INCDEC: case NJS_TRAP_PROPERTY: - ret = njs_vm_trap(vm, ret - NJS_TRAP_LAST, value1, value2); + ret = njs_vm_trap(vm, ret - NJS_TRAP_BASE, value1, value2); if (nxt_fast_path(ret == NXT_OK)) { goto again; @@ -243,7 +243,7 @@ njs_vmcode_interpreter(njs_vm_t *vm) previous = frame->native.previous; if (previous == NULL) { - return ret; + return NXT_ERROR; } vm->frame = previous; @@ -260,7 +260,7 @@ njs_vmcode_interpreter(njs_vm_t *vm) } } - /* NXT_AGAIN, NXT_DONE */ + /* NXT_AGAIN, NJS_STOP. */ return ret; } @@ -1183,7 +1183,7 @@ njs_vmcode_property_next(njs_vm_t *vm, njs_value_t *object, njs_value_t *value) return ret; } - /* ret == NXT_DONE. */ + /* ret == NJS_DONE. */ } } @@ -2229,6 +2229,7 @@ njs_vmcode_function_call(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval) njs_vmcode_function_call_t *call; call = (njs_vmcode_function_call_t *) vm->current; + /* Update code pointer here to store it as return address in call frame. */ vm->current += sizeof(njs_vmcode_function_call_t); if (!vm->frame->native) { @@ -2245,12 +2246,13 @@ njs_vmcode_function_call(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval) ret = vm->frame->u.native(vm, ¶m); /* * A native method can return: - * NXT_OK on method success; - * NJS_PASS by Function.apply() and Function.call(); - * NXT_AGAIN to postpone nJSVM processing; - * NXT_ERROR. + * 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_PASS and NXT_AGAIN cases. + * The callee arguments must be preserved + * for NJS_APPLIED and NXT_AGAIN cases. */ if (ret == NXT_OK) { skip = NULL; @@ -2283,7 +2285,8 @@ njs_vmcode_function_call(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval) */ *retval = vm->retval; - } else if (ret == NJS_PASS) { + } else if (ret == NJS_APPLIED) { + /* A user-defined method has been prepared to run. */ ret = 0; } else if (ret == NXT_AGAIN) { @@ -2378,7 +2381,7 @@ njs_vmcode_stop(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval) vm->retval = *value; - return NXT_DONE; + return NJS_STOP; } @@ -2626,10 +2629,9 @@ njs_primitive_value(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint) param.nargs = 0; ret = njs_function_apply(vm, &prop->value, ¶m); - /* * njs_function_apply() can return - * NXT_OK, NJS_PASS, NXT_ERROR, NXT_AGAIN. + * NXT_OK, NJS_APPLIED, NXT_ERROR, NXT_AGAIN. */ if (nxt_fast_path(ret == NXT_OK)) { @@ -2638,10 +2640,16 @@ njs_primitive_value(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint) break; } + /* Try the second method. */ continue; } - if (ret == NJS_PASS) { + if (ret == NJS_APPLIED) { + /* + * A user-defined method has been prepared to + * run. The method will return to the current + * instruction and will restart it. + */ ret = 0; } } diff --git a/njs/njs_vm.h b/njs/njs_vm.h index b2fe2298..2b00c150 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -8,14 +8,36 @@ #define _NJS_VM_H_INCLUDED_ -#define NJS_TRAP_NUMBER -10 -#define NJS_TRAP_NUMBERS -11 -#define NJS_TRAP_INCDEC -12 -#define NJS_TRAP_STRINGS -13 -#define NJS_TRAP_PROPERTY -14 -#define NJS_TRAP_LAST NJS_TRAP_PROPERTY - -#define NJS_PASS -20 +/* + * Negative return values handled by nJSVM interpreter as special events. + * The values must be in range from -1 to -15, because -16 is minimal jump + * offset on 32-bit platforms. + * -1 (NJS_ERROR/NXT_ERROR): error or exception; + * -2 (NJS_AGAIN/NXT_AGAIN): postpone nJSVM execution; + * -3: not used; + * -4 (NJS_STOP/NXT_DONE): njs_vmcode_stop() has stopped execution, + * execution has completed successfully; + * -5 .. -9: traps to convert objects to primitive values; + * -10 .. -15: not used. + */ + +#define NJS_STOP NXT_DONE + +/* Traps events. */ +#define NJS_TRAP_NUMBER (-5) +#define NJS_TRAP_NUMBERS (-6) +#define NJS_TRAP_INCDEC (-7) +#define NJS_TRAP_STRINGS (-8) +#define NJS_TRAP_PROPERTY (-9) +#define NJS_TRAP_BASE NJS_TRAP_PROPERTY + +#define NJS_PREEMPT (-15) + +/* + * A user-defined function is prepared to run. This code is never + * returned to interpreter, so the value can be shared with NJS_STOP. + */ +#define NJS_APPLIED NXT_DONE /* The order of the enum is used in njs_vmcode_typeof() */ diff --git a/njs/njscript.c b/njs/njscript.c index 9825dd6e..f57956e8 100644 --- a/njs/njscript.c +++ b/njs/njscript.c @@ -340,7 +340,7 @@ njs_vm_run(njs_vm_t *vm) return ret; } - if (nxt_slow_path(ret != NXT_DONE)) { + if (nxt_slow_path(ret != NJS_STOP)) { nxt_thread_log_debug("VM: ERROR"); return ret; } -- 2.47.3