comparison src/bytecode.c @ 412:697ef44129c6 r21-2-14

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