comparison src/bytecode.c @ 5125:b5df3737028a ben-lisp-object

merge
author Ben Wing <ben@xemacs.org>
date Wed, 24 Feb 2010 01:58:04 -0600
parents 623d57b7fbe8 fe0d3106cc36
children a9c41067dd88
comparison
equal deleted inserted replaced
5124:623d57b7fbe8 5125:b5df3737028a
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;
98 100
99 EXFUN (Ffetch_bytecode, 1); 101 EXFUN (Ffetch_bytecode, 1);
100 102
101 Lisp_Object Qbyte_code, Qcompiled_functionp, Qinvalid_byte_code; 103 Lisp_Object Qbyte_code, Qcompiled_functionp, Qinvalid_byte_code;
102 104
105
103 enum Opcode /* Byte codes */ 106 enum Opcode /* Byte codes */
104 { 107 {
105 Bvarref = 010, 108 #define OPCODE(sym, val) B##sym = val,
106 Bvarset = 020, 109 #include "bytecode-ops.h"
107 Bvarbind = 030,
108 Bcall = 040,
109 Bunbind = 050,
110
111 Bnth = 070,
112 Bsymbolp = 071,
113 Bconsp = 072,
114 Bstringp = 073,
115 Blistp = 074,
116 Bold_eq = 075,
117 Bold_memq = 076,
118 Bnot = 077,
119 Bcar = 0100,
120 Bcdr = 0101,
121 Bcons = 0102,
122 Blist1 = 0103,
123 Blist2 = 0104,
124 Blist3 = 0105,
125 Blist4 = 0106,
126 Blength = 0107,
127 Baref = 0110,
128 Baset = 0111,
129 Bsymbol_value = 0112,
130 Bsymbol_function = 0113,
131 Bset = 0114,
132 Bfset = 0115,
133 Bget = 0116,
134 Bsubstring = 0117,
135 Bconcat2 = 0120,
136 Bconcat3 = 0121,
137 Bconcat4 = 0122,
138 Bsub1 = 0123,
139 Badd1 = 0124,
140 Beqlsign = 0125,
141 Bgtr = 0126,
142 Blss = 0127,
143 Bleq = 0130,
144 Bgeq = 0131,
145 Bdiff = 0132,
146 Bnegate = 0133,
147 Bplus = 0134,
148 Bmax = 0135,
149 Bmin = 0136,
150 Bmult = 0137,
151
152 Bpoint = 0140,
153 Beq = 0141, /* was Bmark,
154 but no longer generated as of v18 */
155 Bgoto_char = 0142,
156 Binsert = 0143,
157 Bpoint_max = 0144,
158 Bpoint_min = 0145,
159 Bchar_after = 0146,
160 Bfollowing_char = 0147,
161 Bpreceding_char = 0150,
162 Bcurrent_column = 0151,
163 Bindent_to = 0152,
164 Bequal = 0153, /* was Bscan_buffer,
165 but no longer generated as of v18 */
166 Beolp = 0154,
167 Beobp = 0155,
168 Bbolp = 0156,
169 Bbobp = 0157,
170 Bcurrent_buffer = 0160,
171 Bset_buffer = 0161,
172 Bsave_current_buffer = 0162, /* was Bread_char,
173 but no longer generated as of v19 */
174 Bmemq = 0163, /* was Bset_mark,
175 but no longer generated as of v18 */
176 Binteractive_p = 0164, /* Needed since interactive-p takes
177 unevalled args */
178 Bforward_char = 0165,
179 Bforward_word = 0166,
180 Bskip_chars_forward = 0167,
181 Bskip_chars_backward = 0170,
182 Bforward_line = 0171,
183 Bchar_syntax = 0172,
184 Bbuffer_substring = 0173,
185 Bdelete_region = 0174,
186 Bnarrow_to_region = 0175,
187 Bwiden = 0176,
188 Bend_of_line = 0177,
189
190 Bconstant2 = 0201,
191 Bgoto = 0202,
192 Bgotoifnil = 0203,
193 Bgotoifnonnil = 0204,
194 Bgotoifnilelsepop = 0205,
195 Bgotoifnonnilelsepop = 0206,
196 Breturn = 0207,
197 Bdiscard = 0210,
198 Bdup = 0211,
199
200 Bsave_excursion = 0212,
201 Bsave_window_excursion= 0213,
202 Bsave_restriction = 0214,
203 Bcatch = 0215,
204
205 Bunwind_protect = 0216,
206 Bcondition_case = 0217,
207 Btemp_output_buffer_setup = 0220,
208 Btemp_output_buffer_show = 0221,
209
210 Bunbind_all = 0222,
211
212 Bset_marker = 0223,
213 Bmatch_beginning = 0224,
214 Bmatch_end = 0225,
215 Bupcase = 0226,
216 Bdowncase = 0227,
217
218 Bstring_equal = 0230,
219 Bstring_lessp = 0231,
220 Bold_equal = 0232,
221 Bnthcdr = 0233,
222 Belt = 0234,
223 Bold_member = 0235,
224 Bold_assq = 0236,
225 Bnreverse = 0237,
226 Bsetcar = 0240,
227 Bsetcdr = 0241,
228 Bcar_safe = 0242,
229 Bcdr_safe = 0243,
230 Bnconc = 0244,
231 Bquo = 0245,
232 Brem = 0246,
233 Bnumberp = 0247,
234 Bintegerp = 0250,
235
236 BRgoto = 0252,
237 BRgotoifnil = 0253,
238 BRgotoifnonnil = 0254,
239 BRgotoifnilelsepop = 0255,
240 BRgotoifnonnilelsepop = 0256,
241
242 BlistN = 0257,
243 BconcatN = 0260,
244 BinsertN = 0261,
245
246 Bbind_multiple_value_limits = 0262, /* New in 21.5. */
247 Bmultiple_value_list_internal = 0263, /* New in 21.5. */
248 Bmultiple_value_call = 0264, /* New in 21.5. */
249 Bthrow = 0265, /* New in 21.5. */
250
251 Bmember = 0266, /* new in v20 */
252 Bassq = 0267, /* new in v20 */
253
254 Bconstant = 0300
255 }; 110 };
256 typedef enum Opcode Opcode; 111 typedef enum Opcode Opcode;
257
258 112
259 Lisp_Object * execute_rare_opcode (Lisp_Object *stack_ptr, 113 Lisp_Object * execute_rare_opcode (Lisp_Object *stack_ptr,
114 #ifdef ERROR_CHECK_BYTE_CODE
115 Lisp_Object *stack_beg,
116 Lisp_Object *stack_end,
117 #endif /* ERROR_CHECK_BYTE_CODE */
260 const Opbyte *program_ptr, 118 const Opbyte *program_ptr,
261 Opcode opcode); 119 Opcode opcode);
262 120
263 /* Define BYTE_CODE_METER to enable generation of a byte-op usage histogram. 121 #ifndef ERROR_CHECK_BYTE_CODE
264 This isn't defined in FSF Emacs and isn't defined in XEmacs v19. */ 122
265 /* #define BYTE_CODE_METER */ 123 /* Normally we would use `x' instead of `0' in the argument list, to avoid
124 problems if `x' (an expression) has side effects, and warnings if `x'
125 contains variables or parameters that are otherwise unused. But in
126 this case `x' contains references to vars and params that exist only
127 when ERROR_CHECK_BYTE_CODE, and leaving in `x' would result in compile
128 errors. */
129 # define bytecode_assert(x) disabled_assert (0)
130 # define bytecode_assert_with_message(x, msg) disabled_assert(0)
131 # define bytecode_abort_with_message(msg) abort_with_message (msg)
132
133 #else /* ERROR_CHECK_BYTE_CODE */
134
135 # define bytecode_assert(x) \
136 ((x) ? (void) 0 : assert_failed_with_remembered_ops (__FILE__, __LINE__, #x))
137 # define bytecode_assert_with_message(x, msg) \
138 ((x) ? (void) 0 : assert_failed_with_remembered_ops (__FILE__, __LINE__, msg))
139 # define bytecode_abort_with_message(msg) \
140 assert_failed_with_remembered_ops (__FILE__, __LINE__, msg)
141
142 /* Table mapping opcodes to their names. This handles opcodes like
143 Bvarref+7, but it doesn't list any of the Bconstant+N opcodes; those
144 are handled specially. */
145 Ascbyte *opcode_name_table[256];
146
147 /* Circular queue remembering the most recent operations. */
148 Opcode remembered_ops[NUM_REMEMBERED_BYTE_OPS];
149 int remembered_op_next_pos, num_remembered;
150
151 static void
152 remember_operation (Opcode op)
153 {
154 remembered_ops[remembered_op_next_pos] = op;
155 remembered_op_next_pos =
156 (remembered_op_next_pos + 1) % NUM_REMEMBERED_BYTE_OPS;
157 if (num_remembered < NUM_REMEMBERED_BYTE_OPS)
158 num_remembered++;
159 }
160
161 static void
162 assert_failed_with_remembered_ops (const Ascbyte *file, int line,
163 const Ascbyte *msg_to_abort_with)
164 {
165 Ascbyte *msg =
166 alloca_array (Ascbyte,
167 NUM_REMEMBERED_BYTE_OPS*50 + strlen (msg_to_abort_with));
168 int i;
169
170 if (msg_to_abort_with)
171 strcpy (msg, msg_to_abort_with);
172 strcat (msg, "\n\nRecent bytecodes, oldest first:\n\n");
173
174 for (i = 0; i < num_remembered; i++)
175 {
176 Ascbyte msg2[50];
177 int pos;
178 Opcode op;
179
180 sprintf (msg2, "%5d: ", i - num_remembered + 1);
181 strcat (msg, msg2);
182 pos = (remembered_op_next_pos + NUM_REMEMBERED_BYTE_OPS +
183 i - num_remembered) % NUM_REMEMBERED_BYTE_OPS;
184 op = remembered_ops[pos];
185 if (op >= Bconstant)
186 {
187 sprintf (msg2, "constant+%d", op - Bconstant);
188 strcat (msg, msg2);
189 }
190 else
191 {
192 const Ascbyte *opname = opcode_name_table[op];
193 if (!opname)
194 {
195 stderr_out ("Internal error! NULL pointer in opcode_name_table, opcode %d\n", op);
196 strcat (msg, "NULL");
197 }
198 else
199 strcat (msg, opname);
200 }
201 sprintf (msg2, " (%d)\n", op);
202 strcat (msg, msg2);
203 }
204
205 assert_failed (file, line, msg);
206 }
207
208 #endif /* ERROR_CHECK_BYTE_CODE */
266 209
267 210
268 #ifdef BYTE_CODE_METER 211 #ifdef BYTE_CODE_METER
269 212
270 Lisp_Object Vbyte_code_meter, Qbyte_code_meter; 213 Lisp_Object Vbyte_code_meter, Qbyte_code_meter;
327 } 270 }
328 271
329 272
330 /* We have our own two-argument versions of various arithmetic ops. 273 /* We have our own two-argument versions of various arithmetic ops.
331 Only two-argument arithmetic operations have their own byte codes. */ 274 Only two-argument arithmetic operations have their own byte codes. */
332 static int 275 int
333 bytecode_arithcompare (Lisp_Object obj1, Lisp_Object obj2) 276 bytecode_arithcompare (Lisp_Object obj1, Lisp_Object obj2)
334 { 277 {
335 #ifdef WITH_NUMBER_TYPES 278 #ifdef WITH_NUMBER_TYPES
336 switch (promote_args (&obj1, &obj2)) 279 switch (promote_args (&obj1, &obj2))
337 { 280 {
616 } 559 }
617 #endif /* WITH_NUMBER_TYPES */ 560 #endif /* WITH_NUMBER_TYPES */
618 } 561 }
619 562
620 563
564
565 /*********************** The instruction array *********************/
566
567 /* Check that there are at least LEN elements left in the end of the
568 instruction array before fetching them. Note that we allow for
569 PROGRAM_PTR == PROGRAM_END after the fetch -- that means there are
570 no more elements to fetch next time around, but we might exit before
571 next time comes.
572
573 When checking the destination if jumps, however, we don't allow
574 PROGRAM_PTR to equal PROGRAM_END, since we will always be fetching
575 another instruction after the jump. */
576
577 #define CHECK_OPCODE_SPACE(len) \
578 bytecode_assert (program_ptr + len <= program_end)
579
621 /* Read next uint8 from the instruction stream. */ 580 /* Read next uint8 from the instruction stream. */
622 #define READ_UINT_1 ((unsigned int) (unsigned char) *program_ptr++) 581 #define READ_UINT_1 \
582 (CHECK_OPCODE_SPACE (1), (unsigned int) (unsigned char) *program_ptr++)
623 583
624 /* Read next uint16 from the instruction stream. */ 584 /* Read next uint16 from the instruction stream. */
625 #define READ_UINT_2 \ 585 #define READ_UINT_2 \
626 (program_ptr += 2, \ 586 (CHECK_OPCODE_SPACE (2), \
587 program_ptr += 2, \
627 (((unsigned int) (unsigned char) program_ptr[-1]) * 256 + \ 588 (((unsigned int) (unsigned char) program_ptr[-1]) * 256 + \
628 ((unsigned int) (unsigned char) program_ptr[-2]))) 589 ((unsigned int) (unsigned char) program_ptr[-2])))
629 590
630 /* Read next int8 from the instruction stream. */ 591 /* Read next int8 from the instruction stream. */
631 #define READ_INT_1 ((int) (signed char) *program_ptr++) 592 #define READ_INT_1 \
593 (CHECK_OPCODE_SPACE (1), (int) (signed char) *program_ptr++)
632 594
633 /* Read next int16 from the instruction stream. */ 595 /* Read next int16 from the instruction stream. */
634 #define READ_INT_2 \ 596 #define READ_INT_2 \
635 (program_ptr += 2, \ 597 (CHECK_OPCODE_SPACE (2), \
598 program_ptr += 2, \
636 (((int) ( signed char) program_ptr[-1]) * 256 + \ 599 (((int) ( signed char) program_ptr[-1]) * 256 + \
637 ((int) (unsigned char) program_ptr[-2]))) 600 ((int) (unsigned char) program_ptr[-2])))
638 601
639 /* Read next int8 from instruction stream; don't advance program_pointer */ 602 /* Read next int8 from instruction stream; don't advance program_pointer */
640 #define PEEK_INT_1 ((int) (signed char) program_ptr[0]) 603 #define PEEK_INT_1 \
604 (CHECK_OPCODE_SPACE (1), (int) (signed char) program_ptr[0])
641 605
642 /* Read next int16 from instruction stream; don't advance program_pointer */ 606 /* Read next int16 from instruction stream; don't advance program_pointer */
643 #define PEEK_INT_2 \ 607 #define PEEK_INT_2 \
644 ((((int) ( signed char) program_ptr[1]) * 256) | \ 608 (CHECK_OPCODE_SPACE (2), \
609 (((int) ( signed char) program_ptr[1]) * 256) | \
645 ((int) (unsigned char) program_ptr[0])) 610 ((int) (unsigned char) program_ptr[0]))
646 611
647 /* Do relative jumps from the current location. 612 /* Do relative jumps from the current location.
648 We only do a QUIT if we jump backwards, for efficiency. 613 We only do a QUIT if we jump backwards, for efficiency.
649 No infloops without backward jumps! */ 614 No infloops without backward jumps! */
650 #define JUMP_RELATIVE(jump) do { \ 615 #define JUMP_RELATIVE(jump) do { \
651 int JR_jump = (jump); \ 616 int _JR_jump = (jump); \
652 if (JR_jump < 0) QUIT; \ 617 if (_JR_jump < 0) QUIT; \
653 program_ptr += JR_jump; \ 618 /* Check that where we're going to is in range. Note that we don't use \
619 CHECK_OPCODE_SPACE() -- that only checks the end, and it allows \
620 program_ptr == program_end, which we don't allow. */ \
621 bytecode_assert (program_ptr + _JR_jump >= program && \
622 program_ptr + _JR_jump < program_end); \
623 program_ptr += _JR_jump; \
654 } while (0) 624 } while (0)
655 625
656 #define JUMP JUMP_RELATIVE (PEEK_INT_2) 626 #define JUMP JUMP_RELATIVE (PEEK_INT_2)
657 #define JUMPR JUMP_RELATIVE (PEEK_INT_1) 627 #define JUMPR JUMP_RELATIVE (PEEK_INT_1)
658 628
659 #define JUMP_NEXT ((void) (program_ptr += 2)) 629 #define JUMP_NEXT (CHECK_OPCODE_SPACE (2), (void) (program_ptr += 2))
660 #define JUMPR_NEXT ((void) (program_ptr += 1)) 630 #define JUMPR_NEXT (CHECK_OPCODE_SPACE (1), (void) (program_ptr += 1))
631
632 /*********************** The stack array *********************/
633
634 /* NOTE: The stack array doesn't work quite like you'd expect.
635
636 STACK_PTR points to the value on the top of the stack. Popping a value
637 fetches the value from the STACK_PTR and then decrements it. Pushing a
638 value first increments it, then writes the new value. STACK_PTR -
639 STACK_BEG is the number of elements on the stack.
640
641 This means that when STACK_PTR == STACK_BEG, the stack is empty, and
642 the space at STACK_BEG is never written to -- the first push will write
643 into the space directly after STACK_BEG. This is why the call to
644 alloca_array() below has a count of `stack_depth + 1', and why
645 we GCPRO1 (stack_ptr[1]) -- the value at stack_ptr[0] is unused and
646 uninitialized.
647
648 Also, STACK_END actually points to the last usable storage location,
649 and does not point past the end, like you'd expect. */
650
651 #define CHECK_STACKPTR_OFFSET(len) \
652 bytecode_assert (stack_ptr + (len) >= stack_beg && \
653 stack_ptr + (len) <= stack_end)
661 654
662 /* Push x onto the execution stack. */ 655 /* Push x onto the execution stack. */
663 #define PUSH(x) (*++stack_ptr = (x)) 656 #define PUSH(x) (CHECK_STACKPTR_OFFSET (1), *++stack_ptr = (x))
664 657
665 /* Pop a value, which may be multiple, off the execution stack. */ 658 /* Pop a value, which may be multiple, off the execution stack. */
666 #define POP_WITH_MULTIPLE_VALUES (*stack_ptr--) 659 #define POP_WITH_MULTIPLE_VALUES (CHECK_STACKPTR_OFFSET (-1), *stack_ptr--)
667 660
668 /* Pop a value off the execution stack, treating multiple values as single. */ 661 /* Pop a value off the execution stack, treating multiple values as single. */
669 #define POP (IGNORE_MULTIPLE_VALUES (POP_WITH_MULTIPLE_VALUES)) 662 #define POP (IGNORE_MULTIPLE_VALUES (POP_WITH_MULTIPLE_VALUES))
670 663
671 #define DISCARD_PRESERVING_MULTIPLE_VALUES(n) (stack_ptr -= (n)) 664 /* ..._UNSAFE() means it evaluates its argument more than once. */
665 #define DISCARD_PRESERVING_MULTIPLE_VALUES_UNSAFE(n) \
666 (CHECK_STACKPTR_OFFSET (-(n)), stack_ptr -= (n))
672 667
673 /* Discard n values from the execution stack. */ 668 /* Discard n values from the execution stack. */
674 #define DISCARD(n) do { \ 669 #define DISCARD(n) do { \
670 int _discard_n = (n); \
675 if (1 != multiple_value_current_limit) \ 671 if (1 != multiple_value_current_limit) \
676 { \ 672 { \
677 int i, en = n; \ 673 int i; \
678 for (i = 0; i < en; i++) \ 674 for (i = 0; i < _discard_n; i++) \
679 { \ 675 { \
676 CHECK_STACKPTR_OFFSET (-1); \
680 *stack_ptr = ignore_multiple_values (*stack_ptr); \ 677 *stack_ptr = ignore_multiple_values (*stack_ptr); \
681 stack_ptr--; \ 678 stack_ptr--; \
682 } \ 679 } \
683 } \ 680 } \
684 else \ 681 else \
685 { \ 682 { \
686 stack_ptr -= (n); \ 683 CHECK_STACKPTR_OFFSET (-_discard_n); \
684 stack_ptr -= _discard_n; \
687 } \ 685 } \
688 } while (0) 686 } while (0)
689 687
690 /* Get the value, which may be multiple, at the top of the execution stack; 688 /* Get the value, which may be multiple, at the top of the execution stack;
691 and leave it there. */ 689 and leave it there. */
701 699
702 700
703 701
704 /* See comment before the big switch in execute_optimized_program(). */ 702 /* See comment before the big switch in execute_optimized_program(). */
705 #define GCPRO_STACK (gcpro1.nvars = stack_ptr - stack_beg) 703 #define GCPRO_STACK (gcpro1.nvars = stack_ptr - stack_beg)
704
706 705
707 /* The actual interpreter for byte code. 706 /* The actual interpreter for byte code.
708 This function has been seriously optimized for performance. 707 This function has been seriously optimized for performance.
709 Don't change the constructs unless you are willing to do 708 Don't change the constructs unless you are willing to do
710 real benchmarking and profiling work -- martin */ 709 real benchmarking and profiling work -- martin */
711 710
712 711
713 Lisp_Object 712 Lisp_Object
714 execute_optimized_program (const Opbyte *program, 713 execute_optimized_program (const Opbyte *program,
714 #ifdef ERROR_CHECK_BYTE_CODE
715 Elemcount program_length,
716 #endif
715 int stack_depth, 717 int stack_depth,
716 Lisp_Object *constants_data) 718 Lisp_Object *constants_data)
717 { 719 {
718 /* This function can GC */ 720 /* This function can GC */
719 REGISTER const Opbyte *program_ptr = (Opbyte *) program; 721 REGISTER const Opbyte *program_ptr = (Opbyte *) program;
722 #ifdef ERROR_CHECK_BYTE_CODE
723 const Opbyte *program_end = program_ptr + program_length;
724 #endif
725 /* See comment above explaining the `+ 1' */
720 Lisp_Object *stack_beg = alloca_array (Lisp_Object, stack_depth + 1); 726 Lisp_Object *stack_beg = alloca_array (Lisp_Object, stack_depth + 1);
721 REGISTER Lisp_Object *stack_ptr = stack_beg; 727 REGISTER Lisp_Object *stack_ptr = stack_beg;
722 int speccount = specpdl_depth (); 728 int speccount = specpdl_depth ();
723 struct gcpro gcpro1; 729 struct gcpro gcpro1;
724 730
725 #ifdef BYTE_CODE_METER 731 #ifdef BYTE_CODE_METER
726 Opcode this_opcode = 0; 732 Opcode this_opcode = (Opcode) 0;
727 Opcode prev_opcode; 733 Opcode prev_opcode;
728 #endif 734 #endif
729 735
730 #ifdef ERROR_CHECK_BYTE_CODE 736 #ifdef ERROR_CHECK_BYTE_CODE
731 Lisp_Object *stack_end = stack_beg + stack_depth; 737 Lisp_Object *stack_end = stack_beg + stack_depth;
756 loses its reference and is effectively UNGCPROed, and the new object is 762 loses its reference and is effectively UNGCPROed, and the new object is
757 automatically GCPROed as long as nvars is correct. Only when we 763 automatically GCPROed as long as nvars is correct. Only when we
758 return from the interpreter do we need to finalize the struct gcpro 764 return from the interpreter do we need to finalize the struct gcpro
759 itself, and that's done at case Breturn. 765 itself, and that's done at case Breturn.
760 */ 766 */
767
768 /* See comment above explaining the `[1]' */
761 GCPRO1 (stack_ptr[1]); 769 GCPRO1 (stack_ptr[1]);
762 770
763 while (1) 771 while (1)
764 { 772 {
765 REGISTER Opcode opcode = (Opcode) READ_UINT_1; 773 REGISTER Opcode opcode = (Opcode) READ_UINT_1;
766 774
775 #ifdef ERROR_CHECK_BYTE_CODE
776 remember_operation (opcode);
777 #endif
778
767 GCPRO_STACK; /* Get nvars right before maybe signaling. */ 779 GCPRO_STACK; /* Get nvars right before maybe signaling. */
780 /* #### NOTE: This code should probably never get triggered, since we
781 now catch the problems earlier, farther down, before we ever set
782 a bad value for STACK_PTR. */
768 #ifdef ERROR_CHECK_BYTE_CODE 783 #ifdef ERROR_CHECK_BYTE_CODE
769 if (stack_ptr > stack_end) 784 if (stack_ptr > stack_end)
770 stack_overflow ("byte code stack overflow", Qunbound); 785 stack_overflow ("byte code stack overflow", Qunbound);
771 if (stack_ptr < stack_beg) 786 if (stack_ptr < stack_beg)
772 stack_overflow ("byte code stack underflow", Qunbound); 787 stack_overflow ("byte code stack underflow", Qunbound);
787 PUSH (constants_data[opcode - Bconstant]); 802 PUSH (constants_data[opcode - Bconstant]);
788 else 803 else
789 { 804 {
790 /* We're not sure what these do, so better safe than sorry. */ 805 /* We're not sure what these do, so better safe than sorry. */
791 /* GCPRO_STACK; */ 806 /* GCPRO_STACK; */
792 stack_ptr = execute_rare_opcode (stack_ptr, program_ptr, opcode); 807 stack_ptr = execute_rare_opcode (stack_ptr,
808 #ifdef ERROR_CHECK_BYTE_CODE
809 stack_beg,
810 stack_end,
811 #endif /* ERROR_CHECK_BYTE_CODE */
812 program_ptr, opcode);
813 CHECK_STACKPTR_OFFSET (0);
793 } 814 }
794 break; 815 break;
795 816
796 case Bvarref: 817 case Bvarref:
797 case Bvarref+1: 818 case Bvarref+1:
1073 #else 1094 #else
1074 TOP_LVALUE = INT_OR_FLOATP (TOP) ? Qt : Qnil; 1095 TOP_LVALUE = INT_OR_FLOATP (TOP) ? Qt : Qnil;
1075 #endif 1096 #endif
1076 break; 1097 break;
1077 1098
1078 case Bintegerp: 1099 case Bfixnump:
1079 #ifdef HAVE_BIGNUM
1080 TOP_LVALUE = INTEGERP (TOP) ? Qt : Qnil;
1081 #else
1082 TOP_LVALUE = INTP (TOP) ? Qt : Qnil; 1100 TOP_LVALUE = INTP (TOP) ? Qt : Qnil;
1083 #endif
1084 break; 1101 break;
1085 1102
1086 case Beq: 1103 case Beq:
1087 { 1104 {
1088 Lisp_Object arg = POP; 1105 Lisp_Object arg = POP;
1439 rarely executed code, to minimize cache misses. 1456 rarely executed code, to minimize cache misses.
1440 1457
1441 Don't make this function static, since then the compiler might inline it. */ 1458 Don't make this function static, since then the compiler might inline it. */
1442 Lisp_Object * 1459 Lisp_Object *
1443 execute_rare_opcode (Lisp_Object *stack_ptr, 1460 execute_rare_opcode (Lisp_Object *stack_ptr,
1461 #ifdef ERROR_CHECK_BYTE_CODE
1462 Lisp_Object *stack_beg,
1463 Lisp_Object *stack_end,
1464 #endif /* ERROR_CHECK_BYTE_CODE */
1444 const Opbyte *UNUSED (program_ptr), 1465 const Opbyte *UNUSED (program_ptr),
1445 Opcode opcode) 1466 Opcode opcode)
1446 { 1467 {
1447 REGISTER int n; 1468 REGISTER int n;
1448 1469
1449 switch (opcode) 1470 switch (opcode)
1450 { 1471 {
1451 1472
1452 case Bsave_excursion: 1473 case Bsave_excursion:
1453 record_unwind_protect (save_excursion_restore, 1474 record_unwind_protect (save_excursion_restore,
1454 save_excursion_save ()); 1475 save_excursion_save ());
1455 break; 1476 break;
1456 1477
1715 } 1736 }
1716 1737
1717 case Bmultiple_value_call: 1738 case Bmultiple_value_call:
1718 { 1739 {
1719 n = XINT (POP); 1740 n = XINT (POP);
1720 DISCARD_PRESERVING_MULTIPLE_VALUES (n - 1); 1741 DISCARD_PRESERVING_MULTIPLE_VALUES_UNSAFE (n - 1);
1721 /* Discard multiple values for the first (function) argument: */ 1742 /* Discard multiple values for the first (function) argument: */
1722 TOP_LVALUE = TOP; 1743 TOP_LVALUE = TOP;
1723 TOP_LVALUE = multiple_value_call (n, TOP_ADDRESS); 1744 TOP_LVALUE = multiple_value_call (n, TOP_ADDRESS);
1724 break; 1745 break;
1725 } 1746 }
1726 1747
1727 case Bmultiple_value_list_internal: 1748 case Bmultiple_value_list_internal:
1728 { 1749 {
1729 DISCARD_PRESERVING_MULTIPLE_VALUES (3); 1750 DISCARD_PRESERVING_MULTIPLE_VALUES_UNSAFE (3);
1730 TOP_LVALUE = multiple_value_list_internal (4, TOP_ADDRESS); 1751 TOP_LVALUE = multiple_value_list_internal (4, TOP_ADDRESS);
1731 break; 1752 break;
1732 } 1753 }
1733 1754
1734 case Bthrow: 1755 case Bthrow:
1739 throw_or_bomb_out (TOP, arg, 0, Qnil, Qnil); 1760 throw_or_bomb_out (TOP, arg, 0, Qnil, Qnil);
1740 break; 1761 break;
1741 } 1762 }
1742 1763
1743 default: 1764 default:
1744 ABORT(); 1765 {
1766 Ascbyte msg[100];
1767 sprintf (msg, "Unknown opcode %d", opcode);
1768 bytecode_abort_with_message (msg);
1769 }
1745 break; 1770 break;
1746 } 1771 }
1747 return stack_ptr; 1772 return stack_ptr;
1748 } 1773 }
1749 1774
1750 1775
1751 DOESNT_RETURN 1776 DOESNT_RETURN
1752 invalid_byte_code (const CIbyte *reason, Lisp_Object frob) 1777 invalid_byte_code (const Ascbyte *reason, Lisp_Object frob)
1753 { 1778 {
1754 signal_error (Qinvalid_byte_code, reason, frob); 1779 signal_error (Qinvalid_byte_code, reason, frob);
1755 } 1780 }
1756 1781
1757 /* Check for valid opcodes. Change this when adding new opcodes. */ 1782 /* Check for valid opcodes. Change this when adding new opcodes. */
1863 optimize_byte_code (/* in */ 1888 optimize_byte_code (/* in */
1864 Lisp_Object instructions, 1889 Lisp_Object instructions,
1865 Lisp_Object constants, 1890 Lisp_Object constants,
1866 /* out */ 1891 /* out */
1867 Opbyte * const program, 1892 Opbyte * const program,
1868 int * const program_length, 1893 Elemcount * const program_length,
1869 int * const varbind_count) 1894 Elemcount * const varbind_count)
1870 { 1895 {
1871 Bytecount instructions_length = XSTRING_LENGTH (instructions); 1896 Bytecount instructions_length = XSTRING_LENGTH (instructions);
1872 Elemcount comfy_size = (Elemcount) (2 * instructions_length); 1897 Elemcount comfy_size = (Elemcount) (2 * instructions_length);
1873 1898
1874 int * const icounts = alloca_array (int, comfy_size); 1899 int * const icounts = alloca_array (int, comfy_size);
2128 instructions slot of the Compiled_Function object. */ 2153 instructions slot of the Compiled_Function object. */
2129 void 2154 void
2130 optimize_compiled_function (Lisp_Object compiled_function) 2155 optimize_compiled_function (Lisp_Object compiled_function)
2131 { 2156 {
2132 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (compiled_function); 2157 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (compiled_function);
2133 int program_length; 2158 Elemcount program_length;
2134 int varbind_count; 2159 Elemcount varbind_count;
2135 Opbyte *program; 2160 Opbyte *program;
2136 2161
2137 { 2162 {
2138 int minargs = 0, maxargs = 0, totalargs = 0; 2163 int minargs = 0, maxargs = 0, totalargs = 0;
2139 int optional_p = 0, rest_p = 0, i = 0; 2164 int optional_p = 0, rest_p = 0, i = 0;
2219 int docp = f->flags.documentationp; 2244 int docp = f->flags.documentationp;
2220 int intp = f->flags.interactivep; 2245 int intp = f->flags.interactivep;
2221 struct gcpro gcpro1, gcpro2; 2246 struct gcpro gcpro1, gcpro2;
2222 GCPRO2 (obj, printcharfun); 2247 GCPRO2 (obj, printcharfun);
2223 2248
2224 write_c_string (printcharfun, print_readably ? "#[" : "#<compiled-function "); 2249 write_ascstring (printcharfun, print_readably ? "#[" : "#<compiled-function ");
2225 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 2250 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
2226 if (!print_readably) 2251 if (!print_readably)
2227 { 2252 {
2228 Lisp_Object ann = compiled_function_annotation (f); 2253 Lisp_Object ann = compiled_function_annotation (f);
2229 if (!NILP (ann)) 2254 if (!NILP (ann))
2232 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ 2257 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */
2233 /* COMPILED_ARGLIST = 0 */ 2258 /* COMPILED_ARGLIST = 0 */
2234 print_internal (compiled_function_arglist (f), printcharfun, escapeflag); 2259 print_internal (compiled_function_arglist (f), printcharfun, escapeflag);
2235 2260
2236 /* COMPILED_INSTRUCTIONS = 1 */ 2261 /* COMPILED_INSTRUCTIONS = 1 */
2237 write_c_string (printcharfun, " "); 2262 write_ascstring (printcharfun, " ");
2238 { 2263 {
2239 struct gcpro ngcpro1; 2264 struct gcpro ngcpro1;
2240 Lisp_Object instructions = compiled_function_instructions (f); 2265 Lisp_Object instructions = compiled_function_instructions (f);
2241 NGCPRO1 (instructions); 2266 NGCPRO1 (instructions);
2242 if (STRINGP (instructions) && !print_readably) 2267 if (STRINGP (instructions) && !print_readably)
2249 print_internal (instructions, printcharfun, escapeflag); 2274 print_internal (instructions, printcharfun, escapeflag);
2250 NUNGCPRO; 2275 NUNGCPRO;
2251 } 2276 }
2252 2277
2253 /* COMPILED_CONSTANTS = 2 */ 2278 /* COMPILED_CONSTANTS = 2 */
2254 write_c_string (printcharfun, " "); 2279 write_ascstring (printcharfun, " ");
2255 print_internal (compiled_function_constants (f), printcharfun, escapeflag); 2280 print_internal (compiled_function_constants (f), printcharfun, escapeflag);
2256 2281
2257 /* COMPILED_STACK_DEPTH = 3 */ 2282 /* COMPILED_STACK_DEPTH = 3 */
2258 write_fmt_string (printcharfun, " %d", compiled_function_stack_depth (f)); 2283 write_fmt_string (printcharfun, " %d", compiled_function_stack_depth (f));
2259 2284
2260 /* COMPILED_DOC_STRING = 4 */ 2285 /* COMPILED_DOC_STRING = 4 */
2261 if (docp || intp) 2286 if (docp || intp)
2262 { 2287 {
2263 write_c_string (printcharfun, " "); 2288 write_ascstring (printcharfun, " ");
2264 print_internal (compiled_function_documentation (f), printcharfun, 2289 print_internal (compiled_function_documentation (f), printcharfun,
2265 escapeflag); 2290 escapeflag);
2266 } 2291 }
2267 2292
2268 /* COMPILED_INTERACTIVE = 5 */ 2293 /* COMPILED_INTERACTIVE = 5 */
2269 if (intp) 2294 if (intp)
2270 { 2295 {
2271 write_c_string (printcharfun, " "); 2296 write_ascstring (printcharfun, " ");
2272 print_internal (compiled_function_interactive (f), printcharfun, 2297 print_internal (compiled_function_interactive (f), printcharfun,
2273 escapeflag); 2298 escapeflag);
2274 } 2299 }
2275 2300
2276 UNGCPRO; 2301 UNGCPRO;
2277 write_c_string (printcharfun, print_readably ? "]" : ">"); 2302 write_ascstring (printcharfun, print_readably ? "]" : ">");
2278 } 2303 }
2279 2304
2280 2305
2281 static Lisp_Object 2306 static Lisp_Object
2282 mark_compiled_function (Lisp_Object obj) 2307 mark_compiled_function (Lisp_Object obj)
2300 /* tail-recurse on constants */ 2325 /* tail-recurse on constants */
2301 return f->constants; 2326 return f->constants;
2302 } 2327 }
2303 2328
2304 static int 2329 static int
2305 compiled_function_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 2330 compiled_function_equal (Lisp_Object obj1, Lisp_Object obj2, int depth,
2331 int UNUSED (foldcase))
2306 { 2332 {
2307 Lisp_Compiled_Function *f1 = XCOMPILED_FUNCTION (obj1); 2333 Lisp_Compiled_Function *f1 = XCOMPILED_FUNCTION (obj1);
2308 Lisp_Compiled_Function *f2 = XCOMPILED_FUNCTION (obj2); 2334 Lisp_Compiled_Function *f2 = XCOMPILED_FUNCTION (obj2);
2309 return 2335 return
2310 (f1->flags.documentationp == f2->flags.documentationp && 2336 (f1->flags.documentationp == f2->flags.documentationp &&
2699 If STACK-DEPTH is incorrect, Emacs may crash. 2725 If STACK-DEPTH is incorrect, Emacs may crash.
2700 */ 2726 */
2701 (instructions, constants, stack_depth)) 2727 (instructions, constants, stack_depth))
2702 { 2728 {
2703 /* This function can GC */ 2729 /* This function can GC */
2704 int varbind_count; 2730 Elemcount varbind_count;
2705 int program_length; 2731 Elemcount program_length;
2706 Opbyte *program; 2732 Opbyte *program;
2707 2733
2708 CHECK_STRING (instructions); 2734 CHECK_STRING (instructions);
2709 CHECK_VECTOR (constants); 2735 CHECK_VECTOR (constants);
2710 CHECK_NATNUM (stack_depth); 2736 CHECK_NATNUM (stack_depth);
2715 program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (instructions)); 2741 program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (instructions));
2716 optimize_byte_code (instructions, constants, program, 2742 optimize_byte_code (instructions, constants, program,
2717 &program_length, &varbind_count); 2743 &program_length, &varbind_count);
2718 SPECPDL_RESERVE (varbind_count); 2744 SPECPDL_RESERVE (varbind_count);
2719 return execute_optimized_program (program, 2745 return execute_optimized_program (program,
2746 #ifdef ERROR_CHECK_BYTE_CODE
2747 program_length,
2748 #endif
2720 XINT (stack_depth), 2749 XINT (stack_depth),
2721 XVECTOR_DATA (constants)); 2750 XVECTOR_DATA (constants));
2722 } 2751 }
2723 2752
2724 2753
2757 2786
2758 void 2787 void
2759 vars_of_bytecode (void) 2788 vars_of_bytecode (void)
2760 { 2789 {
2761 #ifdef BYTE_CODE_METER 2790 #ifdef BYTE_CODE_METER
2762
2763 DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter /* 2791 DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter /*
2764 A vector of vectors which holds a histogram of byte code usage. 2792 A vector of vectors which holds a histogram of byte code usage.
2765 \(aref (aref byte-code-meter 0) CODE) indicates how many times the byte 2793 \(aref (aref byte-code-meter 0) CODE) indicates how many times the byte
2766 opcode CODE has been executed. 2794 opcode CODE has been executed.
2767 \(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0, 2795 \(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0,
2782 while (i--) 2810 while (i--)
2783 XVECTOR_DATA (Vbyte_code_meter)[i] = make_vector (256, Qzero); 2811 XVECTOR_DATA (Vbyte_code_meter)[i] = make_vector (256, Qzero);
2784 } 2812 }
2785 #endif /* BYTE_CODE_METER */ 2813 #endif /* BYTE_CODE_METER */
2786 } 2814 }
2815
2816 #ifdef ERROR_CHECK_BYTE_CODE
2817
2818 /* Initialize the opcodes in the table that correspond to a base opcode
2819 plus an offset (except for Bconstant). */
2820
2821 static void
2822 init_opcode_table_multi_op (Opcode op)
2823 {
2824 const Ascbyte *basename = opcode_name_table[op];
2825 Ascbyte temp[300];
2826 int i;
2827
2828 for (i = 1; i < 7; i++)
2829 {
2830 assert (!opcode_name_table[op + i]);
2831 sprintf (temp, "%s+%d", basename, i);
2832 opcode_name_table[op + i] = xstrdup (temp);
2833 }
2834 }
2835
2836 #endif /* ERROR_CHECK_BYTE_CODE */
2837
2838 void
2839 reinit_vars_of_bytecode (void)
2840 {
2841 #ifdef ERROR_CHECK_BYTE_CODE
2842 int i;
2843
2844 #define OPCODE(sym, val) opcode_name_table[val] = xstrdup (#sym);
2845 #include "bytecode-ops.h"
2846
2847 for (i = 0; i < countof (opcode_name_table); i++)
2848 {
2849 int j;
2850 Ascbyte *name = opcode_name_table[i];
2851 if (name)
2852 {
2853 Bytecount len = strlen (name);
2854 /* Prettify the name by converting underscores to hyphens, similar
2855 to what happens with DEFSYMBOL. */
2856 for (j = 0; j < len; j++)
2857 if (name[j] == '_')
2858 name[j] = '-';
2859 }
2860 }
2861
2862 init_opcode_table_multi_op (Bvarref);
2863 init_opcode_table_multi_op (Bvarset);
2864 init_opcode_table_multi_op (Bvarbind);
2865 init_opcode_table_multi_op (Bcall);
2866 init_opcode_table_multi_op (Bunbind);
2867 #endif /* ERROR_CHECK_BYTE_CODE */
2868 }