diff options
| -rw-r--r-- | src/bytecode.c | 91 | ||||
| -rw-r--r-- | src/eval.c | 37 | ||||
| -rw-r--r-- | src/lisp.h | 5 |
3 files changed, 116 insertions, 17 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 | |||
| 311 | 311 | ||
| 312 | #define TOP (*top) | 312 | #define TOP (*top) |
| 313 | 313 | ||
| 314 | #define UPDATE_OFFSET (backtrace_byte_offset = pc - bytestr_data); | ||
| 315 | |||
| 316 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, | 314 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, |
| 317 | doc: /* Function used internally in byte-compiled code. | 315 | doc: /* Function used internally in byte-compiled code. |
| 318 | The first argument, BYTESTR, is a string of byte code; | 316 | 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, | |||
| 433 | /* NEXT is invoked at the end of an instruction to go to the | 431 | /* NEXT is invoked at the end of an instruction to go to the |
| 434 | next instruction. It is either a computed goto, or a | 432 | next instruction. It is either a computed goto, or a |
| 435 | plain break. */ | 433 | plain break. */ |
| 436 | #define NEXT UPDATE_OFFSET goto *(targets[op = FETCH]) | 434 | #define NEXT goto *(targets[op = FETCH]) |
| 437 | /* FIRST is like NEXT, but is only used at the start of the | 435 | /* FIRST is like NEXT, but is only used at the start of the |
| 438 | interpreter body. In the switch-based interpreter it is the | 436 | interpreter body. In the switch-based interpreter it is the |
| 439 | switch, so the threaded definition must include a semicolon. */ | 437 | 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, | |||
| 635 | } | 633 | } |
| 636 | } | 634 | } |
| 637 | #endif | 635 | #endif |
| 638 | TOP = Ffuncall (op + 1, &TOP); | 636 | Lisp_Object fun, original_fun; |
| 637 | Lisp_Object funcar; | ||
| 638 | Lisp_Object *fun_args; | ||
| 639 | ptrdiff_t numargs = op; | ||
| 640 | Lisp_Object val; | ||
| 641 | ptrdiff_t count_c; | ||
| 642 | |||
| 643 | maybe_quit (); | ||
| 644 | |||
| 645 | if (++lisp_eval_depth > max_lisp_eval_depth) | ||
| 646 | { | ||
| 647 | if (max_lisp_eval_depth < 100) | ||
| 648 | max_lisp_eval_depth = 100; | ||
| 649 | if (lisp_eval_depth > max_lisp_eval_depth) | ||
| 650 | error ("Lisp nesting exceeds `max-lisp-eval-depth'"); | ||
| 651 | } | ||
| 652 | |||
| 653 | fun_args = &TOP + 1; | ||
| 654 | |||
| 655 | count_c = record_in_backtrace_with_offset (TOP, fun_args, numargs, pc - bytestr_data - 1); | ||
| 656 | |||
| 657 | maybe_gc (); | ||
| 658 | |||
| 659 | if (debug_on_next_call) | ||
| 660 | do_debug_on_call (Qlambda, count); | ||
| 661 | |||
| 662 | original_fun = TOP; | ||
| 663 | |||
| 664 | retry: | ||
| 665 | |||
| 666 | /* Optimize for no indirection. */ | ||
| 667 | fun = original_fun; | ||
| 668 | if (SYMBOLP (fun) && !NILP (fun) | ||
| 669 | && (fun = XSYMBOL (fun)->u.s.function, SYMBOLP (fun))) | ||
| 670 | fun = indirect_function (fun); | ||
| 671 | |||
| 672 | if (COMPILEDP (fun)) | ||
| 673 | { | ||
| 674 | Lisp_Object syms_left = AREF (fun, COMPILED_ARGLIST); | ||
| 675 | if (FIXNUMP (syms_left)) | ||
| 676 | { | ||
| 677 | if (CONSP (AREF (fun, COMPILED_BYTECODE))) | ||
| 678 | Ffetch_bytecode (fun); | ||
| 679 | val = exec_byte_code (AREF (fun, COMPILED_BYTECODE), | ||
| 680 | AREF (fun, COMPILED_CONSTANTS), | ||
| 681 | AREF (fun, COMPILED_STACK_DEPTH), | ||
| 682 | syms_left, numargs, fun_args); | ||
| 683 | } | ||
| 684 | else | ||
| 685 | { | ||
| 686 | /* The rest of funcall_lambda is very bulky */ | ||
| 687 | val = funcall_lambda (fun, numargs, fun_args); | ||
| 688 | } | ||
| 689 | } | ||
| 690 | else if (SUBRP (fun)) | ||
| 691 | val = funcall_subr (XSUBR (fun), numargs, fun_args); | ||
| 692 | #ifdef HAVE_MODULES | ||
| 693 | else if (MODULE_FUNCTIONP (fun)) | ||
| 694 | val = funcall_module (fun, numargs, fun_args); | ||
| 695 | #endif | ||
| 696 | else | ||
| 697 | { | ||
| 698 | if (NILP (fun)) | ||
| 699 | xsignal1 (Qvoid_function, original_fun); | ||
| 700 | if (!CONSP (fun) | ||
| 701 | || (funcar = XCAR (fun), !SYMBOLP(funcar))) | ||
| 702 | xsignal1 (Qinvalid_function, original_fun); | ||
| 703 | if (EQ (funcar, Qlambda) | ||
| 704 | || EQ (funcar, Qclosure)) | ||
| 705 | val = funcall_lambda (fun, numargs, fun_args); | ||
| 706 | else if (EQ (funcar, Qautoload)) | ||
| 707 | { | ||
| 708 | Fautoload_do_load (fun, original_fun, Qnil); | ||
| 709 | goto retry; | ||
| 710 | } | ||
| 711 | else | ||
| 712 | xsignal1 (Qinvalid_function, original_fun); | ||
| 713 | } | ||
| 714 | lisp_eval_depth--; | ||
| 715 | if (backtrace_debug_on_exit (specpdl + count_c)) | ||
| 716 | val = call_debugger (list2 (Qexit, val)); | ||
| 717 | specpdl_ptr--; | ||
| 718 | |||
| 719 | TOP = val; | ||
| 639 | NEXT; | 720 | NEXT; |
| 640 | } | 721 | } |
| 641 | 722 | ||
| @@ -1451,7 +1532,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1451 | unbind_to (count, Qnil); | 1532 | unbind_to (count, Qnil); |
| 1452 | error ("binding stack not balanced (serious byte compiler bug)"); | 1533 | error ("binding stack not balanced (serious byte compiler bug)"); |
| 1453 | } | 1534 | } |
| 1454 | backtrace_byte_offset = -1; | 1535 | |
| 1455 | Lisp_Object result = TOP; | 1536 | Lisp_Object result = TOP; |
| 1456 | SAFE_FREE (); | 1537 | SAFE_FREE (); |
| 1457 | return result; | 1538 | return result; |
diff --git a/src/eval.c b/src/eval.c index 5b43b81a6ca..544dfc25af9 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -56,8 +56,6 @@ Lisp_Object Vrun_hooks; | |||
| 56 | /* FIXME: We should probably get rid of this! */ | 56 | /* FIXME: We should probably get rid of this! */ |
| 57 | Lisp_Object Vsignaling_function; | 57 | Lisp_Object Vsignaling_function; |
| 58 | 58 | ||
| 59 | int backtrace_byte_offset = -1; | ||
| 60 | |||
| 61 | /* These would ordinarily be static, but they need to be visible to GDB. */ | 59 | /* These would ordinarily be static, but they need to be visible to GDB. */ |
| 62 | bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE; | 60 | bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE; |
| 63 | Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE; | 61 | Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE; |
| @@ -65,7 +63,6 @@ Lisp_Object backtrace_function (union specbinding *) EXTERNALLY_VISIBLE; | |||
| 65 | union specbinding *backtrace_next (union specbinding *) EXTERNALLY_VISIBLE; | 63 | union specbinding *backtrace_next (union specbinding *) EXTERNALLY_VISIBLE; |
| 66 | union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE; | 64 | union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE; |
| 67 | 65 | ||
| 68 | static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *); | ||
| 69 | static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t); | 66 | static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t); |
| 70 | static Lisp_Object lambda_arity (Lisp_Object); | 67 | static Lisp_Object lambda_arity (Lisp_Object); |
| 71 | 68 | ||
| @@ -146,7 +143,7 @@ backtrace_bytecode_offset (union specbinding *pdl) | |||
| 146 | return pdl->bt.bytecode_offset; | 143 | return pdl->bt.bytecode_offset; |
| 147 | } | 144 | } |
| 148 | 145 | ||
| 149 | static bool | 146 | bool |
| 150 | backtrace_debug_on_exit (union specbinding *pdl) | 147 | backtrace_debug_on_exit (union specbinding *pdl) |
| 151 | { | 148 | { |
| 152 | eassert (pdl->kind == SPECPDL_BACKTRACE); | 149 | eassert (pdl->kind == SPECPDL_BACKTRACE); |
| @@ -354,7 +351,7 @@ call_debugger (Lisp_Object arg) | |||
| 354 | return unbind_to (count, val); | 351 | return unbind_to (count, val); |
| 355 | } | 352 | } |
| 356 | 353 | ||
| 357 | static void | 354 | void |
| 358 | do_debug_on_call (Lisp_Object code, ptrdiff_t count) | 355 | do_debug_on_call (Lisp_Object code, ptrdiff_t count) |
| 359 | { | 356 | { |
| 360 | debug_on_next_call = 0; | 357 | debug_on_next_call = 0; |
| @@ -2146,6 +2143,27 @@ grow_specpdl (void) | |||
| 2146 | } | 2143 | } |
| 2147 | 2144 | ||
| 2148 | ptrdiff_t | 2145 | ptrdiff_t |
| 2146 | record_in_backtrace_with_offset (Lisp_Object function, Lisp_Object *args, | ||
| 2147 | ptrdiff_t nargs, int offset) | ||
| 2148 | { | ||
| 2149 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 2150 | |||
| 2151 | eassert (nargs >= UNEVALLED); | ||
| 2152 | specpdl_ptr->bt.kind = SPECPDL_BACKTRACE; | ||
| 2153 | specpdl_ptr->bt.debug_on_exit = false; | ||
| 2154 | specpdl_ptr->bt.function = function; | ||
| 2155 | current_thread->stack_top = specpdl_ptr->bt.args = args; | ||
| 2156 | specpdl_ptr->bt.nargs = nargs; | ||
| 2157 | specpdl_ptr->bt.bytecode_offset = -1; | ||
| 2158 | union specbinding *nxt = backtrace_top (); | ||
| 2159 | if (backtrace_p (nxt) && nxt->kind == SPECPDL_BACKTRACE) | ||
| 2160 | nxt->bt.bytecode_offset = offset; | ||
| 2161 | grow_specpdl (); | ||
| 2162 | |||
| 2163 | return count; | ||
| 2164 | } | ||
| 2165 | |||
| 2166 | ptrdiff_t | ||
| 2149 | record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs) | 2167 | record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs) |
| 2150 | { | 2168 | { |
| 2151 | ptrdiff_t count = SPECPDL_INDEX (); | 2169 | ptrdiff_t count = SPECPDL_INDEX (); |
| @@ -2156,10 +2174,7 @@ record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs) | |||
| 2156 | specpdl_ptr->bt.function = function; | 2174 | specpdl_ptr->bt.function = function; |
| 2157 | current_thread->stack_top = specpdl_ptr->bt.args = args; | 2175 | current_thread->stack_top = specpdl_ptr->bt.args = args; |
| 2158 | specpdl_ptr->bt.nargs = nargs; | 2176 | specpdl_ptr->bt.nargs = nargs; |
| 2159 | union specbinding *nxt = specpdl_ptr; | 2177 | specpdl_ptr->bt.bytecode_offset = -1; |
| 2160 | nxt = backtrace_next(nxt); | ||
| 2161 | if (nxt->kind == SPECPDL_BACKTRACE) | ||
| 2162 | nxt->bt.bytecode_offset = backtrace_byte_offset; | ||
| 2163 | grow_specpdl (); | 2178 | grow_specpdl (); |
| 2164 | 2179 | ||
| 2165 | return count; | 2180 | return count; |
| @@ -2965,7 +2980,7 @@ apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count) | |||
| 2965 | FUN must be either a lambda-expression, a compiled-code object, | 2980 | FUN must be either a lambda-expression, a compiled-code object, |
| 2966 | or a module function. */ | 2981 | or a module function. */ |
| 2967 | 2982 | ||
| 2968 | static Lisp_Object | 2983 | Lisp_Object |
| 2969 | funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, | 2984 | funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, |
| 2970 | register Lisp_Object *arg_vector) | 2985 | register Lisp_Object *arg_vector) |
| 2971 | { | 2986 | { |
| @@ -3053,7 +3068,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, | |||
| 3053 | arg = Qnil; | 3068 | arg = Qnil; |
| 3054 | 3069 | ||
| 3055 | /* Bind the argument. */ | 3070 | /* Bind the argument. */ |
| 3056 | if (!NILP (lexenv) && SYMBOLP (next)) | 3071 | if (!NILP (lexenv)) |
| 3057 | /* Lexically bind NEXT by adding it to the lexenv alist. */ | 3072 | /* Lexically bind NEXT by adding it to the lexenv alist. */ |
| 3058 | lexenv = Fcons (Fcons (next, arg), lexenv); | 3073 | lexenv = Fcons (Fcons (next, arg), lexenv); |
| 3059 | else | 3074 | else |
diff --git a/src/lisp.h b/src/lisp.h index ef6302a4670..e04e374ca97 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4113,7 +4113,6 @@ extern Lisp_Object Vautoload_queue; | |||
| 4113 | extern Lisp_Object Vrun_hooks; | 4113 | extern Lisp_Object Vrun_hooks; |
| 4114 | extern Lisp_Object Vsignaling_function; | 4114 | extern Lisp_Object Vsignaling_function; |
| 4115 | extern Lisp_Object inhibit_lisp_code; | 4115 | extern Lisp_Object inhibit_lisp_code; |
| 4116 | extern int backtrace_byte_offset; | ||
| 4117 | 4116 | ||
| 4118 | /* To run a normal hook, use the appropriate function from the list below. | 4117 | /* To run a normal hook, use the appropriate function from the list below. |
| 4119 | The calling convention: | 4118 | The calling convention: |
| @@ -4141,6 +4140,7 @@ extern AVOID signal_error (const char *, Lisp_Object); | |||
| 4141 | extern AVOID overflow_error (void); | 4140 | extern AVOID overflow_error (void); |
| 4142 | extern bool FUNCTIONP (Lisp_Object); | 4141 | extern bool FUNCTIONP (Lisp_Object); |
| 4143 | extern Lisp_Object funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *arg_vector); | 4142 | extern Lisp_Object funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *arg_vector); |
| 4143 | extern Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *); | ||
| 4144 | extern Lisp_Object eval_sub (Lisp_Object form); | 4144 | extern Lisp_Object eval_sub (Lisp_Object form); |
| 4145 | extern Lisp_Object apply1 (Lisp_Object, Lisp_Object); | 4145 | extern Lisp_Object apply1 (Lisp_Object, Lisp_Object); |
| 4146 | extern Lisp_Object call0 (Lisp_Object); | 4146 | extern Lisp_Object call0 (Lisp_Object); |
| @@ -4185,6 +4185,7 @@ extern Lisp_Object vformat_string (const char *, va_list) | |||
| 4185 | ATTRIBUTE_FORMAT_PRINTF (1, 0); | 4185 | ATTRIBUTE_FORMAT_PRINTF (1, 0); |
| 4186 | extern void un_autoload (Lisp_Object); | 4186 | extern void un_autoload (Lisp_Object); |
| 4187 | extern Lisp_Object call_debugger (Lisp_Object arg); | 4187 | extern Lisp_Object call_debugger (Lisp_Object arg); |
| 4188 | extern void do_debug_on_call (Lisp_Object code, ptrdiff_t count); | ||
| 4188 | extern void init_eval_once (void); | 4189 | extern void init_eval_once (void); |
| 4189 | extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...); | 4190 | extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...); |
| 4190 | extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object); | 4191 | extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object); |
| @@ -4193,8 +4194,10 @@ extern void init_eval (void); | |||
| 4193 | extern void syms_of_eval (void); | 4194 | extern void syms_of_eval (void); |
| 4194 | extern void prog_ignore (Lisp_Object); | 4195 | extern void prog_ignore (Lisp_Object); |
| 4195 | extern ptrdiff_t record_in_backtrace (Lisp_Object, Lisp_Object *, ptrdiff_t); | 4196 | extern ptrdiff_t record_in_backtrace (Lisp_Object, Lisp_Object *, ptrdiff_t); |
| 4197 | extern ptrdiff_t record_in_backtrace_with_offset (Lisp_Object, Lisp_Object *, ptrdiff_t, int); | ||
| 4196 | extern void mark_specpdl (union specbinding *first, union specbinding *ptr); | 4198 | extern void mark_specpdl (union specbinding *first, union specbinding *ptr); |
| 4197 | extern void get_backtrace (Lisp_Object array); | 4199 | extern void get_backtrace (Lisp_Object array); |
| 4200 | extern bool backtrace_debug_on_exit (union specbinding *pdl); | ||
| 4198 | Lisp_Object backtrace_top_function (void); | 4201 | Lisp_Object backtrace_top_function (void); |
| 4199 | extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); | 4202 | extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); |
| 4200 | 4203 | ||