aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-08-09 00:37:40 -0700
committerPaul Eggert2016-08-09 01:31:22 -0700
commit644fc17b9ae181174a842e3876e887666d505666 (patch)
tree25fd8d1b3e1a32753d3db759d0909acbc2b12e77 /src
parentcb71a119f7231984e010cc28ef33854721036a0f (diff)
downloademacs-644fc17b9ae181174a842e3876e887666d505666.tar.gz
emacs-644fc17b9ae181174a842e3876e887666d505666.zip
Remove interpreter’s byte stack
This improves performance overall on my benchmark on x86-64, since the interpreted program-counter resides in a machine register rather than in RAM. * etc/DEBUG, src/.gdbinit: Remove xbytecode GDB command, as there is no longer a byte stack to decode. * src/bytecode.c (struct byte_stack, byte_stack_list) (relocate_byte_stack): Remove. All uses removed. (FETCH): Simplify now that pc is now local (typically, in a register) and no longer needs to be relocated. (CHECK_RANGE): Remove. All uses now done inline, in a different way. (BYTE_CODE_QUIT): Remove; now done by op_relative_branch. (exec_byte_code): Allocate a copy of the function’s bytecode, so that there is no problem if GC moves it. * src/lisp.h (struct handler): Remove byte_stack member. All uses removed. (SAFE_ALLOCA_LISP_EXTRA): New macro, a generalization of SAFE_ALLOCA_LISP. (SAFE_ALLOCA_LISP): Use it.
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit15
-rw-r--r--src/alloc.c2
-rw-r--r--src/bytecode.c188
-rw-r--r--src/eval.c3
-rw-r--r--src/lisp.h13
5 files changed, 52 insertions, 169 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
index a4e9f709386..8e7ac3ce547 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1215,21 +1215,6 @@ document xwhichsymbols
1215 maximum number of symbols referencing it to produce. 1215 maximum number of symbols referencing it to produce.
1216end 1216end
1217 1217
1218define xbytecode
1219 set $bt = byte_stack_list
1220 while $bt
1221 xgetptr $bt->byte_string
1222 set $ptr = (struct Lisp_String *) $ptr
1223 xprintbytestr $ptr
1224 printf "\n0x%x => ", $bt->byte_string
1225 xwhichsymbols $bt->byte_string 5
1226 set $bt = $bt->next
1227 end
1228end
1229document xbytecode
1230 Print a backtrace of the byte code stack.
1231end
1232
1233# Show Lisp backtrace after normal backtrace. 1218# Show Lisp backtrace after normal backtrace.
1234define hookpost-backtrace 1219define hookpost-backtrace
1235 set $bt = backtrace_top () 1220 set $bt = backtrace_top ()
diff --git a/src/alloc.c b/src/alloc.c
index e25d91ff8aa..db165757e19 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5799,8 +5799,6 @@ garbage_collect_1 (void *end)
5799 5799
5800 gc_sweep (); 5800 gc_sweep ();
5801 5801
5802 relocate_byte_stack ();
5803
5804 /* Clear the mark bits that we set in certain root slots. */ 5802 /* Clear the mark bits that we set in certain root slots. */
5805 VECTOR_UNMARK (&buffer_defaults); 5803 VECTOR_UNMARK (&buffer_defaults);
5806 VECTOR_UNMARK (&buffer_local_symbols); 5804 VECTOR_UNMARK (&buffer_local_symbols);
diff --git a/src/bytecode.c b/src/bytecode.c
index 0c5b8494d0c..995d37c09d5 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -281,59 +281,9 @@ enum byte_code_op
281#endif 281#endif
282}; 282};
283 283
284/* Structure describing a value stack used during byte-code execution
285 in Fbyte_code. */
286
287struct byte_stack
288{
289 /* Program counter. This points into the byte_string below
290 and is relocated when that string is relocated. */
291 const unsigned char *pc;
292
293 /* The string containing the byte-code, and its current address.
294 Storing this here protects it from GC. */
295 Lisp_Object byte_string;
296 const unsigned char *byte_string_start;
297
298 /* Next entry in byte_stack_list. */
299 struct byte_stack *next;
300};
301
302/* A list of currently active byte-code execution value stacks.
303 Fbyte_code adds an entry to the head of this list before it starts
304 processing byte-code, and it removes the entry again when it is
305 done. Signaling an error truncates the list. */
306
307struct byte_stack *byte_stack_list;
308
309
310/* Relocate program counters in the stacks on byte_stack_list. Called
311 when GC has completed. */
312
313void
314relocate_byte_stack (void)
315{
316 struct byte_stack *stack;
317
318 for (stack = byte_stack_list; stack; stack = stack->next)
319 {
320 if (stack->byte_string_start != SDATA (stack->byte_string))
321 {
322 ptrdiff_t offset = stack->pc - stack->byte_string_start;
323 stack->byte_string_start = SDATA (stack->byte_string);
324 stack->pc = stack->byte_string_start + offset;
325 }
326 }
327}
328
329
330/* Fetch the next byte from the bytecode stream. */ 284/* Fetch the next byte from the bytecode stream. */
331 285
332#if BYTE_CODE_SAFE 286#define FETCH (*pc++)
333#define FETCH (eassert (stack.byte_string_start == SDATA (stack.byte_string)), *stack.pc++)
334#else
335#define FETCH *stack.pc++
336#endif
337 287
338/* Fetch two bytes from the bytecode stream and make a 16-bit number 288/* Fetch two bytes from the bytecode stream and make a 16-bit number
339 out of them. */ 289 out of them. */
@@ -358,32 +308,6 @@ relocate_byte_stack (void)
358 308
359#define TOP (*top) 309#define TOP (*top)
360 310
361/* Check for jumping out of range. */
362
363#define CHECK_RANGE(ARG) \
364 (BYTE_CODE_SAFE && bytestr_length <= (ARG) ? emacs_abort () : (void) 0)
365
366/* A version of the QUIT macro which makes sure that the stack top is
367 set before signaling `quit'. */
368
369#define BYTE_CODE_QUIT \
370 do { \
371 if (quitcounter++) \
372 break; \
373 maybe_gc (); \
374 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \
375 { \
376 Lisp_Object flag = Vquit_flag; \
377 Vquit_flag = Qnil; \
378 if (EQ (Vthrow_on_input, flag)) \
379 Fthrow (Vthrow_on_input, Qt); \
380 quit (); \
381 } \
382 else if (pending_signals) \
383 process_pending_signals (); \
384 } while (0)
385
386
387DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, 311DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0,
388 doc: /* Function used internally in byte-compiled code. 312 doc: /* Function used internally in byte-compiled code.
389The first argument, BYTESTR, is a string of byte code; 313The first argument, BYTESTR, is a string of byte code;
@@ -423,7 +347,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
423 Lisp_Object *vectorp; 347 Lisp_Object *vectorp;
424 ptrdiff_t const_length; 348 ptrdiff_t const_length;
425 ptrdiff_t bytestr_length; 349 ptrdiff_t bytestr_length;
426 struct byte_stack stack;
427 Lisp_Object *top; 350 Lisp_Object *top;
428 Lisp_Object result; 351 Lisp_Object result;
429 enum handlertype type; 352 enum handlertype type;
@@ -445,16 +368,16 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
445 bytestr_length = SBYTES (bytestr); 368 bytestr_length = SBYTES (bytestr);
446 vectorp = XVECTOR (vector)->contents; 369 vectorp = XVECTOR (vector)->contents;
447 370
448 stack.byte_string = bytestr; 371 unsigned char quitcounter = 1;
449 stack.pc = stack.byte_string_start = SDATA (bytestr);
450 unsigned char quitcounter = 0;
451 EMACS_INT stack_items = XFASTINT (maxdepth) + 1; 372 EMACS_INT stack_items = XFASTINT (maxdepth) + 1;
452 Lisp_Object *stack_base; 373 Lisp_Object *stack_base;
453 SAFE_ALLOCA_LISP (stack_base, stack_items); 374 SAFE_ALLOCA_LISP_EXTRA (stack_base, stack_items, bytestr_length);
454 Lisp_Object *stack_lim = stack_base + stack_items; 375 Lisp_Object *stack_lim = stack_base + stack_items;
455 top = stack_base; 376 top = stack_base;
456 stack.next = byte_stack_list; 377 memcpy (stack_lim, SDATA (bytestr), bytestr_length);
457 byte_stack_list = &stack; 378 void *void_stack_lim = stack_lim;
379 unsigned char const *bytestr_data = void_stack_lim;
380 unsigned char const *pc = bytestr_data;
458 ptrdiff_t count = SPECPDL_INDEX (); 381 ptrdiff_t count = SPECPDL_INDEX ();
459 382
460 if (!NILP (args_template)) 383 if (!NILP (args_template))
@@ -608,11 +531,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
608 op = FETCH2; 531 op = FETCH2;
609 v1 = POP; 532 v1 = POP;
610 if (NILP (v1)) 533 if (NILP (v1))
611 { 534 goto op_branch;
612 BYTE_CODE_QUIT;
613 CHECK_RANGE (op);
614 stack.pc = stack.byte_string_start + op;
615 }
616 NEXT; 535 NEXT;
617 } 536 }
618 537
@@ -791,10 +710,22 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
791 NEXT; 710 NEXT;
792 711
793 CASE (Bgoto): 712 CASE (Bgoto):
794 BYTE_CODE_QUIT; 713 op = FETCH2;
795 op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */ 714 op_branch:
796 CHECK_RANGE (op); 715 op -= pc - bytestr_data;
797 stack.pc = stack.byte_string_start + op; 716 op_relative_branch:
717 if (BYTE_CODE_SAFE
718 && ! (bytestr_data - pc <= op
719 && op < bytestr_data + bytestr_length - pc))
720 emacs_abort ();
721 quitcounter += op < 0;
722 if (!quitcounter)
723 {
724 quitcounter = 1;
725 maybe_gc ();
726 QUIT;
727 }
728 pc += op;
798 NEXT; 729 NEXT;
799 730
800 CASE (Bgotoifnonnil): 731 CASE (Bgotoifnonnil):
@@ -803,51 +734,35 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
803 op = FETCH2; 734 op = FETCH2;
804 v1 = POP; 735 v1 = POP;
805 if (!NILP (v1)) 736 if (!NILP (v1))
806 { 737 goto op_branch;
807 BYTE_CODE_QUIT;
808 CHECK_RANGE (op);
809 stack.pc = stack.byte_string_start + op;
810 }
811 NEXT; 738 NEXT;
812 } 739 }
813 740
814 CASE (Bgotoifnilelsepop): 741 CASE (Bgotoifnilelsepop):
815 op = FETCH2; 742 op = FETCH2;
816 if (NILP (TOP)) 743 if (NILP (TOP))
817 { 744 goto op_branch;
818 BYTE_CODE_QUIT; 745 DISCARD (1);
819 CHECK_RANGE (op);
820 stack.pc = stack.byte_string_start + op;
821 }
822 else DISCARD (1);
823 NEXT; 746 NEXT;
824 747
825 CASE (Bgotoifnonnilelsepop): 748 CASE (Bgotoifnonnilelsepop):
826 op = FETCH2; 749 op = FETCH2;
827 if (!NILP (TOP)) 750 if (!NILP (TOP))
828 { 751 goto op_branch;
829 BYTE_CODE_QUIT; 752 DISCARD (1);
830 CHECK_RANGE (op);
831 stack.pc = stack.byte_string_start + op;
832 }
833 else DISCARD (1);
834 NEXT; 753 NEXT;
835 754
836 CASE (BRgoto): 755 CASE (BRgoto):
837 BYTE_CODE_QUIT; 756 op = FETCH - 128;
838 stack.pc += (int) *stack.pc - 127; 757 goto op_relative_branch;
839 NEXT;
840 758
841 CASE (BRgotoifnil): 759 CASE (BRgotoifnil):
842 { 760 {
843 Lisp_Object v1; 761 Lisp_Object v1;
844 v1 = POP; 762 v1 = POP;
763 op = FETCH - 128;
845 if (NILP (v1)) 764 if (NILP (v1))
846 { 765 goto op_relative_branch;
847 BYTE_CODE_QUIT;
848 stack.pc += (int) *stack.pc - 128;
849 }
850 stack.pc++;
851 NEXT; 766 NEXT;
852 } 767 }
853 768
@@ -855,33 +770,24 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
855 { 770 {
856 Lisp_Object v1; 771 Lisp_Object v1;
857 v1 = POP; 772 v1 = POP;
773 op = FETCH - 128;
858 if (!NILP (v1)) 774 if (!NILP (v1))
859 { 775 goto op_relative_branch;
860 BYTE_CODE_QUIT;
861 stack.pc += (int) *stack.pc - 128;
862 }
863 stack.pc++;
864 NEXT; 776 NEXT;
865 } 777 }
866 778
867 CASE (BRgotoifnilelsepop): 779 CASE (BRgotoifnilelsepop):
868 op = *stack.pc++; 780 op = FETCH - 128;
869 if (NILP (TOP)) 781 if (NILP (TOP))
870 { 782 goto op_relative_branch;
871 BYTE_CODE_QUIT; 783 DISCARD (1);
872 stack.pc += op - 128;
873 }
874 else DISCARD (1);
875 NEXT; 784 NEXT;
876 785
877 CASE (BRgotoifnonnilelsepop): 786 CASE (BRgotoifnonnilelsepop):
878 op = *stack.pc++; 787 op = FETCH - 128;
879 if (!NILP (TOP)) 788 if (!NILP (TOP))
880 { 789 goto op_relative_branch;
881 BYTE_CODE_QUIT; 790 DISCARD (1);
882 stack.pc += op - 128;
883 }
884 else DISCARD (1);
885 NEXT; 791 NEXT;
886 792
887 CASE (Breturn): 793 CASE (Breturn):
@@ -946,15 +852,11 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
946 if (sys_setjmp (c->jmp)) 852 if (sys_setjmp (c->jmp))
947 { 853 {
948 struct handler *c = handlerlist; 854 struct handler *c = handlerlist;
949 int dest;
950 top = c->bytecode_top; 855 top = c->bytecode_top;
951 dest = c->bytecode_dest; 856 op = c->bytecode_dest;
952 handlerlist = c->next; 857 handlerlist = c->next;
953 PUSH (c->val); 858 PUSH (c->val);
954 CHECK_RANGE (dest); 859 goto op_branch;
955 /* Might have been re-set by longjmp! */
956 stack.byte_string_start = SDATA (stack.byte_string);
957 stack.pc = stack.byte_string_start + dest;
958 } 860 }
959 861
960 NEXT; 862 NEXT;
@@ -1629,7 +1531,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1629 call3 (Qerror, 1531 call3 (Qerror,
1630 build_string ("Invalid byte opcode: op=%s, ptr=%d"), 1532 build_string ("Invalid byte opcode: op=%s, ptr=%d"),
1631 make_number (op), 1533 make_number (op),
1632 make_number ((stack.pc - 1) - stack.byte_string_start)); 1534 make_number (pc - 1 - bytestr_data));
1633 1535
1634 /* Handy byte-codes for lexical binding. */ 1536 /* Handy byte-codes for lexical binding. */
1635 CASE (Bstack_ref1): 1537 CASE (Bstack_ref1):
@@ -1689,8 +1591,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
1689 1591
1690 exit: 1592 exit:
1691 1593
1692 byte_stack_list = byte_stack_list->next;
1693
1694 /* Binds and unbinds are supposed to be compiled balanced. */ 1594 /* Binds and unbinds are supposed to be compiled balanced. */
1695 if (SPECPDL_INDEX () != count) 1595 if (SPECPDL_INDEX () != count)
1696 { 1596 {
diff --git a/src/eval.c b/src/eval.c
index 7b7bdd8df7b..f681ef7c278 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -222,7 +222,6 @@ static struct handler handlerlist_sentinel;
222void 222void
223init_eval (void) 223init_eval (void)
224{ 224{
225 byte_stack_list = 0;
226 specpdl_ptr = specpdl; 225 specpdl_ptr = specpdl;
227 { /* Put a dummy catcher at top-level so that handlerlist is never NULL. 226 { /* Put a dummy catcher at top-level so that handlerlist is never NULL.
228 This is important since handlerlist->nextfree holds the freelist 227 This is important since handlerlist->nextfree holds the freelist
@@ -1135,7 +1134,6 @@ unwind_to_catch (struct handler *catch, Lisp_Object value)
1135 1134
1136 eassert (handlerlist == catch); 1135 eassert (handlerlist == catch);
1137 1136
1138 byte_stack_list = catch->byte_stack;
1139 lisp_eval_depth = catch->lisp_eval_depth; 1137 lisp_eval_depth = catch->lisp_eval_depth;
1140 1138
1141 sys_longjmp (catch->jmp, 1); 1139 sys_longjmp (catch->jmp, 1);
@@ -1430,7 +1428,6 @@ push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype)
1430 c->pdlcount = SPECPDL_INDEX (); 1428 c->pdlcount = SPECPDL_INDEX ();
1431 c->poll_suppress_count = poll_suppress_count; 1429 c->poll_suppress_count = poll_suppress_count;
1432 c->interrupt_input_blocked = interrupt_input_blocked; 1430 c->interrupt_input_blocked = interrupt_input_blocked;
1433 c->byte_stack = byte_stack_list;
1434 handlerlist = c; 1431 handlerlist = c;
1435 return c; 1432 return c;
1436} 1433}
diff --git a/src/lisp.h b/src/lisp.h
index 8ac9cc1d2a9..97c8d9fe84f 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3202,7 +3202,6 @@ struct handler
3202 ptrdiff_t pdlcount; 3202 ptrdiff_t pdlcount;
3203 int poll_suppress_count; 3203 int poll_suppress_count;
3204 int interrupt_input_blocked; 3204 int interrupt_input_blocked;
3205 struct byte_stack *byte_stack;
3206}; 3205};
3207 3206
3208extern Lisp_Object memory_signal_data; 3207extern Lisp_Object memory_signal_data;
@@ -4231,8 +4230,6 @@ extern int read_bytecode_char (bool);
4231 4230
4232/* Defined in bytecode.c. */ 4231/* Defined in bytecode.c. */
4233extern void syms_of_bytecode (void); 4232extern void syms_of_bytecode (void);
4234extern struct byte_stack *byte_stack_list;
4235extern void relocate_byte_stack (void);
4236extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object, 4233extern Lisp_Object exec_byte_code (Lisp_Object, Lisp_Object, Lisp_Object,
4237 Lisp_Object, ptrdiff_t, Lisp_Object *); 4234 Lisp_Object, ptrdiff_t, Lisp_Object *);
4238extern Lisp_Object get_byte_code_arity (Lisp_Object); 4235extern Lisp_Object get_byte_code_arity (Lisp_Object);
@@ -4530,12 +4527,14 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
4530 } \ 4527 } \
4531 } while (false) 4528 } while (false)
4532 4529
4533/* SAFE_ALLOCA_LISP allocates an array of Lisp_Objects. */ 4530/* Set BUF to point to an allocated array of NELT Lisp_Objects,
4531 immediately followed by EXTRA spare bytes. */
4534 4532
4535#define SAFE_ALLOCA_LISP(buf, nelt) \ 4533#define SAFE_ALLOCA_LISP_EXTRA(buf, nelt, extra) \
4536 do { \ 4534 do { \
4537 ptrdiff_t alloca_nbytes; \ 4535 ptrdiff_t alloca_nbytes; \
4538 if (INT_MULTIPLY_WRAPV (nelt, word_size, &alloca_nbytes) \ 4536 if (INT_MULTIPLY_WRAPV (nelt, word_size, &alloca_nbytes) \
4537 || INT_ADD_WRAPV (alloca_nbytes, extra, &alloca_nbytes) \
4539 || SIZE_MAX < alloca_nbytes) \ 4538 || SIZE_MAX < alloca_nbytes) \
4540 memory_full (SIZE_MAX); \ 4539 memory_full (SIZE_MAX); \
4541 else if (alloca_nbytes <= sa_avail) \ 4540 else if (alloca_nbytes <= sa_avail) \
@@ -4550,6 +4549,10 @@ extern void *record_xmalloc (size_t) ATTRIBUTE_ALLOC_SIZE ((1));
4550 } \ 4549 } \
4551 } while (false) 4550 } while (false)
4552 4551
4552/* Set BUF to point to an allocated array of NELT Lisp_Objects. */
4553
4554#define SAFE_ALLOCA_LISP(buf, nelt) SAFE_ALLOCA_LISP_EXTRA (buf, nelt, 0)
4555
4553 4556
4554/* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate 4557/* If USE_STACK_LISP_OBJECTS, define macros that and functions that allocate
4555 block-scoped conses and strings. These objects are not 4558 block-scoped conses and strings. These objects are not