diff options
Diffstat (limited to 'src/bytecode.c')
-rw-r--r-- | src/bytecode.c | 91 |
1 files changed, 86 insertions, 5 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 29b76f88ef7..fe59cf6600b 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -311,8 +311,6 @@ enum byte_code_op #define TOP (*top) -#define UPDATE_OFFSET (backtrace_byte_offset = pc - bytestr_data); - DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, doc: /* Function used internally in byte-compiled code. The first argument, BYTESTR, is a string of byte code; @@ -433,7 +431,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, /* NEXT is invoked at the end of an instruction to go to the next instruction. It is either a computed goto, or a plain break. */ -#define NEXT UPDATE_OFFSET goto *(targets[op = FETCH]) +#define NEXT goto *(targets[op = FETCH]) /* FIRST is like NEXT, but is only used at the start of the interpreter body. In the switch-based interpreter it is the switch, so the threaded definition must include a semicolon. */ @@ -635,7 +633,90 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, } } #endif - TOP = Ffuncall (op + 1, &TOP); + Lisp_Object fun, original_fun; + Lisp_Object funcar; + Lisp_Object *fun_args; + ptrdiff_t numargs = op; + Lisp_Object val; + ptrdiff_t count_c; + + maybe_quit (); + + if (++lisp_eval_depth > max_lisp_eval_depth) + { + if (max_lisp_eval_depth < 100) + max_lisp_eval_depth = 100; + if (lisp_eval_depth > max_lisp_eval_depth) + error ("Lisp nesting exceeds `max-lisp-eval-depth'"); + } + + fun_args = &TOP + 1; + + count_c = record_in_backtrace_with_offset (TOP, fun_args, numargs, pc - bytestr_data - 1); + + maybe_gc (); + + if (debug_on_next_call) + do_debug_on_call (Qlambda, count); + + original_fun = TOP; + + retry: + + /* Optimize for no indirection. */ + fun = original_fun; + if (SYMBOLP (fun) && !NILP (fun) + && (fun = XSYMBOL (fun)->u.s.function, SYMBOLP (fun))) + fun = indirect_function (fun); + + if (COMPILEDP (fun)) + { + Lisp_Object syms_left = AREF (fun, COMPILED_ARGLIST); + if (FIXNUMP (syms_left)) + { + if (CONSP (AREF (fun, COMPILED_BYTECODE))) + Ffetch_bytecode (fun); + val = exec_byte_code (AREF (fun, COMPILED_BYTECODE), + AREF (fun, COMPILED_CONSTANTS), + AREF (fun, COMPILED_STACK_DEPTH), + syms_left, numargs, fun_args); + } + else + { + /* The rest of funcall_lambda is very bulky */ + val = funcall_lambda (fun, numargs, fun_args); + } + } + else if (SUBRP (fun)) + val = funcall_subr (XSUBR (fun), numargs, fun_args); +#ifdef HAVE_MODULES + else if (MODULE_FUNCTIONP (fun)) + val = funcall_module (fun, numargs, fun_args); +#endif + else + { + if (NILP (fun)) + xsignal1 (Qvoid_function, original_fun); + if (!CONSP (fun) + || (funcar = XCAR (fun), !SYMBOLP(funcar))) + xsignal1 (Qinvalid_function, original_fun); + if (EQ (funcar, Qlambda) + || EQ (funcar, Qclosure)) + val = funcall_lambda (fun, numargs, fun_args); + else if (EQ (funcar, Qautoload)) + { + Fautoload_do_load (fun, original_fun, Qnil); + goto retry; + } + else + xsignal1 (Qinvalid_function, original_fun); + } + lisp_eval_depth--; + if (backtrace_debug_on_exit (specpdl + count_c)) + val = call_debugger (list2 (Qexit, val)); + specpdl_ptr--; + + TOP = val; NEXT; } @@ -1451,7 +1532,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, unbind_to (count, Qnil); error ("binding stack not balanced (serious byte compiler bug)"); } - backtrace_byte_offset = -1; + Lisp_Object result = TOP; SAFE_FREE (); return result; |