aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZach Shaftel2020-06-18 01:09:31 -0400
committerZach Shaftel2020-06-18 01:09:31 -0400
commite1aee0ffe8aa51a8963737f8a957cf19eabdb9d7 (patch)
treebe1ff734ed32fa702c4cd88adfabca389e1a1bc6
parent3d5ac37d36ecae90a634515b78608062fc9729be (diff)
downloademacs-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.c91
-rw-r--r--src/eval.c37
-rw-r--r--src/lisp.h5
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
316DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, 314DEFUN ("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.
318The first argument, BYTESTR, is a string of byte code; 316The 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! */
57Lisp_Object Vsignaling_function; 57Lisp_Object Vsignaling_function;
58 58
59int 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. */
62bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE; 60bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
63Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE; 61Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE;
@@ -65,7 +63,6 @@ Lisp_Object backtrace_function (union specbinding *) EXTERNALLY_VISIBLE;
65union specbinding *backtrace_next (union specbinding *) EXTERNALLY_VISIBLE; 63union specbinding *backtrace_next (union specbinding *) EXTERNALLY_VISIBLE;
66union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE; 64union specbinding *backtrace_top (void) EXTERNALLY_VISIBLE;
67 65
68static Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *);
69static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t); 66static Lisp_Object apply_lambda (Lisp_Object, Lisp_Object, ptrdiff_t);
70static Lisp_Object lambda_arity (Lisp_Object); 67static 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
149static bool 146bool
150backtrace_debug_on_exit (union specbinding *pdl) 147backtrace_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
357static void 354void
358do_debug_on_call (Lisp_Object code, ptrdiff_t count) 355do_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
2148ptrdiff_t 2145ptrdiff_t
2146record_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
2166ptrdiff_t
2149record_in_backtrace (Lisp_Object function, Lisp_Object *args, ptrdiff_t nargs) 2167record_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
2968static Lisp_Object 2983Lisp_Object
2969funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, 2984funcall_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;
4113extern Lisp_Object Vrun_hooks; 4113extern Lisp_Object Vrun_hooks;
4114extern Lisp_Object Vsignaling_function; 4114extern Lisp_Object Vsignaling_function;
4115extern Lisp_Object inhibit_lisp_code; 4115extern Lisp_Object inhibit_lisp_code;
4116extern 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);
4141extern AVOID overflow_error (void); 4140extern AVOID overflow_error (void);
4142extern bool FUNCTIONP (Lisp_Object); 4141extern bool FUNCTIONP (Lisp_Object);
4143extern Lisp_Object funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *arg_vector); 4142extern Lisp_Object funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *arg_vector);
4143extern Lisp_Object funcall_lambda (Lisp_Object, ptrdiff_t, Lisp_Object *);
4144extern Lisp_Object eval_sub (Lisp_Object form); 4144extern Lisp_Object eval_sub (Lisp_Object form);
4145extern Lisp_Object apply1 (Lisp_Object, Lisp_Object); 4145extern Lisp_Object apply1 (Lisp_Object, Lisp_Object);
4146extern Lisp_Object call0 (Lisp_Object); 4146extern 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);
4186extern void un_autoload (Lisp_Object); 4186extern void un_autoload (Lisp_Object);
4187extern Lisp_Object call_debugger (Lisp_Object arg); 4187extern Lisp_Object call_debugger (Lisp_Object arg);
4188extern void do_debug_on_call (Lisp_Object code, ptrdiff_t count);
4188extern void init_eval_once (void); 4189extern void init_eval_once (void);
4189extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...); 4190extern Lisp_Object safe_call (ptrdiff_t, Lisp_Object, ...);
4190extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object); 4191extern Lisp_Object safe_call1 (Lisp_Object, Lisp_Object);
@@ -4193,8 +4194,10 @@ extern void init_eval (void);
4193extern void syms_of_eval (void); 4194extern void syms_of_eval (void);
4194extern void prog_ignore (Lisp_Object); 4195extern void prog_ignore (Lisp_Object);
4195extern ptrdiff_t record_in_backtrace (Lisp_Object, Lisp_Object *, ptrdiff_t); 4196extern ptrdiff_t record_in_backtrace (Lisp_Object, Lisp_Object *, ptrdiff_t);
4197extern ptrdiff_t record_in_backtrace_with_offset (Lisp_Object, Lisp_Object *, ptrdiff_t, int);
4196extern void mark_specpdl (union specbinding *first, union specbinding *ptr); 4198extern void mark_specpdl (union specbinding *first, union specbinding *ptr);
4197extern void get_backtrace (Lisp_Object array); 4199extern void get_backtrace (Lisp_Object array);
4200extern bool backtrace_debug_on_exit (union specbinding *pdl);
4198Lisp_Object backtrace_top_function (void); 4201Lisp_Object backtrace_top_function (void);
4199extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); 4202extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol);
4200 4203