Mercurial > hg > xemacs-beta
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 } |