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 } |
