Mercurial > hg > xemacs-beta
comparison src/bytecode.c @ 398:74fd4e045ea6 r21-2-29
Import from CVS: tag r21-2-29
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:13:30 +0200 |
parents | aabb7f5b1c81 |
children | a86b2b5e0111 |
comparison
equal
deleted
inserted
replaced
397:f4aeb21a5bad | 398:74fd4e045ea6 |
---|---|
26 | 26 |
27 /* Authorship: | 27 /* Authorship: |
28 | 28 |
29 FSF: long ago. | 29 FSF: long ago. |
30 | 30 |
31 hacked on by jwz@netscape.com 1991-06 | 31 hacked on by jwz@jwz.org 1991-06 |
32 o added a compile-time switch to turn on simple sanity checking; | 32 o added a compile-time switch to turn on simple sanity checking; |
33 o put back the obsolete byte-codes for error-detection; | 33 o put back the obsolete byte-codes for error-detection; |
34 o added a new instruction, unbind_all, which I will use for | 34 o added a new instruction, unbind_all, which I will use for |
35 tail-recursion elimination; | 35 tail-recursion elimination; |
36 o made temp_output_buffer_show be called with the right number | 36 o made temp_output_buffer_show be called with the right number |
54 #include "buffer.h" | 54 #include "buffer.h" |
55 #include "bytecode.h" | 55 #include "bytecode.h" |
56 #include "opaque.h" | 56 #include "opaque.h" |
57 #include "syntax.h" | 57 #include "syntax.h" |
58 | 58 |
59 #include <stddef.h> | |
60 #include <limits.h> | 59 #include <limits.h> |
61 | 60 |
62 EXFUN (Ffetch_bytecode, 1); | 61 EXFUN (Ffetch_bytecode, 1); |
63 | 62 |
64 Lisp_Object Qbyte_code, Qcompiled_functionp, Qinvalid_byte_code; | 63 Lisp_Object Qbyte_code, Qcompiled_functionp, Qinvalid_byte_code; |
215 | 214 |
216 | 215 |
217 static void invalid_byte_code_error (char *error_message, ...); | 216 static void invalid_byte_code_error (char *error_message, ...); |
218 | 217 |
219 Lisp_Object * execute_rare_opcode (Lisp_Object *stack_ptr, | 218 Lisp_Object * execute_rare_opcode (Lisp_Object *stack_ptr, |
220 CONST Opbyte *program_ptr, | 219 const Opbyte *program_ptr, |
221 Opcode opcode); | 220 Opcode opcode); |
222 | 221 |
223 static Lisp_Object execute_optimized_program (CONST Opbyte *program, | 222 static Lisp_Object execute_optimized_program (const Opbyte *program, |
224 int stack_depth, | 223 int stack_depth, |
225 Lisp_Object *constants_data); | 224 Lisp_Object *constants_data); |
226 | 225 |
227 extern Lisp_Object Qand_rest, Qand_optional; | 226 extern Lisp_Object Qand_rest, Qand_optional; |
228 | |
229 /* Define ERROR_CHECK_BYTE_CODE to enable some minor sanity checking. | |
230 Useful for debugging the byte compiler. */ | |
231 #ifdef DEBUG_XEMACS | |
232 #define ERROR_CHECK_BYTE_CODE | |
233 #endif | |
234 | 227 |
235 /* Define BYTE_CODE_METER to enable generation of a byte-op usage histogram. | 228 /* Define BYTE_CODE_METER to enable generation of a byte-op usage histogram. |
236 This isn't defined in FSF Emacs and isn't defined in XEmacs v19. */ | 229 This isn't defined in FSF Emacs and isn't defined in XEmacs v19. */ |
237 /* #define BYTE_CODE_METER */ | 230 /* #define BYTE_CODE_METER */ |
238 | 231 |
240 #ifdef BYTE_CODE_METER | 233 #ifdef BYTE_CODE_METER |
241 | 234 |
242 Lisp_Object Vbyte_code_meter, Qbyte_code_meter; | 235 Lisp_Object Vbyte_code_meter, Qbyte_code_meter; |
243 int byte_metering_on; | 236 int byte_metering_on; |
244 | 237 |
245 #define METER_2(code1, code2) \ | 238 static void |
246 XINT (XVECTOR_DATA (XVECTOR_DATA (Vbyte_code_meter)[(code1)])[(code2)]) | 239 meter_code (Opcode prev_opcode, Opcode this_opcode) |
247 | 240 { |
248 #define METER_1(code) METER_2 (0, (code)) | 241 if (byte_metering_on) |
249 | 242 { |
250 #define METER_CODE(last_code, this_code) do { \ | 243 Lisp_Object *p = XVECTOR_DATA (XVECTOR_DATA (Vbyte_code_meter)[this_opcode]); |
251 if (byte_metering_on) \ | 244 p[0] = INT_PLUS1 (p[0]); |
252 { \ | 245 if (prev_opcode) |
253 if (METER_1 (this_code) != ((1<<VALBITS)-1)) \ | 246 p[prev_opcode] = INT_PLUS1 (p[prev_opcode]); |
254 METER_1 (this_code)++; \ | 247 } |
255 if (last_code \ | 248 } |
256 && METER_2 (last_code, this_code) != ((1<<VALBITS)-1)) \ | |
257 METER_2 (last_code, this_code)++; \ | |
258 } \ | |
259 } while (0) | |
260 | 249 |
261 #endif /* BYTE_CODE_METER */ | 250 #endif /* BYTE_CODE_METER */ |
262 | 251 |
263 | 252 |
264 static Lisp_Object | 253 static Lisp_Object |
265 bytecode_negate (Lisp_Object obj) | 254 bytecode_negate (Lisp_Object obj) |
266 { | 255 { |
267 retry: | 256 retry: |
268 | 257 |
258 if (INTP (obj)) return make_int (- XINT (obj)); | |
269 #ifdef LISP_FLOAT_TYPE | 259 #ifdef LISP_FLOAT_TYPE |
270 if (FLOATP (obj)) return make_float (- XFLOAT_DATA (obj)); | 260 if (FLOATP (obj)) return make_float (- XFLOAT_DATA (obj)); |
271 #endif | 261 #endif |
272 if (CHARP (obj)) return make_int (- ((int) XCHAR (obj))); | 262 if (CHARP (obj)) return make_int (- ((int) XCHAR (obj))); |
273 if (MARKERP (obj)) return make_int (- ((int) marker_position (obj))); | 263 if (MARKERP (obj)) return make_int (- ((int) marker_position (obj))); |
274 if (INTP (obj)) return make_int (- XINT (obj)); | |
275 | 264 |
276 obj = wrong_type_argument (Qnumber_char_or_marker_p, obj); | 265 obj = wrong_type_argument (Qnumber_char_or_marker_p, obj); |
277 goto retry; | 266 goto retry; |
278 } | 267 } |
279 | 268 |
303 { | 292 { |
304 retry: | 293 retry: |
305 | 294 |
306 #ifdef LISP_FLOAT_TYPE | 295 #ifdef LISP_FLOAT_TYPE |
307 { | 296 { |
308 int ival1, ival2; | 297 EMACS_INT ival1, ival2; |
309 | 298 |
310 if (INTP (obj1)) ival1 = XINT (obj1); | 299 if (INTP (obj1)) ival1 = XINT (obj1); |
311 else if (CHARP (obj1)) ival1 = XCHAR (obj1); | 300 else if (CHARP (obj1)) ival1 = XCHAR (obj1); |
312 else if (MARKERP (obj1)) ival1 = marker_position (obj1); | 301 else if (MARKERP (obj1)) ival1 = marker_position (obj1); |
313 else goto arithcompare_float; | 302 else goto arithcompare_float; |
347 | 336 |
348 return dval1 < dval2 ? -1 : dval1 > dval2 ? 1 : 0; | 337 return dval1 < dval2 ? -1 : dval1 > dval2 ? 1 : 0; |
349 } | 338 } |
350 #else /* !LISP_FLOAT_TYPE */ | 339 #else /* !LISP_FLOAT_TYPE */ |
351 { | 340 { |
352 int ival1, ival2; | 341 EMACS_INT ival1, ival2; |
353 | 342 |
354 if (INTP (obj1)) ival1 = XINT (obj1); | 343 if (INTP (obj1)) ival1 = XINT (obj1); |
355 else if (CHARP (obj1)) ival1 = XCHAR (obj1); | 344 else if (CHARP (obj1)) ival1 = XCHAR (obj1); |
356 else if (MARKERP (obj1)) ival1 = marker_position (obj1); | 345 else if (MARKERP (obj1)) ival1 = marker_position (obj1); |
357 else | 346 else |
376 | 365 |
377 static Lisp_Object | 366 static Lisp_Object |
378 bytecode_arithop (Lisp_Object obj1, Lisp_Object obj2, Opcode opcode) | 367 bytecode_arithop (Lisp_Object obj1, Lisp_Object obj2, Opcode opcode) |
379 { | 368 { |
380 #ifdef LISP_FLOAT_TYPE | 369 #ifdef LISP_FLOAT_TYPE |
381 int ival1, ival2; | 370 EMACS_INT ival1, ival2; |
382 int float_p; | 371 int float_p; |
383 | 372 |
384 retry: | 373 retry: |
385 | 374 |
386 float_p = 0; | 375 float_p = 0; |
438 case Bmin: if (dval1 > dval2) dval1 = dval2; break; | 427 case Bmin: if (dval1 > dval2) dval1 = dval2; break; |
439 } | 428 } |
440 return make_float (dval1); | 429 return make_float (dval1); |
441 } | 430 } |
442 #else /* !LISP_FLOAT_TYPE */ | 431 #else /* !LISP_FLOAT_TYPE */ |
443 int ival1, ival2; | 432 EMACS_INT ival1, ival2; |
444 | 433 |
445 retry: | 434 retry: |
446 | 435 |
447 if (INTP (obj1)) ival1 = XINT (obj1); | 436 if (INTP (obj1)) ival1 = XINT (obj1); |
448 else if (CHARP (obj1)) ival1 = XCHAR (obj1); | 437 else if (CHARP (obj1)) ival1 = XCHAR (obj1); |
536 UNBIND_TO_GCPRO (speccount, value); | 525 UNBIND_TO_GCPRO (speccount, value); |
537 return value; | 526 return value; |
538 } | 527 } |
539 | 528 |
540 wrong_number_of_arguments: | 529 wrong_number_of_arguments: |
530 /* The actual printed compiled_function object is incomprehensible. | |
531 Check the backtrace to see if we can get a more meaningful symbol. */ | |
532 if (EQ (fun, indirect_function (*backtrace_list->function, 0))) | |
533 fun = *backtrace_list->function; | |
541 return Fsignal (Qwrong_number_of_arguments, list2 (fun, make_int (nargs))); | 534 return Fsignal (Qwrong_number_of_arguments, list2 (fun, make_int (nargs))); |
542 } | 535 } |
543 | 536 |
544 | 537 |
545 /* Read next uint8 from the instruction stream. */ | 538 /* Read next uint8 from the instruction stream. */ |
601 Don't change the constructs unless you are willing to do | 594 Don't change the constructs unless you are willing to do |
602 real benchmarking and profiling work -- martin */ | 595 real benchmarking and profiling work -- martin */ |
603 | 596 |
604 | 597 |
605 static Lisp_Object | 598 static Lisp_Object |
606 execute_optimized_program (CONST Opbyte *program, | 599 execute_optimized_program (const Opbyte *program, |
607 int stack_depth, | 600 int stack_depth, |
608 Lisp_Object *constants_data) | 601 Lisp_Object *constants_data) |
609 { | 602 { |
610 /* This function can GC */ | 603 /* This function can GC */ |
611 REGISTER CONST Opbyte *program_ptr = (Opbyte *) program; | 604 REGISTER const Opbyte *program_ptr = (Opbyte *) program; |
612 REGISTER Lisp_Object *stack_ptr | 605 REGISTER Lisp_Object *stack_ptr |
613 = alloca_array (Lisp_Object, stack_depth + 1); | 606 = alloca_array (Lisp_Object, stack_depth + 1); |
614 int speccount = specpdl_depth (); | 607 int speccount = specpdl_depth (); |
615 struct gcpro gcpro1; | 608 struct gcpro gcpro1; |
616 | 609 |
648 #endif | 641 #endif |
649 | 642 |
650 #ifdef BYTE_CODE_METER | 643 #ifdef BYTE_CODE_METER |
651 prev_opcode = this_opcode; | 644 prev_opcode = this_opcode; |
652 this_opcode = opcode; | 645 this_opcode = opcode; |
653 METER_CODE (prev_opcode, this_opcode); | 646 meter_code (prev_opcode, this_opcode); |
654 #endif | 647 #endif |
655 | 648 |
656 switch (opcode) | 649 switch (opcode) |
657 { | 650 { |
658 REGISTER int n; | 651 REGISTER int n; |
691 case Bvarset+7: n = READ_UINT_2; goto do_varset; | 684 case Bvarset+7: n = READ_UINT_2; goto do_varset; |
692 case Bvarset+6: n = READ_UINT_1; /* most common */ | 685 case Bvarset+6: n = READ_UINT_1; /* most common */ |
693 do_varset: | 686 do_varset: |
694 { | 687 { |
695 Lisp_Object symbol = constants_data[n]; | 688 Lisp_Object symbol = constants_data[n]; |
696 struct Lisp_Symbol *symbol_ptr = XSYMBOL (symbol); | 689 Lisp_Symbol *symbol_ptr = XSYMBOL (symbol); |
697 Lisp_Object old_value = symbol_ptr->value; | 690 Lisp_Object old_value = symbol_ptr->value; |
698 Lisp_Object new_value = POP; | 691 Lisp_Object new_value = POP; |
699 if (!SYMBOL_VALUE_MAGIC_P (old_value) || UNBOUNDP (old_value)) | 692 if (!SYMBOL_VALUE_MAGIC_P (old_value) || UNBOUNDP (old_value)) |
700 symbol_ptr->value = new_value; | 693 symbol_ptr->value = new_value; |
701 else | 694 else |
712 case Bvarbind+7: n = READ_UINT_2; goto do_varbind; | 705 case Bvarbind+7: n = READ_UINT_2; goto do_varbind; |
713 case Bvarbind+6: n = READ_UINT_1; /* most common */ | 706 case Bvarbind+6: n = READ_UINT_1; /* most common */ |
714 do_varbind: | 707 do_varbind: |
715 { | 708 { |
716 Lisp_Object symbol = constants_data[n]; | 709 Lisp_Object symbol = constants_data[n]; |
717 struct Lisp_Symbol *symbol_ptr = XSYMBOL (symbol); | 710 Lisp_Symbol *symbol_ptr = XSYMBOL (symbol); |
718 Lisp_Object old_value = symbol_ptr->value; | 711 Lisp_Object old_value = symbol_ptr->value; |
719 Lisp_Object new_value = POP; | 712 Lisp_Object new_value = POP; |
720 if (!SYMBOL_VALUE_MAGIC_P (old_value) || UNBOUNDP (old_value)) | 713 if (!SYMBOL_VALUE_MAGIC_P (old_value) || UNBOUNDP (old_value)) |
721 { | 714 { |
722 specpdl_ptr->symbol = symbol; | 715 specpdl_ptr->symbol = symbol; |
765 UNBIND_TO (specpdl_depth() - | 758 UNBIND_TO (specpdl_depth() - |
766 (opcode < Bunbind+6 ? opcode-Bunbind : | 759 (opcode < Bunbind+6 ? opcode-Bunbind : |
767 opcode == Bunbind+6 ? READ_UINT_1 : READ_UINT_2)); | 760 opcode == Bunbind+6 ? READ_UINT_1 : READ_UINT_2)); |
768 break; | 761 break; |
769 | 762 |
763 | |
770 case Bgoto: | 764 case Bgoto: |
771 JUMP; | 765 JUMP; |
772 break; | 766 break; |
773 | 767 |
774 case Bgotoifnil: | 768 case Bgotoifnil: |
1002 TOP = Fget (TOP, arg, Qnil); | 996 TOP = Fget (TOP, arg, Qnil); |
1003 break; | 997 break; |
1004 } | 998 } |
1005 | 999 |
1006 case Bsub1: | 1000 case Bsub1: |
1007 TOP = INTP (TOP) ? make_int (XINT (TOP) - 1) : Fsub1 (TOP); | 1001 TOP = INTP (TOP) ? INT_MINUS1 (TOP) : Fsub1 (TOP); |
1008 break; | 1002 break; |
1009 | 1003 |
1010 case Badd1: | 1004 case Badd1: |
1011 TOP = INTP (TOP) ? make_int (XINT (TOP) + 1) : Fadd1 (TOP); | 1005 TOP = INTP (TOP) ? INT_PLUS1 (TOP) : Fadd1 (TOP); |
1012 break; | 1006 break; |
1013 | 1007 |
1014 | 1008 |
1015 case Beqlsign: | 1009 case Beqlsign: |
1016 { | 1010 { |
1060 case Bplus: | 1054 case Bplus: |
1061 { | 1055 { |
1062 Lisp_Object arg2 = POP; | 1056 Lisp_Object arg2 = POP; |
1063 Lisp_Object arg1 = TOP; | 1057 Lisp_Object arg1 = TOP; |
1064 TOP = INTP (arg1) && INTP (arg2) ? | 1058 TOP = INTP (arg1) && INTP (arg2) ? |
1065 make_int (XINT (arg1) + XINT (arg2)) : | 1059 INT_PLUS (arg1, arg2) : |
1066 bytecode_arithop (arg1, arg2, opcode); | 1060 bytecode_arithop (arg1, arg2, opcode); |
1067 break; | 1061 break; |
1068 } | 1062 } |
1069 | 1063 |
1070 case Bdiff: | 1064 case Bdiff: |
1071 { | 1065 { |
1072 Lisp_Object arg2 = POP; | 1066 Lisp_Object arg2 = POP; |
1073 Lisp_Object arg1 = TOP; | 1067 Lisp_Object arg1 = TOP; |
1074 TOP = INTP (arg1) && INTP (arg2) ? | 1068 TOP = INTP (arg1) && INTP (arg2) ? |
1075 make_int (XINT (arg1) - XINT (arg2)) : | 1069 INT_MINUS (arg1, arg2) : |
1076 bytecode_arithop (arg1, arg2, opcode); | 1070 bytecode_arithop (arg1, arg2, opcode); |
1077 break; | 1071 break; |
1078 } | 1072 } |
1079 | 1073 |
1080 case Bmult: | 1074 case Bmult: |
1112 { | 1106 { |
1113 Lisp_Object arg = POP; | 1107 Lisp_Object arg = POP; |
1114 TOP = Fmemq (TOP, arg); | 1108 TOP = Fmemq (TOP, arg); |
1115 break; | 1109 break; |
1116 } | 1110 } |
1117 | |
1118 | 1111 |
1119 case Bset: | 1112 case Bset: |
1120 { | 1113 { |
1121 Lisp_Object arg = POP; | 1114 Lisp_Object arg = POP; |
1122 TOP = Fset (TOP, arg); | 1115 TOP = Fset (TOP, arg); |
1226 rarely executed code, to minimize cache misses. | 1219 rarely executed code, to minimize cache misses. |
1227 | 1220 |
1228 Don't make this function static, since then the compiler might inline it. */ | 1221 Don't make this function static, since then the compiler might inline it. */ |
1229 Lisp_Object * | 1222 Lisp_Object * |
1230 execute_rare_opcode (Lisp_Object *stack_ptr, | 1223 execute_rare_opcode (Lisp_Object *stack_ptr, |
1231 CONST Opbyte *program_ptr, | 1224 const Opbyte *program_ptr, |
1232 Opcode opcode) | 1225 Opcode opcode) |
1233 { | 1226 { |
1234 switch (opcode) | 1227 switch (opcode) |
1235 { | 1228 { |
1236 | 1229 |
1496 va_list args; | 1489 va_list args; |
1497 char *buf = alloca_array (char, strlen (error_message) + 128); | 1490 char *buf = alloca_array (char, strlen (error_message) + 128); |
1498 | 1491 |
1499 sprintf (buf, "%s", error_message); | 1492 sprintf (buf, "%s", error_message); |
1500 va_start (args, error_message); | 1493 va_start (args, error_message); |
1501 obj = emacs_doprnt_string_va ((CONST Bufbyte *) GETTEXT (buf), Qnil, -1, | 1494 obj = emacs_doprnt_string_va ((const Bufbyte *) GETTEXT (buf), Qnil, -1, |
1502 args); | 1495 args); |
1503 va_end (args); | 1496 va_end (args); |
1504 | 1497 |
1505 signal_error (Qinvalid_byte_code, list1 (obj)); | 1498 signal_error (Qinvalid_byte_code, list1 (obj)); |
1506 } | 1499 } |
1612 static void | 1605 static void |
1613 optimize_byte_code (/* in */ | 1606 optimize_byte_code (/* in */ |
1614 Lisp_Object instructions, | 1607 Lisp_Object instructions, |
1615 Lisp_Object constants, | 1608 Lisp_Object constants, |
1616 /* out */ | 1609 /* out */ |
1617 Opbyte * CONST program, | 1610 Opbyte * const program, |
1618 int * CONST program_length, | 1611 int * const program_length, |
1619 int * CONST varbind_count) | 1612 int * const varbind_count) |
1620 { | 1613 { |
1621 size_t instructions_length = XSTRING_LENGTH (instructions); | 1614 size_t instructions_length = XSTRING_LENGTH (instructions); |
1622 size_t comfy_size = 2 * instructions_length; | 1615 size_t comfy_size = 2 * instructions_length; |
1623 | 1616 |
1624 int * CONST icounts = alloca_array (int, comfy_size); | 1617 int * const icounts = alloca_array (int, comfy_size); |
1625 int * icounts_ptr = icounts; | 1618 int * icounts_ptr = icounts; |
1626 | 1619 |
1627 /* We maintain a table of jumps in the source code. */ | 1620 /* We maintain a table of jumps in the source code. */ |
1628 struct jump | 1621 struct jump |
1629 { | 1622 { |
1630 int from; | 1623 int from; |
1631 int to; | 1624 int to; |
1632 }; | 1625 }; |
1633 struct jump * CONST jumps = alloca_array (struct jump, comfy_size); | 1626 struct jump * const jumps = alloca_array (struct jump, comfy_size); |
1634 struct jump *jumps_ptr = jumps; | 1627 struct jump *jumps_ptr = jumps; |
1635 | 1628 |
1636 Opbyte *program_ptr = program; | 1629 Opbyte *program_ptr = program; |
1637 | 1630 |
1638 CONST Bufbyte *ptr = XSTRING_DATA (instructions); | 1631 const Bufbyte *ptr = XSTRING_DATA (instructions); |
1639 CONST Bufbyte * CONST end = ptr + instructions_length; | 1632 const Bufbyte * const end = ptr + instructions_length; |
1640 | 1633 |
1641 *varbind_count = 0; | 1634 *varbind_count = 0; |
1642 | 1635 |
1643 while (ptr < end) | 1636 while (ptr < end) |
1644 { | 1637 { |
1899 program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (f->instructions)); | 1892 program = alloca_array (Opbyte, 1 + 2 * XSTRING_LENGTH (f->instructions)); |
1900 optimize_byte_code (f->instructions, f->constants, | 1893 optimize_byte_code (f->instructions, f->constants, |
1901 program, &program_length, &varbind_count); | 1894 program, &program_length, &varbind_count); |
1902 f->specpdl_depth = XINT (Flength (f->arglist)) + varbind_count; | 1895 f->specpdl_depth = XINT (Flength (f->arglist)) + varbind_count; |
1903 f->instructions = | 1896 f->instructions = |
1904 Fpurecopy (make_opaque (program_length * sizeof (Opbyte), | 1897 make_opaque (program, program_length * sizeof (Opbyte)); |
1905 (CONST void *) program)); | |
1906 } | 1898 } |
1907 | 1899 |
1908 assert (OPAQUEP (f->instructions)); | 1900 assert (OPAQUEP (f->instructions)); |
1909 } | 1901 } |
1910 | 1902 |
1986 write_c_string (print_readably ? "]" : ">", printcharfun); | 1978 write_c_string (print_readably ? "]" : ">", printcharfun); |
1987 } | 1979 } |
1988 | 1980 |
1989 | 1981 |
1990 static Lisp_Object | 1982 static Lisp_Object |
1991 mark_compiled_function (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 1983 mark_compiled_function (Lisp_Object obj) |
1992 { | 1984 { |
1993 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (obj); | 1985 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (obj); |
1994 | 1986 |
1995 markobj (f->instructions); | 1987 mark_object (f->instructions); |
1996 markobj (f->arglist); | 1988 mark_object (f->arglist); |
1997 markobj (f->doc_and_interactive); | 1989 mark_object (f->doc_and_interactive); |
1998 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | 1990 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK |
1999 markobj (f->annotated); | 1991 mark_object (f->annotated); |
2000 #endif | 1992 #endif |
2001 /* tail-recurse on constants */ | 1993 /* tail-recurse on constants */ |
2002 return f->constants; | 1994 return f->constants; |
2003 } | 1995 } |
2004 | 1996 |
2028 f->flags.domainp, | 2020 f->flags.domainp, |
2029 internal_hash (f->instructions, depth + 1), | 2021 internal_hash (f->instructions, depth + 1), |
2030 internal_hash (f->constants, depth + 1)); | 2022 internal_hash (f->constants, depth + 1)); |
2031 } | 2023 } |
2032 | 2024 |
2025 static const struct lrecord_description compiled_function_description[] = { | |
2026 { XD_LISP_OBJECT, offsetof (Lisp_Compiled_Function, instructions) }, | |
2027 { XD_LISP_OBJECT, offsetof (Lisp_Compiled_Function, constants) }, | |
2028 { XD_LISP_OBJECT, offsetof (Lisp_Compiled_Function, arglist) }, | |
2029 { XD_LISP_OBJECT, offsetof (Lisp_Compiled_Function, doc_and_interactive) }, | |
2030 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | |
2031 { XD_LISP_OBJECT, offsetof (Lisp_Compiled_Function, annotated) }, | |
2032 #endif | |
2033 { XD_END } | |
2034 }; | |
2035 | |
2033 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("compiled-function", compiled_function, | 2036 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("compiled-function", compiled_function, |
2034 mark_compiled_function, | 2037 mark_compiled_function, |
2035 print_compiled_function, 0, | 2038 print_compiled_function, 0, |
2036 compiled_function_equal, | 2039 compiled_function_equal, |
2037 compiled_function_hash, | 2040 compiled_function_hash, |
2041 compiled_function_description, | |
2038 Lisp_Compiled_Function); | 2042 Lisp_Compiled_Function); |
2039 | 2043 |
2040 DEFUN ("compiled-function-p", Fcompiled_function_p, 1, 1, 0, /* | 2044 DEFUN ("compiled-function-p", Fcompiled_function_p, 1, 1, 0, /* |
2041 Return t if OBJECT is a byte-compiled function object. | 2045 Return t if OBJECT is a byte-compiled function object. |
2042 */ | 2046 */ |
2063 | 2067 |
2064 { | 2068 { |
2065 /* Invert action performed by optimize_byte_code() */ | 2069 /* Invert action performed by optimize_byte_code() */ |
2066 Lisp_Opaque *opaque = XOPAQUE (f->instructions); | 2070 Lisp_Opaque *opaque = XOPAQUE (f->instructions); |
2067 | 2071 |
2068 Bufbyte * CONST buffer = | 2072 Bufbyte * const buffer = |
2069 alloca_array (Bufbyte, OPAQUE_SIZE (opaque) * MAX_EMCHAR_LEN); | 2073 alloca_array (Bufbyte, OPAQUE_SIZE (opaque) * MAX_EMCHAR_LEN); |
2070 Bufbyte *bp = buffer; | 2074 Bufbyte *bp = buffer; |
2071 | 2075 |
2072 CONST Opbyte * CONST program = (CONST Opbyte *) OPAQUE_DATA (opaque); | 2076 const Opbyte * const program = (const Opbyte *) OPAQUE_DATA (opaque); |
2073 CONST Opbyte *program_ptr = program; | 2077 const Opbyte *program_ptr = program; |
2074 CONST Opbyte * CONST program_end = program_ptr + OPAQUE_SIZE (opaque); | 2078 const Opbyte * const program_end = program_ptr + OPAQUE_SIZE (opaque); |
2075 | 2079 |
2076 while (program_ptr < program_end) | 2080 while (program_ptr < program_end) |
2077 { | 2081 { |
2078 Opcode opcode = (Opcode) READ_UINT_1; | 2082 Opcode opcode = (Opcode) READ_UINT_1; |
2079 bp += set_charptr_emchar (bp, opcode); | 2083 bp += set_charptr_emchar (bp, opcode); |
2346 if (!CONSP (tem)) | 2350 if (!CONSP (tem)) |
2347 signal_simple_error ("Invalid lazy-loaded byte code", tem); | 2351 signal_simple_error ("Invalid lazy-loaded byte code", tem); |
2348 /* v18 or v19 bytecode file. Need to Ebolify. */ | 2352 /* v18 or v19 bytecode file. Need to Ebolify. */ |
2349 if (f->flags.ebolified && VECTORP (XCDR (tem))) | 2353 if (f->flags.ebolified && VECTORP (XCDR (tem))) |
2350 ebolify_bytecode_constants (XCDR (tem)); | 2354 ebolify_bytecode_constants (XCDR (tem)); |
2351 /* VERY IMPORTANT to purecopy here!!!!! | 2355 f->instructions = XCAR (tem); |
2352 See load_force_doc_string_unwind. */ | 2356 f->constants = XCDR (tem); |
2353 f->instructions = Fpurecopy (XCAR (tem)); | |
2354 f->constants = Fpurecopy (XCDR (tem)); | |
2355 return function; | 2357 return function; |
2356 } | 2358 } |
2357 abort (); | 2359 abort (); |
2358 return Qnil; /* not reached */ | 2360 return Qnil; /* not reached */ |
2359 } | 2361 } |