comparison src/bytecode.c @ 4921:17362f371cc2

add more byte-code assertions and better failure output -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-02-03 Ben Wing <ben@xemacs.org> * alloc.c (Fmake_byte_code): * bytecode.h: * lisp.h: * lread.c: * lread.c (readevalloop): * lread.c (Fread): * lread.c (Fread_from_string): * lread.c (read_list_conser): * lread.c (read_list): * lread.c (vars_of_lread): * symbols.c: * symbols.c (Fdefine_function): Turn on the "compiled-function annotation hack". Implement it properly by hooking into Fdefalias(). Note in the docstring to `defalias' that we do this. Remove some old broken code and change code that implemented the old kludgy way of hooking into the Lisp reader into bracketed by `#ifdef COMPILED_FUNCTION_ANNOTATION_HACK_OLD_WAY', which is not enabled. Also enable byte-code metering when DEBUG_XEMACS -- this is a form of profiling for computing histograms of which sequences of two bytecodes are used most often. * bytecode-ops.h: * bytecode-ops.h (OPCODE): New file. Extract out all the opcodes and declare them using OPCODE(), a bit like frame slots and such. This way the file can be included multiple times if necessary to iterate multiple times over the byte opcodes. * bytecode.c: * bytecode.c (NUM_REMEMBERED_BYTE_OPS): * bytecode.c (OPCODE): * bytecode.c (assert_failed_with_remembered_ops): * bytecode.c (READ_UINT_2): * bytecode.c (READ_INT_1): * bytecode.c (READ_INT_2): * bytecode.c (PEEK_INT_1): * bytecode.c (PEEK_INT_2): * bytecode.c (JUMP_RELATIVE): * bytecode.c (JUMP_NEXT): * bytecode.c (PUSH): * bytecode.c (POP_WITH_MULTIPLE_VALUES): * bytecode.c (DISCARD): * bytecode.c (UNUSED): * bytecode.c (optimize_byte_code): * bytecode.c (optimize_compiled_function): * bytecode.c (Fbyte_code): * bytecode.c (vars_of_bytecode): * bytecode.c (init_opcode_table_multi_op): * bytecode.c (reinit_vars_of_bytecode): * emacs.c (main_1): * eval.c (funcall_compiled_function): * symsinit.h: Any time we change either the instruction pointer or the stack pointer, assert that we're going to move it to a valid location. This should catch failures right when they occur rather than sometime later. This requires that we pass in another couple of parameters into some functions (only with error-checking enabled, see below). Also keep track, using a circular queue, of the last 100 byte opcodes seen, and when we hit an assert failure during byte-code execution, output the contents of the queue in a nice readable fashion. This requires that bytecode-ops.h be included a second time so that a table mapping opcodes to the name of their operation can be constructed. This table is constructed in new function reinit_vars_of_bytecode(). Everything in the last two paras happens only when ERROR_CHECK_BYTE_CODE. Add some longish comments describing how the arrays that hold the stack and instructions, and the pointers used to access them, work. * gc.c: Import some code from my `latest-fix' workspace to mark the staticpro's in order from lowest to highest, rather than highest to lowest, so it's easier to debug when something goes wrong. * lisp.h (abort_with_message): Renamed from abort_with_msg(). * symbols.c (defsymbol_massage_name_1): * symbols.c (defsymbol_nodump): * symbols.c (defsymbol): * symbols.c (defkeyword): * symeval.h (DEFVAR_SYMVAL_FWD_OBJECT): Make the various calls to staticpro() instead call staticpro_1(), passing in the name of the C var being staticpro'ed, so that it shows up in staticpro_names. Otherwise staticpro_names just has 1000+ copies of the word `location'.
author Ben Wing <ben@xemacs.org>
date Wed, 03 Feb 2010 08:01:55 -0600
parents 1628e3b9601a
children 053f3c9af8c0
comparison
equal deleted inserted replaced
4914:1628e3b9601a 4921:17362f371cc2
56 #include "bytecode.h" 56 #include "bytecode.h"
57 #include "opaque.h" 57 #include "opaque.h"
58 #include "syntax.h" 58 #include "syntax.h"
59 #include "window.h" 59 #include "window.h"
60 60
61 #define NUM_REMEMBERED_BYTE_OPS 100
62
61 #ifdef NEW_GC 63 #ifdef NEW_GC
62 static Lisp_Object 64 static Lisp_Object
63 make_compiled_function_args (int totalargs) 65 make_compiled_function_args (int totalargs)
64 { 66 {
65 Lisp_Compiled_Function_Args *args; 67 Lisp_Compiled_Function_Args *args;
99 101
100 EXFUN (Ffetch_bytecode, 1); 102 EXFUN (Ffetch_bytecode, 1);
101 103
102 Lisp_Object Qbyte_code, Qcompiled_functionp, Qinvalid_byte_code; 104 Lisp_Object Qbyte_code, Qcompiled_functionp, Qinvalid_byte_code;
103 105
106
104 enum Opcode /* Byte codes */ 107 enum Opcode /* Byte codes */
105 { 108 {
106 Bvarref = 010, 109 #define OPCODE(sym, val) B##sym = val,
107 Bvarset = 020, 110 #include "bytecode-ops.h"
108 Bvarbind = 030,
109 Bcall = 040,
110 Bunbind = 050,
111
112 Bnth = 070,
113 Bsymbolp = 071,
114 Bconsp = 072,
115 Bstringp = 073,
116 Blistp = 074,
117 Bold_eq = 075,
118 Bold_memq = 076,
119 Bnot = 077,
120 Bcar = 0100,
121 Bcdr = 0101,
122 Bcons = 0102,
123 Blist1 = 0103,
124 Blist2 = 0104,
125 Blist3 = 0105,
126 Blist4 = 0106,
127 Blength = 0107,
128 Baref = 0110,
129 Baset = 0111,
130 Bsymbol_value = 0112,
131 Bsymbol_function = 0113,
132 Bset = 0114,
133 Bfset = 0115,
134 Bget = 0116,
135 Bsubstring = 0117,
136 Bconcat2 = 0120,
137 Bconcat3 = 0121,
138 Bconcat4 = 0122,
139 Bsub1 = 0123,
140 Badd1 = 0124,
141 Beqlsign = 0125,
142 Bgtr = 0126,
143 Blss = 0127,
144 Bleq = 0130,
145 Bgeq = 0131,
146 Bdiff = 0132,
147 Bnegate = 0133,
148 Bplus = 0134,
149 Bmax = 0135,
150 Bmin = 0136,
151 Bmult = 0137,
152
153 Bpoint = 0140,
154 Beq = 0141, /* was Bmark,
155 but no longer generated as of v18 */
156 Bgoto_char = 0142,
157 Binsert = 0143,
158 Bpoint_max = 0144,
159 Bpoint_min = 0145,
160 Bchar_after = 0146,
161 Bfollowing_char = 0147,
162 Bpreceding_char = 0150,
163 Bcurrent_column = 0151,
164 Bindent_to = 0152,
165 Bequal = 0153, /* was Bscan_buffer,
166 but no longer generated as of v18 */
167 Beolp = 0154,
168 Beobp = 0155,
169 Bbolp = 0156,
170 Bbobp = 0157,
171 Bcurrent_buffer = 0160,
172 Bset_buffer = 0161,
173 Bsave_current_buffer = 0162, /* was Bread_char,
174 but no longer generated as of v19 */
175 Bmemq = 0163, /* was Bset_mark,
176 but no longer generated as of v18 */
177 Binteractive_p = 0164, /* Needed since interactive-p takes
178 unevalled args */
179 Bforward_char = 0165,
180 Bforward_word = 0166,
181 Bskip_chars_forward = 0167,
182 Bskip_chars_backward = 0170,
183 Bforward_line = 0171,
184 Bchar_syntax = 0172,
185 Bbuffer_substring = 0173,
186 Bdelete_region = 0174,
187 Bnarrow_to_region = 0175,
188 Bwiden = 0176,
189 Bend_of_line = 0177,
190
191 Bconstant2 = 0201,
192 Bgoto = 0202,
193 Bgotoifnil = 0203,
194 Bgotoifnonnil = 0204,
195 Bgotoifnilelsepop = 0205,
196 Bgotoifnonnilelsepop = 0206,
197 Breturn = 0207,
198 Bdiscard = 0210,
199 Bdup = 0211,
200
201 Bsave_excursion = 0212,
202 Bsave_window_excursion= 0213,
203 Bsave_restriction = 0214,
204 Bcatch = 0215,
205
206 Bunwind_protect = 0216,
207 Bcondition_case = 0217,
208 Btemp_output_buffer_setup = 0220,
209 Btemp_output_buffer_show = 0221,
210
211 Bunbind_all = 0222,
212
213 Bset_marker = 0223,
214 Bmatch_beginning = 0224,
215 Bmatch_end = 0225,
216 Bupcase = 0226,
217 Bdowncase = 0227,
218
219 Bstring_equal = 0230,
220 Bstring_lessp = 0231,
221 Bold_equal = 0232,
222 Bnthcdr = 0233,
223 Belt = 0234,
224 Bold_member = 0235,
225 Bold_assq = 0236,
226 Bnreverse = 0237,
227 Bsetcar = 0240,
228 Bsetcdr = 0241,
229 Bcar_safe = 0242,
230 Bcdr_safe = 0243,
231 Bnconc = 0244,
232 Bquo = 0245,
233 Brem = 0246,
234 Bnumberp = 0247,
235 Bfixnump = 0250, /* Was Bintegerp. */
236
237 BRgoto = 0252,
238 BRgotoifnil = 0253,
239 BRgotoifnonnil = 0254,
240 BRgotoifnilelsepop = 0255,
241 BRgotoifnonnilelsepop = 0256,
242
243 BlistN = 0257,
244 BconcatN = 0260,
245 BinsertN = 0261,
246
247 Bbind_multiple_value_limits = 0262, /* New in 21.5. */
248 Bmultiple_value_list_internal = 0263, /* New in 21.5. */
249 Bmultiple_value_call = 0264, /* New in 21.5. */
250 Bthrow = 0265, /* New in 21.5. */
251
252 Bmember = 0266, /* new in v20 */
253 Bassq = 0267, /* new in v20 */
254
255 Bconstant = 0300
256 }; 111 };
257 typedef enum Opcode Opcode; 112 typedef enum Opcode Opcode;
258
259 113
260 Lisp_Object * execute_rare_opcode (Lisp_Object *stack_ptr, 114 Lisp_Object * execute_rare_opcode (Lisp_Object *stack_ptr,
115 #ifdef ERROR_CHECK_BYTE_CODE
116 Lisp_Object *stack_beg,
117 Lisp_Object *stack_end,
118 #endif /* ERROR_CHECK_BYTE_CODE */
261 const Opbyte *program_ptr, 119 const Opbyte *program_ptr,
262 Opcode opcode); 120 Opcode opcode);
263 121
264 /* Define BYTE_CODE_METER to enable generation of a byte-op usage histogram. 122 #ifndef ERROR_CHECK_BYTE_CODE
265 This isn't defined in FSF Emacs and isn't defined in XEmacs v19. */ 123
266 /* #define BYTE_CODE_METER */ 124 # define bytecode_assert(x) disabled_assert (x)
125 # define bytecode_assert_with_message(x, msg) disabled_assert(x)
126 # define bytecode_abort_with_message(msg) abort_with_message (msg)
127
128 #else /* ERROR_CHECK_BYTE_CODE */
129
130 # define bytecode_assert(x) \
131 ((x) ? (void) 0 : assert_failed_with_remembered_ops (__FILE__, __LINE__, #x))
132 # define bytecode_assert_with_message(x, msg) \
133 ((x) ? (void) 0 : assert_failed_with_remembered_ops (__FILE__, __LINE__, msg))
134 # define bytecode_abort_with_message(msg) \
135 assert_failed_with_remembered_ops (__FILE__, __LINE__, msg)
136
137 /* Table mapping opcodes to their names. This handles opcodes like
138 Bvarref+7, but it doesn't list any of the Bconstant+N opcodes; those
139 are handled specially. */
140 Ascbyte *opcode_name_table[256];
141
142 /* Circular queue remembering the most recent operations. */
143 Opcode remembered_ops[NUM_REMEMBERED_BYTE_OPS];
144 int remembered_op_next_pos, num_remembered;
145
146 static void
147 remember_operation (Opcode op)
148 {
149 remembered_ops[remembered_op_next_pos] = op;
150 remembered_op_next_pos =
151 (remembered_op_next_pos + 1) % NUM_REMEMBERED_BYTE_OPS;
152 if (num_remembered < NUM_REMEMBERED_BYTE_OPS)
153 num_remembered++;
154 }
155
156 static void
157 assert_failed_with_remembered_ops (const Ascbyte *file, int line,
158 Ascbyte *msg_to_abort_with)
159 {
160 Ascbyte *msg =
161 alloca_array (Ascbyte,
162 NUM_REMEMBERED_BYTE_OPS*50 + strlen (msg_to_abort_with));
163 int i;
164
165 if (msg_to_abort_with)
166 strcpy (msg, msg_to_abort_with);
167 strcat (msg, "\n\nRecent bytecodes, oldest first:\n\n");
168
169 for (i = 0; i < num_remembered; i++)
170 {
171 Ascbyte msg2[50];
172 int pos;
173 Opcode op;
174
175 sprintf (msg2, "%5d: ", i - num_remembered + 1);
176 strcat (msg, msg2);
177 pos = (remembered_op_next_pos + NUM_REMEMBERED_BYTE_OPS +
178 i - num_remembered) % NUM_REMEMBERED_BYTE_OPS;
179 op = remembered_ops[pos];
180 if (op >= Bconstant)
181 {
182 sprintf (msg2, "constant+%d", op - Bconstant);
183 strcat (msg, msg2);
184 }
185 else
186 {
187 Ascbyte *opname = opcode_name_table[op];
188 if (!opname)
189 {
190 stderr_out ("Internal error! NULL pointer in opcode_name_table, opcode %d\n", op);
191 strcat (msg, "NULL");
192 }
193 else
194 strcat (msg, opname);
195 }
196 sprintf (msg2, " (%d)\n", op);
197 strcat (msg, msg2);
198 }
199
200 assert_failed (file, line, msg);
201 }
202
203 #endif /* ERROR_CHECK_BYTE_CODE */
267 204
268 205
269 #ifdef BYTE_CODE_METER 206 #ifdef BYTE_CODE_METER
270 207
271 Lisp_Object Vbyte_code_meter, Qbyte_code_meter; 208 Lisp_Object Vbyte_code_meter, Qbyte_code_meter;
617 } 554 }
618 #endif /* WITH_NUMBER_TYPES */ 555 #endif /* WITH_NUMBER_TYPES */
619 } 556 }
620 557
621 558
559
560 /*********************** The instruction array *********************/
561
562 /* Check that there are at least LEN elements left in the end of the
563 instruction array before fetching them. Note that we allow for
564 PROGRAM_PTR == PROGRAM_END after the fetch -- that means there are
565 no more elements to fetch next time around, but we might exit before
566 next time comes.
567
568 When checking the destination if jumps, however, we don't allow
569 PROGRAM_PTR to equal PROGRAM_END, since we will always be fetching
570 another instruction after the jump. */
571
572 #define CHECK_OPCODE_SPACE(len) \
573 bytecode_assert (program_ptr + len <= program_end)
574
622 /* Read next uint8 from the instruction stream. */ 575 /* Read next uint8 from the instruction stream. */
623 #define READ_UINT_1 ((unsigned int) (unsigned char) *program_ptr++) 576 #define READ_UINT_1 \
577 (CHECK_OPCODE_SPACE (1), (unsigned int) (unsigned char) *program_ptr++)
624 578
625 /* Read next uint16 from the instruction stream. */ 579 /* Read next uint16 from the instruction stream. */
626 #define READ_UINT_2 \ 580 #define READ_UINT_2 \
627 (program_ptr += 2, \ 581 (CHECK_OPCODE_SPACE (2), \
582 program_ptr += 2, \
628 (((unsigned int) (unsigned char) program_ptr[-1]) * 256 + \ 583 (((unsigned int) (unsigned char) program_ptr[-1]) * 256 + \
629 ((unsigned int) (unsigned char) program_ptr[-2]))) 584 ((unsigned int) (unsigned char) program_ptr[-2])))
630 585
631 /* Read next int8 from the instruction stream. */ 586 /* Read next int8 from the instruction stream. */
632 #define READ_INT_1 ((int) (signed char) *program_ptr++) 587 #define READ_INT_1 \
588 (CHECK_OPCODE_SPACE (1), (int) (signed char) *program_ptr++)
633 589
634 /* Read next int16 from the instruction stream. */ 590 /* Read next int16 from the instruction stream. */
635 #define READ_INT_2 \ 591 #define READ_INT_2 \
636 (program_ptr += 2, \ 592 (CHECK_OPCODE_SPACE (2), \
593 program_ptr += 2, \
637 (((int) ( signed char) program_ptr[-1]) * 256 + \ 594 (((int) ( signed char) program_ptr[-1]) * 256 + \
638 ((int) (unsigned char) program_ptr[-2]))) 595 ((int) (unsigned char) program_ptr[-2])))
639 596
640 /* Read next int8 from instruction stream; don't advance program_pointer */ 597 /* Read next int8 from instruction stream; don't advance program_pointer */
641 #define PEEK_INT_1 ((int) (signed char) program_ptr[0]) 598 #define PEEK_INT_1 \
599 (CHECK_OPCODE_SPACE (1), (int) (signed char) program_ptr[0])
642 600
643 /* Read next int16 from instruction stream; don't advance program_pointer */ 601 /* Read next int16 from instruction stream; don't advance program_pointer */
644 #define PEEK_INT_2 \ 602 #define PEEK_INT_2 \
645 ((((int) ( signed char) program_ptr[1]) * 256) | \ 603 (CHECK_OPCODE_SPACE (2), \
604 (((int) ( signed char) program_ptr[1]) * 256) | \
646 ((int) (unsigned char) program_ptr[0])) 605 ((int) (unsigned char) program_ptr[0]))
647 606
648 /* Do relative jumps from the current location. 607 /* Do relative jumps from the current location.
649 We only do a QUIT if we jump backwards, for efficiency. 608 We only do a QUIT if we jump backwards, for efficiency.
650 No infloops without backward jumps! */ 609 No infloops without backward jumps! */
651 #define JUMP_RELATIVE(jump) do { \ 610 #define JUMP_RELATIVE(jump) do { \
652 int JR_jump = (jump); \ 611 int _JR_jump = (jump); \
653 if (JR_jump < 0) QUIT; \ 612 if (_JR_jump < 0) QUIT; \
654 program_ptr += JR_jump; \ 613 /* Check that where we're going to is in range. Note that we don't use \
614 CHECK_OPCODE_SPACE() -- that only checks the end, and it allows \
615 program_ptr == program_end, which we don't allow. */ \
616 bytecode_assert (program_ptr + _JR_jump >= program && \
617 program_ptr + _JR_jump < program_end); \
618 program_ptr += _JR_jump; \
655 } while (0) 619 } while (0)
656 620
657 #define JUMP JUMP_RELATIVE (PEEK_INT_2) 621 #define JUMP JUMP_RELATIVE (PEEK_INT_2)
658 #define JUMPR JUMP_RELATIVE (PEEK_INT_1) 622 #define JUMPR JUMP_RELATIVE (PEEK_INT_1)
659 623
660 #define JUMP_NEXT ((void) (program_ptr += 2)) 624 #define JUMP_NEXT (CHECK_OPCODE_SPACE (2), (void) (program_ptr += 2))
661 #define JUMPR_NEXT ((void) (program_ptr += 1)) 625 #define JUMPR_NEXT (CHECK_OPCODE_SPACE (1), (void) (program_ptr += 1))
626
627 /*********************** The stack array *********************/
628
629 /* NOTE: The stack array doesn't work quite like you'd expect.
630
631 STACK_PTR points to the value on the top of the stack. Popping a value
632 fetches the value from the STACK_PTR and then decrements it. Pushing a
633 value first increments it, then writes the new value. STACK_PTR -
634 STACK_BEG is the number of elements on the stack.
635
636 This means that when STACK_PTR == STACK_BEG, the stack is empty, and
637 the space at STACK_BEG is never written to -- the first push will write
638 into the space directly after STACK_BEG. This is why the call to
639 alloca_array() below has a count of `stack_depth + 1', and why
640 we GCPRO1 (stack_ptr[1]) -- the value at stack_ptr[0] is unused and
641 uninitialized.
642
643 Also, STACK_END actually points to the last usable storage location,
644 and does not point past the end, like you'd expect. */
645
646 #define CHECK_STACKPTR_OFFSET(len) \
647 bytecode_assert (stack_ptr + (len) >= stack_beg && \
648 stack_ptr + (len) <= stack_end)
662 649
663 /* Push x onto the execution stack. */ 650 /* Push x onto the execution stack. */
664 #define PUSH(x) (*++stack_ptr = (x)) 651 #define PUSH(x) (CHECK_STACKPTR_OFFSET (1), *++stack_ptr = (x))
665 652
666 /* Pop a value, which may be multiple, off the execution stack. */ 653 /* Pop a value, which may be multiple, off the execution stack. */
667 #define POP_WITH_MULTIPLE_VALUES (*stack_ptr--) 654 #define POP_WITH_MULTIPLE_VALUES (CHECK_STACKPTR_OFFSET (-1), *stack_ptr--)
668 655
669 /* Pop a value off the execution stack, treating multiple values as single. */ 656 /* Pop a value off the execution stack, treating multiple values as single. */
670 #define POP (IGNORE_MULTIPLE_VALUES (POP_WITH_MULTIPLE_VALUES)) 657 #define POP (IGNORE_MULTIPLE_VALUES (POP_WITH_MULTIPLE_VALUES))
671 658
672 #define DISCARD_PRESERVING_MULTIPLE_VALUES(n) (stack_ptr -= (n)) 659 /* ..._UNSAFE() means it evaluates its argument more than once. */
660 #define DISCARD_PRESERVING_MULTIPLE_VALUES_UNSAFE(n) \
661 (CHECK_STACKPTR_OFFSET (-(n)), stack_ptr -= (n))
673 662
674 /* Discard n values from the execution stack. */ 663 /* Discard n values from the execution stack. */
675 #define DISCARD(n) do { \ 664 #define DISCARD(n) do { \
665 int _discard_n = (n); \
676 if (1 != multiple_value_current_limit) \ 666 if (1 != multiple_value_current_limit) \
677 { \ 667 { \
678 int i, en = n; \ 668 int i; \
679 for (i = 0; i < en; i++) \ 669 for (i = 0; i < _discard_n; i++) \
680 { \ 670 { \
671 CHECK_STACKPTR_OFFSET (-1); \
681 *stack_ptr = ignore_multiple_values (*stack_ptr); \ 672 *stack_ptr = ignore_multiple_values (*stack_ptr); \
682 stack_ptr--; \ 673 stack_ptr--; \
683 } \ 674 } \
684 } \ 675 } \
685 else \ 676 else \
686 { \ 677 { \
687 stack_ptr -= (n); \ 678 CHECK_STACKPTR_OFFSET (-_discard_n); \
679 stack_ptr -= _discard_n; \
688 } \ 680 } \
689 } while (0) 681 } while (0)
690 682
691 /* Get the value, which may be multiple, at the top of the execution stack; 683 /* Get the value, which may be multiple, at the top of the execution stack;
692 and leave it there. */ 684 and leave it there. */
702 694
703 695
704 696
705 /* See comment before the big switch in execute_optimized_program(). */ 697 /* See comment before the big switch in execute_optimized_program(). */
706 #define GCPRO_STACK (gcpro1.nvars = stack_ptr - stack_beg) 698 #define GCPRO_STACK (gcpro1.nvars = stack_ptr - stack_beg)
699
707 700
708 /* The actual interpreter for byte code. 701 /* The actual interpreter for byte code.
709 This function has been seriously optimized for performance. 702 This function has been seriously optimized for performance.
710 Don't change the constructs unless you are willing to do 703 Don't change the constructs unless you are willing to do
711 real benchmarking and profiling work -- martin */ 704 real benchmarking and profiling work -- martin */
712 705
713 706
714 Lisp_Object 707 Lisp_Object
715 execute_optimized_program (const Opbyte *program, 708 execute_optimized_program (const Opbyte *program,
709 #ifdef ERROR_CHECK_BYTE_CODE
710 Elemcount program_length,
711 #endif
716 int stack_depth, 712 int stack_depth,
717 Lisp_Object *constants_data) 713 Lisp_Object *constants_data)
718 { 714 {
719 /* This function can GC */ 715 /* This function can GC */
720 REGISTER const Opbyte *program_ptr = (Opbyte *) program; 716 REGISTER const Opbyte *program_ptr = (Opbyte *) program;
717 #ifdef ERROR_CHECK_BYTE_CODE
718 const Opbyte *program_end = program_ptr + program_length;
719 #endif
720 /* See comment above explaining the `+ 1' */
721 Lisp_Object *stack_beg = alloca_array (Lisp_Object, stack_depth + 1); 721 Lisp_Object *stack_beg = alloca_array (Lisp_Object, stack_depth + 1);
722 REGISTER Lisp_Object *stack_ptr = stack_beg; 722 REGISTER Lisp_Object *stack_ptr = stack_beg;
723 int speccount = specpdl_depth (); 723 int speccount = specpdl_depth ();
724 struct gcpro gcpro1; 724 struct gcpro gcpro1;
725 725
757 loses its reference and is effectively UNGCPROed, and the new object is 757 loses its reference and is effectively UNGCPROed, and the new object is
758 automatically GCPROed as long as nvars is correct. Only when we 758 automatically GCPROed as long as nvars is correct. Only when we
759 return from the interpreter do we need to finalize the struct gcpro 759 return from the interpreter do we need to finalize the struct gcpro
760 itself, and that's done at case Breturn. 760 itself, and that's done at case Breturn.
761 */ 761 */
762
763 /* See comment above explaining the `[1]' */
762 GCPRO1 (stack_ptr[1]); 764 GCPRO1 (stack_ptr[1]);
763 765
764 while (1) 766 while (1)
765 { 767 {
766 REGISTER Opcode opcode = (Opcode) READ_UINT_1; 768 REGISTER Opcode opcode = (Opcode) READ_UINT_1;
767 769
770 #ifdef ERROR_CHECK_BYTE_CODE
771 remember_operation (opcode);
772 #endif
773
768 GCPRO_STACK; /* Get nvars right before maybe signaling. */ 774 GCPRO_STACK; /* Get nvars right before maybe signaling. */
775 /* #### NOTE: This code should probably never get triggered, since we
776 now catch the problems earlier, farther down, before we ever set
777 a bad value for STACK_PTR. */
769 #ifdef ERROR_CHECK_BYTE_CODE 778 #ifdef ERROR_CHECK_BYTE_CODE
770 if (stack_ptr > stack_end) 779 if (stack_ptr > stack_end)
771 stack_overflow ("byte code stack overflow", Qunbound); 780 stack_overflow ("byte code stack overflow", Qunbound);
772 if (stack_ptr < stack_beg) 781 if (stack_ptr < stack_beg)
773 stack_overflow ("byte code stack underflow", Qunbound); 782 stack_overflow ("byte code stack underflow", Qunbound);
788 PUSH (constants_data[opcode - Bconstant]); 797 PUSH (constants_data[opcode - Bconstant]);
789 else 798 else
790 { 799 {
791 /* We're not sure what these do, so better safe than sorry. */ 800 /* We're not sure what these do, so better safe than sorry. */
792 /* GCPRO_STACK; */ 801 /* GCPRO_STACK; */
793 stack_ptr = execute_rare_opcode (stack_ptr, program_ptr, opcode); 802 stack_ptr = execute_rare_opcode (stack_ptr,
803 #ifdef ERROR_CHECK_BYTE_CODE
804 stack_beg,
805 stack_end,
806 #endif /* ERROR_CHECK_BYTE_CODE */
807 program_ptr, opcode);
808 CHECK_STACKPTR_OFFSET (0);
794 } 809 }
795 break; 810 break;
796 811
797 case Bvarref: 812 case Bvarref:
798 case Bvarref+1: 813 case Bvarref+1:
1436 rarely executed code, to minimize cache misses. 1451 rarely executed code, to minimize cache misses.
1437 1452
1438 Don't make this function static, since then the compiler might inline it. */ 1453 Don't make this function static, since then the compiler might inline it. */
1439 Lisp_Object * 1454 Lisp_Object *
1440 execute_rare_opcode (Lisp_Object *stack_ptr, 1455 execute_rare_opcode (Lisp_Object *stack_ptr,
1456 #ifdef ERROR_CHECK_BYTE_CODE
1457 Lisp_Object *stack_beg,
1458 Lisp_Object *stack_end,
1459 #endif /* ERROR_CHECK_BYTE_CODE */
1441 const Opbyte *UNUSED (program_ptr), 1460 const Opbyte *UNUSED (program_ptr),
1442 Opcode opcode) 1461 Opcode opcode)
1443 { 1462 {
1444 REGISTER int n; 1463 REGISTER int n;
1445 1464
1446 switch (opcode) 1465 switch (opcode)
1447 { 1466 {
1448 1467
1449 case Bsave_excursion: 1468 case Bsave_excursion:
1450 record_unwind_protect (save_excursion_restore, 1469 record_unwind_protect (save_excursion_restore,
1451 save_excursion_save ()); 1470 save_excursion_save ());
1452 break; 1471 break;
1453 1472
1712 } 1731 }
1713 1732
1714 case Bmultiple_value_call: 1733 case Bmultiple_value_call:
1715 { 1734 {
1716 n = XINT (POP); 1735 n = XINT (POP);
1717 DISCARD_PRESERVING_MULTIPLE_VALUES (n - 1); 1736 DISCARD_PRESERVING_MULTIPLE_VALUES_UNSAFE (n - 1);
1718 /* Discard multiple values for the first (function) argument: */ 1737 /* Discard multiple values for the first (function) argument: */
1719 TOP_LVALUE = TOP; 1738 TOP_LVALUE = TOP;
1720 TOP_LVALUE = multiple_value_call (n, TOP_ADDRESS); 1739 TOP_LVALUE = multiple_value_call (n, TOP_ADDRESS);
1721 break; 1740 break;
1722 } 1741 }
1723 1742
1724 case Bmultiple_value_list_internal: 1743 case Bmultiple_value_list_internal:
1725 { 1744 {
1726 DISCARD_PRESERVING_MULTIPLE_VALUES (3); 1745 DISCARD_PRESERVING_MULTIPLE_VALUES_UNSAFE (3);
1727 TOP_LVALUE = multiple_value_list_internal (4, TOP_ADDRESS); 1746 TOP_LVALUE = multiple_value_list_internal (4, TOP_ADDRESS);
1728 break; 1747 break;
1729 } 1748 }
1730 1749
1731 case Bthrow: 1750 case Bthrow:
1739 1758
1740 default: 1759 default:
1741 { 1760 {
1742 Ascbyte msg[100]; 1761 Ascbyte msg[100];
1743 sprintf (msg, "Unknown opcode %d", opcode); 1762 sprintf (msg, "Unknown opcode %d", opcode);
1744 abort_with_msg (msg); 1763 bytecode_abort_with_message (msg);
1745 } 1764 }
1746 break; 1765 break;
1747 } 1766 }
1748 return stack_ptr; 1767 return stack_ptr;
1749 } 1768 }
1864 optimize_byte_code (/* in */ 1883 optimize_byte_code (/* in */
1865 Lisp_Object instructions, 1884 Lisp_Object instructions,
1866 Lisp_Object constants, 1885 Lisp_Object constants,
1867 /* out */ 1886 /* out */
1868 Opbyte * const program, 1887 Opbyte * const program,
1869 int * const program_length, 1888 Elemcount * const program_length,
1870 int * const varbind_count) 1889 Elemcount * const varbind_count)
1871 { 1890 {
1872 Bytecount instructions_length = XSTRING_LENGTH (instructions); 1891 Bytecount instructions_length = XSTRING_LENGTH (instructions);
1873 Elemcount comfy_size = (Elemcount) (2 * instructions_length); 1892 Elemcount comfy_size = (Elemcount) (2 * instructions_length);
1874 1893
1875 int * const icounts = alloca_array (int, comfy_size); 1894 int * const icounts = alloca_array (int, comfy_size);
2129 instructions slot of the Compiled_Function object. */ 2148 instructions slot of the Compiled_Function object. */
2130 void 2149 void
2131 optimize_compiled_function (Lisp_Object compiled_function) 2150 optimize_compiled_function (Lisp_Object compiled_function)
2132 { 2151 {
2133 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (compiled_function); 2152 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (compiled_function);
2134 int program_length; 2153 Elemcount program_length;
2135 int varbind_count; 2154 Elemcount varbind_count;
2136 Opbyte *program; 2155 Opbyte *program;
2137 2156
2138 { 2157 {
2139 int minargs = 0, maxargs = 0, totalargs = 0; 2158 int minargs = 0, maxargs = 0, totalargs = 0;
2140 int optional_p = 0, rest_p = 0, i = 0; 2159 int optional_p = 0, rest_p = 0, i = 0;
2702 If STACK-DEPTH is incorrect, Emacs may crash. 2721 If STACK-DEPTH is incorrect, Emacs may crash.
2703 */ 2722 */
2704 (instructions, constants, stack_depth)) 2723 (instructions, constants, stack_depth))
2705 { 2724 {
2706 /* This function can GC */ 2725 /* This function can GC */
2707 int varbind_count; 2726 Elemcount varbind_count;
2708 int program_length; 2727 Elemcount program_length;
2709 Opbyte *program; 2728 Opbyte *program;
2710 2729
2711 CHECK_STRING (instructions); 2730 CHECK_STRING (instructions);
2712 CHECK_VECTOR (constants); 2731 CHECK_VECTOR (constants);
2713 CHECK_NATNUM (stack_depth); 2732 CHECK_NATNUM (stack_depth);
2718 program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (instructions)); 2737 program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (instructions));
2719 optimize_byte_code (instructions, constants, program, 2738 optimize_byte_code (instructions, constants, program,
2720 &program_length, &varbind_count); 2739 &program_length, &varbind_count);
2721 SPECPDL_RESERVE (varbind_count); 2740 SPECPDL_RESERVE (varbind_count);
2722 return execute_optimized_program (program, 2741 return execute_optimized_program (program,
2742 #ifdef ERROR_CHECK_BYTE_CODE
2743 program_length,
2744 #endif
2723 XINT (stack_depth), 2745 XINT (stack_depth),
2724 XVECTOR_DATA (constants)); 2746 XVECTOR_DATA (constants));
2725 } 2747 }
2726 2748
2727 2749
2760 2782
2761 void 2783 void
2762 vars_of_bytecode (void) 2784 vars_of_bytecode (void)
2763 { 2785 {
2764 #ifdef BYTE_CODE_METER 2786 #ifdef BYTE_CODE_METER
2765
2766 DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter /* 2787 DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter /*
2767 A vector of vectors which holds a histogram of byte code usage. 2788 A vector of vectors which holds a histogram of byte code usage.
2768 \(aref (aref byte-code-meter 0) CODE) indicates how many times the byte 2789 \(aref (aref byte-code-meter 0) CODE) indicates how many times the byte
2769 opcode CODE has been executed. 2790 opcode CODE has been executed.
2770 \(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0, 2791 \(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0,
2785 while (i--) 2806 while (i--)
2786 XVECTOR_DATA (Vbyte_code_meter)[i] = make_vector (256, Qzero); 2807 XVECTOR_DATA (Vbyte_code_meter)[i] = make_vector (256, Qzero);
2787 } 2808 }
2788 #endif /* BYTE_CODE_METER */ 2809 #endif /* BYTE_CODE_METER */
2789 } 2810 }
2811
2812 #ifdef ERROR_CHECK_BYTE_CODE
2813
2814 /* Initialize the opcodes in the table that correspond to a base opcode
2815 plus an offset (except for Bconstant). */
2816
2817 static void
2818 init_opcode_table_multi_op (Opcode op)
2819 {
2820 Ascbyte *basename = opcode_name_table[op];
2821 Ascbyte temp[300];
2822 int i;
2823
2824 for (i = 1; i < 7; i++)
2825 {
2826 assert (!opcode_name_table[op + i]);
2827 sprintf (temp, "%s+%d", basename, i);
2828 opcode_name_table[op + i] = xstrdup (temp);
2829 }
2830 }
2831
2832 #endif /* ERROR_CHECK_BYTE_CODE */
2833
2834 void
2835 reinit_vars_of_bytecode (void)
2836 {
2837 #ifdef ERROR_CHECK_BYTE_CODE
2838 int i;
2839
2840 #define OPCODE(sym, val) opcode_name_table[val] = xstrdup (#sym);
2841 #include "bytecode-ops.h"
2842
2843 for (i = 0; i < countof (opcode_name_table); i++)
2844 {
2845 int j;
2846 Ascbyte *name = opcode_name_table[i];
2847 if (name)
2848 {
2849 Bytecount len = strlen (name);
2850 /* Prettify the name by converting underscores to hyphens, similar
2851 to what happens with DEFSYMBOL. */
2852 for (j = 0; j < len; j++)
2853 if (name[j] == '_')
2854 name[j] = '-';
2855 }
2856 }
2857
2858 init_opcode_table_multi_op (Bvarref);
2859 init_opcode_table_multi_op (Bvarset);
2860 init_opcode_table_multi_op (Bvarbind);
2861 init_opcode_table_multi_op (Bcall);
2862 init_opcode_table_multi_op (Bunbind);
2863 #endif /* ERROR_CHECK_BYTE_CODE */
2864 }