diff options
| author | Zach Shaftel | 2020-06-18 01:09:31 -0400 |
|---|---|---|
| committer | Zach Shaftel | 2020-06-18 01:09:31 -0400 |
| commit | e1aee0ffe8aa51a8963737f8a957cf19eabdb9d7 (patch) | |
| tree | be1ff734ed32fa702c4cd88adfabca389e1a1bc6 | |
| parent | 3d5ac37d36ecae90a634515b78608062fc9729be (diff) | |
| download | emacs-e1aee0ffe8aa51a8963737f8a957cf19eabdb9d7.tar.gz emacs-e1aee0ffe8aa51a8963737f8a957cf19eabdb9d7.zip | |
Don't call Ffuncall directly from exec_byte_codefeature/zach-soc-funcall-from-bytecode
* src/bytecode.c (exec_byte_code): Do a good chunk of Ffuncall's
work in the Bcall ops, so Ffuncall no longer needs to be called. As
it stands, it's an ugly clone of the contents of Ffuncall (and
some of funcall_lambda). Work in progress.
* src/eval.c (record_in_backtrace_with_offset): New function. Like
record_in_backtrace but accepts the bytecode offset and stores it
in the pertinent backtrace frame.
(record_in_backtrace): Don't record the offset.
(funcall_lambda): Remove unnecessary SYMBOLP check.
* src/lisp.h (funcall_lambda, do_debug_on_call)
(record_in_backtrace_with_offset , backtrace_debug_on_exit):
Declare.
| -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 | ||