Mercurial > emacs
comparison src/bytecode.c @ 435:43e88c4db330
*** empty log message ***
| author | Richard M. Stallman <rms@gnu.org> |
|---|---|
| date | Tue, 26 Nov 1991 05:00:30 +0000 |
| parents | d0eb77a4d8f7 |
| children | db84d8d9a1d9 |
comparison
equal
deleted
inserted
replaced
| 434:ab8836c672bd | 435:43e88c4db330 |
|---|---|
| 18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
| 19 | 19 |
| 20 hacked on by jwz@lucid.com 17-jun-91 | 20 hacked on by jwz@lucid.com 17-jun-91 |
| 21 o added a compile-time switch to turn on simple sanity checking; | 21 o added a compile-time switch to turn on simple sanity checking; |
| 22 o put back the obsolete byte-codes for error-detection; | 22 o put back the obsolete byte-codes for error-detection; |
| 23 o put back fset, symbol-function, and read-char because I don't | |
| 24 see any reason for them to have been removed; | |
| 25 o added a new instruction, unbind_all, which I will use for | 23 o added a new instruction, unbind_all, which I will use for |
| 26 tail-recursion elimination; | 24 tail-recursion elimination; |
| 27 o made temp_output_buffer_show() be called with the right number | 25 o made temp_output_buffer_show be called with the right number |
| 28 of args; | 26 of args; |
| 29 o made the new bytecodes be called with args in the right order; | 27 o made the new bytecodes be called with args in the right order; |
| 30 o added metering support. | 28 o added metering support. |
| 31 | 29 |
| 32 by Hallvard: | 30 by Hallvard: |
| 33 o added relative jump instructions. | 31 o added relative jump instructions; |
| 34 o all conditionals now only do QUIT if they jump. | 32 o all conditionals now only do QUIT if they jump. |
| 35 */ | 33 */ |
| 36 | |
| 37 | 34 |
| 38 #include "config.h" | 35 #include "config.h" |
| 39 #include "lisp.h" | 36 #include "lisp.h" |
| 40 #include "buffer.h" | 37 #include "buffer.h" |
| 41 #include "syntax.h" | 38 #include "syntax.h" |
| 44 * define BYTE_CODE_SAFE to enable some minor sanity checking (useful for | 41 * define BYTE_CODE_SAFE to enable some minor sanity checking (useful for |
| 45 * debugging the byte compiler...) | 42 * debugging the byte compiler...) |
| 46 * | 43 * |
| 47 * define BYTE_CODE_METER to enable generation of a byte-op usage histogram. | 44 * define BYTE_CODE_METER to enable generation of a byte-op usage histogram. |
| 48 */ | 45 */ |
| 49 #define BYTE_CODE_SAFE | 46 /* #define BYTE_CODE_SAFE */ |
| 50 #define BYTE_CODE_METER | 47 /* #define BYTE_CODE_METER */ |
| 51 | 48 |
| 52 | 49 |
| 53 #ifdef BYTE_CODE_METER | 50 #ifdef BYTE_CODE_METER |
| 54 | 51 |
| 55 Lisp_Object Vbyte_code_meter, Qbyte_code_meter; | 52 Lisp_Object Vbyte_code_meter, Qbyte_code_meter; |
| 56 int byte_metering_on; | 53 int byte_metering_on; |
| 57 | 54 |
| 58 # define METER_2(code1,code2) \ | 55 #define METER_2(code1, code2) \ |
| 59 XFASTINT (XVECTOR (XVECTOR (Vbyte_code_meter)->contents[(code1)]) \ | 56 XFASTINT (XVECTOR (XVECTOR (Vbyte_code_meter)->contents[(code1)]) \ |
| 60 ->contents[(code2)]) | 57 ->contents[(code2)]) |
| 61 | 58 |
| 62 # define METER_1(code) METER_2 (0,(code)) | 59 #define METER_1(code) METER_2 (0, (code)) |
| 63 | 60 |
| 64 # define METER_CODE(last_code, this_code) { \ | 61 #define METER_CODE(last_code, this_code) \ |
| 65 if (byte_metering_on) { \ | 62 { \ |
| 66 if (METER_1 (this_code) != ((1<<VALBITS)-1)) \ | 63 if (byte_metering_on) \ |
| 67 METER_1 (this_code) ++; \ | 64 { \ |
| 68 if (last_code && \ | 65 if (METER_1 (this_code) != ((1<<VALBITS)-1)) \ |
| 69 METER_2 (last_code,this_code) != ((1<<VALBITS)-1)) \ | 66 METER_1 (this_code)++; \ |
| 70 METER_2 (last_code,this_code) ++; \ | 67 if (last_code \ |
| 71 } \ | 68 && METER_2 (last_code, this_code) != ((1<<VALBITS)-1)) \ |
| 72 } | 69 METER_2 (last_code, this_code)++; \ |
| 73 | 70 } \ |
| 74 #else /* ! BYTE_CODE_METER */ | 71 } |
| 75 | 72 |
| 76 # define meter_code(last_code, this_code) | 73 #else /* no BYTE_CODE_METER */ |
| 77 | 74 |
| 78 #endif | 75 #define METER_CODE(last_code, this_code) |
| 76 | |
| 77 #endif /* no BYTE_CODE_METER */ | |
| 79 | 78 |
| 80 | 79 |
| 81 Lisp_Object Qbytecode; | 80 Lisp_Object Qbytecode; |
| 82 | 81 |
| 83 /* Byte codes: */ | 82 /* Byte codes: */ |
| 105 #define Blist4 0106 | 104 #define Blist4 0106 |
| 106 #define Blength 0107 | 105 #define Blength 0107 |
| 107 #define Baref 0110 | 106 #define Baref 0110 |
| 108 #define Baset 0111 | 107 #define Baset 0111 |
| 109 #define Bsymbol_value 0112 | 108 #define Bsymbol_value 0112 |
| 110 #define Bsymbol_function 0113 | 109 #define Bsymbol_function 0113 /* no longer generated as of v19 */ |
| 111 #define Bset 0114 | 110 #define Bset 0114 |
| 112 #define Bfset 0115 | 111 #define Bfset 0115 /* no longer generated as of v19 */ |
| 113 #define Bget 0116 | 112 #define Bget 0116 |
| 114 #define Bsubstring 0117 | 113 #define Bsubstring 0117 |
| 115 #define Bconcat2 0120 | 114 #define Bconcat2 0120 |
| 116 #define Bconcat3 0121 | 115 #define Bconcat3 0121 |
| 117 #define Bconcat4 0122 | 116 #define Bconcat4 0122 |
| 215 #define BRgotoifnilelsepop 0255 | 214 #define BRgotoifnilelsepop 0255 |
| 216 #define BRgotoifnonnilelsepop 0256 | 215 #define BRgotoifnonnilelsepop 0256 |
| 217 | 216 |
| 218 #define BlistN 0257 | 217 #define BlistN 0257 |
| 219 #define BconcatN 0260 | 218 #define BconcatN 0260 |
| 219 #define BinsertN 0261 | |
| 220 | 220 |
| 221 #define Bconstant 0300 | 221 #define Bconstant 0300 |
| 222 #define CONSTANTLIM 0100 | 222 #define CONSTANTLIM 0100 |
| 223 | 223 |
| 224 /* Fetch the next byte from the bytecode stream */ | 224 /* Fetch the next byte from the bytecode stream */ |
| 299 | 299 |
| 300 while (1) | 300 while (1) |
| 301 { | 301 { |
| 302 #ifdef BYTE_CODE_SAFE | 302 #ifdef BYTE_CODE_SAFE |
| 303 if (stackp > stacke) | 303 if (stackp > stacke) |
| 304 error ( | 304 error ("Byte code stack overflow (byte compiler bug), pc %d, depth %d", |
| 305 "Stack overflow in byte code (byte compiler bug), pc = %d, depth = %d", | |
| 306 pc - XSTRING (string_saved)->data, stacke - stackp); | 305 pc - XSTRING (string_saved)->data, stacke - stackp); |
| 307 if (stackp < stack) | 306 if (stackp < stack) |
| 308 error ("Stack underflow in byte code (byte compiler bug), pc = %d", | 307 error ("Byte code stack underflow (byte compiler bug), pc %d", |
| 309 pc - XSTRING (string_saved)->data); | 308 pc - XSTRING (string_saved)->data); |
| 310 #endif | 309 #endif |
| 311 | 310 |
| 312 if (string_saved != bytestr) | 311 if (string_saved != bytestr) |
| 313 { | 312 { |
| 404 | 403 |
| 405 case Bcall: case Bcall+1: case Bcall+2: case Bcall+3: | 404 case Bcall: case Bcall+1: case Bcall+2: case Bcall+3: |
| 406 case Bcall+4: case Bcall+5: | 405 case Bcall+4: case Bcall+5: |
| 407 op -= Bcall; | 406 op -= Bcall; |
| 408 docall: | 407 docall: |
| 409 DISCARD(op); | 408 DISCARD (op); |
| 410 #ifdef BYTE_CODE_METER | 409 #ifdef BYTE_CODE_METER |
| 411 if (byte_metering_on && XTYPE (TOP) == Lisp_Symbol) | 410 if (byte_metering_on && XTYPE (TOP) == Lisp_Symbol) |
| 412 { | 411 { |
| 413 v1 = TOP; | 412 v1 = TOP; |
| 414 v2 = Fget (v1, Qbyte_code_meter); | 413 v2 = Fget (v1, Qbyte_code_meter); |
| 417 XSETINT (v2, XINT (v2) + 1); | 416 XSETINT (v2, XINT (v2) + 1); |
| 418 Fput (v1, Qbyte_code_meter, v2); | 417 Fput (v1, Qbyte_code_meter, v2); |
| 419 } | 418 } |
| 420 } | 419 } |
| 421 #endif | 420 #endif |
| 421 /* The frobbing of gcpro3 was lost by jwz's changes in June 91 | |
| 422 and then reinserted by jwz in Nov 91. */ | |
| 423 /* Remove protection from the args we are giving to Ffuncall. | |
| 424 FFuncall will protect them, and double protection would | |
| 425 cause disasters. */ | |
| 426 gcpro3.nvars = &TOP - stack - 1; | |
| 422 TOP = Ffuncall (op + 1, &TOP); | 427 TOP = Ffuncall (op + 1, &TOP); |
| 428 gcpro3.nvars = XFASTINT (maxdepth); | |
| 423 break; | 429 break; |
| 424 | 430 |
| 425 case Bunbind+6: | 431 case Bunbind+6: |
| 426 op = FETCH; | 432 op = FETCH; |
| 427 goto dounbind; | 433 goto dounbind; |
| 437 unbind_to (specpdl_ptr - specpdl - op, Qnil); | 443 unbind_to (specpdl_ptr - specpdl - op, Qnil); |
| 438 break; | 444 break; |
| 439 | 445 |
| 440 case Bunbind_all: | 446 case Bunbind_all: |
| 441 /* To unbind back to the beginning of this frame. Not used yet, | 447 /* To unbind back to the beginning of this frame. Not used yet, |
| 442 but wil be needed for tail-recursion elimination. | 448 but will be needed for tail-recursion elimination. */ |
| 443 */ | |
| 444 unbind_to (count, Qnil); | 449 unbind_to (count, Qnil); |
| 445 break; | 450 break; |
| 446 | 451 |
| 447 case Bgoto: | 452 case Bgoto: |
| 448 QUIT; | 453 QUIT; |
| 473 if (NULL (TOP)) | 478 if (NULL (TOP)) |
| 474 { | 479 { |
| 475 QUIT; | 480 QUIT; |
| 476 pc = XSTRING (string_saved)->data + op; | 481 pc = XSTRING (string_saved)->data + op; |
| 477 } | 482 } |
| 478 else DISCARD(1); | 483 else DISCARD (1); |
| 479 break; | 484 break; |
| 480 | 485 |
| 481 case Bgotoifnonnilelsepop: | 486 case Bgotoifnonnilelsepop: |
| 482 op = FETCH2; | 487 op = FETCH2; |
| 483 if (!NULL (TOP)) | 488 if (!NULL (TOP)) |
| 484 { | 489 { |
| 485 QUIT; | 490 QUIT; |
| 486 pc = XSTRING (string_saved)->data + op; | 491 pc = XSTRING (string_saved)->data + op; |
| 487 } | 492 } |
| 488 else DISCARD(1); | 493 else DISCARD (1); |
| 489 break; | 494 break; |
| 490 | 495 |
| 491 case BRgoto: | 496 case BRgoto: |
| 492 QUIT; | 497 QUIT; |
| 493 pc += *pc - 127; | 498 pc += *pc - 127; |
| 516 if (NULL (TOP)) | 521 if (NULL (TOP)) |
| 517 { | 522 { |
| 518 QUIT; | 523 QUIT; |
| 519 pc += op - 128; | 524 pc += op - 128; |
| 520 } | 525 } |
| 521 else DISCARD(1); | 526 else DISCARD (1); |
| 522 break; | 527 break; |
| 523 | 528 |
| 524 case BRgotoifnonnilelsepop: | 529 case BRgotoifnonnilelsepop: |
| 525 op = *pc++; | 530 op = *pc++; |
| 526 if (!NULL (TOP)) | 531 if (!NULL (TOP)) |
| 527 { | 532 { |
| 528 QUIT; | 533 QUIT; |
| 529 pc += op - 128; | 534 pc += op - 128; |
| 530 } | 535 } |
| 531 else DISCARD(1); | 536 else DISCARD (1); |
| 532 break; | 537 break; |
| 533 | 538 |
| 534 case Breturn: | 539 case Breturn: |
| 535 v1 = POP; | 540 v1 = POP; |
| 536 goto exit; | 541 goto exit; |
| 537 | 542 |
| 538 case Bdiscard: | 543 case Bdiscard: |
| 539 DISCARD(1); | 544 DISCARD (1); |
| 540 break; | 545 break; |
| 541 | 546 |
| 542 case Bdup: | 547 case Bdup: |
| 543 v1 = TOP; | 548 v1 = TOP; |
| 544 PUSH (v1); | 549 PUSH (v1); |
| 669 v1 = POP; | 674 v1 = POP; |
| 670 TOP = Fcons (TOP, Fcons (v1, Qnil)); | 675 TOP = Fcons (TOP, Fcons (v1, Qnil)); |
| 671 break; | 676 break; |
| 672 | 677 |
| 673 case Blist3: | 678 case Blist3: |
| 674 DISCARD(2); | 679 DISCARD (2); |
| 675 TOP = Flist (3, &TOP); | 680 TOP = Flist (3, &TOP); |
| 676 break; | 681 break; |
| 677 | 682 |
| 678 case Blist4: | 683 case Blist4: |
| 679 DISCARD(3); | 684 DISCARD (3); |
| 680 TOP = Flist (4, &TOP); | 685 TOP = Flist (4, &TOP); |
| 681 break; | 686 break; |
| 682 | 687 |
| 683 case BlistN: | 688 case BlistN: |
| 684 op = FETCH; | 689 op = FETCH; |
| 727 v2 = POP; v1 = POP; | 732 v2 = POP; v1 = POP; |
| 728 TOP = Fsubstring (TOP, v1, v2); | 733 TOP = Fsubstring (TOP, v1, v2); |
| 729 break; | 734 break; |
| 730 | 735 |
| 731 case Bconcat2: | 736 case Bconcat2: |
| 732 DISCARD(1); | 737 DISCARD (1); |
| 733 TOP = Fconcat (2, &TOP); | 738 TOP = Fconcat (2, &TOP); |
| 734 break; | 739 break; |
| 735 | 740 |
| 736 case Bconcat3: | 741 case Bconcat3: |
| 737 DISCARD(2); | 742 DISCARD (2); |
| 738 TOP = Fconcat (3, &TOP); | 743 TOP = Fconcat (3, &TOP); |
| 739 break; | 744 break; |
| 740 | 745 |
| 741 case Bconcat4: | 746 case Bconcat4: |
| 742 DISCARD(3); | 747 DISCARD (3); |
| 743 TOP = Fconcat (4, &TOP); | 748 TOP = Fconcat (4, &TOP); |
| 744 break; | 749 break; |
| 745 | 750 |
| 746 case BconcatN: | 751 case BconcatN: |
| 747 op = FETCH; | 752 op = FETCH; |
| 797 v1 = POP; | 802 v1 = POP; |
| 798 TOP = Fgeq (TOP, v1); | 803 TOP = Fgeq (TOP, v1); |
| 799 break; | 804 break; |
| 800 | 805 |
| 801 case Bdiff: | 806 case Bdiff: |
| 802 DISCARD(1); | 807 DISCARD (1); |
| 803 TOP = Fminus (2, &TOP); | 808 TOP = Fminus (2, &TOP); |
| 804 break; | 809 break; |
| 805 | 810 |
| 806 case Bnegate: | 811 case Bnegate: |
| 807 v1 = TOP; | 812 v1 = TOP; |
| 813 else | 818 else |
| 814 TOP = Fminus (1, &TOP); | 819 TOP = Fminus (1, &TOP); |
| 815 break; | 820 break; |
| 816 | 821 |
| 817 case Bplus: | 822 case Bplus: |
| 818 DISCARD(1); | 823 DISCARD (1); |
| 819 TOP = Fplus (2, &TOP); | 824 TOP = Fplus (2, &TOP); |
| 820 break; | 825 break; |
| 821 | 826 |
| 822 case Bmax: | 827 case Bmax: |
| 823 DISCARD(1); | 828 DISCARD (1); |
| 824 TOP = Fmax (2, &TOP); | 829 TOP = Fmax (2, &TOP); |
| 825 break; | 830 break; |
| 826 | 831 |
| 827 case Bmin: | 832 case Bmin: |
| 828 DISCARD(1); | 833 DISCARD (1); |
| 829 TOP = Fmin (2, &TOP); | 834 TOP = Fmin (2, &TOP); |
| 830 break; | 835 break; |
| 831 | 836 |
| 832 case Bmult: | 837 case Bmult: |
| 833 DISCARD(1); | 838 DISCARD (1); |
| 834 TOP = Ftimes (2, &TOP); | 839 TOP = Ftimes (2, &TOP); |
| 835 break; | 840 break; |
| 836 | 841 |
| 837 case Bquo: | 842 case Bquo: |
| 838 DISCARD(1); | 843 DISCARD (1); |
| 839 TOP = Fquo (2, &TOP); | 844 TOP = Fquo (2, &TOP); |
| 840 break; | 845 break; |
| 841 | 846 |
| 842 case Brem: | 847 case Brem: |
| 843 v1 = POP; | 848 v1 = POP; |
| 853 TOP = Fgoto_char (TOP); | 858 TOP = Fgoto_char (TOP); |
| 854 break; | 859 break; |
| 855 | 860 |
| 856 case Binsert: | 861 case Binsert: |
| 857 TOP = Finsert (1, &TOP); | 862 TOP = Finsert (1, &TOP); |
| 863 break; | |
| 864 | |
| 865 case BinsertN: | |
| 866 op = FETCH; | |
| 867 DISCARD (op - 1); | |
| 868 TOP = Finsert (op, &TOP); | |
| 858 break; | 869 break; |
| 859 | 870 |
| 860 case Bpoint_max: | 871 case Bpoint_max: |
| 861 XFASTINT (v1) = ZV; | 872 XFASTINT (v1) = ZV; |
| 862 PUSH (v1); | 873 PUSH (v1); |
| 1066 else | 1077 else |
| 1067 TOP = Qnil; | 1078 TOP = Qnil; |
| 1068 break; | 1079 break; |
| 1069 | 1080 |
| 1070 case Bnconc: | 1081 case Bnconc: |
| 1071 DISCARD(1); | 1082 DISCARD (1); |
| 1072 TOP = Fnconc (2, &TOP); | 1083 TOP = Fnconc (2, &TOP); |
| 1073 break; | 1084 break; |
| 1074 | 1085 |
| 1075 case Bnumberp: | 1086 case Bnumberp: |
| 1076 TOP = (XTYPE (TOP) == Lisp_Int || XTYPE (TOP) == Lisp_Float | 1087 TOP = (XTYPE (TOP) == Lisp_Int || XTYPE (TOP) == Lisp_Float |
| 1087 break; | 1098 break; |
| 1088 case Bscan_buffer: | 1099 case Bscan_buffer: |
| 1089 error ("scan-buffer is an obsolete bytecode"); | 1100 error ("scan-buffer is an obsolete bytecode"); |
| 1090 break; | 1101 break; |
| 1091 case Bmark: | 1102 case Bmark: |
| 1092 error("mark is an obsolete bytecode"); | 1103 error ("mark is an obsolete bytecode"); |
| 1093 break; | 1104 break; |
| 1094 #endif | 1105 #endif |
| 1095 | 1106 |
| 1096 default: | 1107 default: |
| 1097 #ifdef BYTE_CODE_SAFE | 1108 #ifdef BYTE_CODE_SAFE |
| 1126 defsubr (&Sbyte_code); | 1137 defsubr (&Sbyte_code); |
| 1127 | 1138 |
| 1128 #ifdef BYTE_CODE_METER | 1139 #ifdef BYTE_CODE_METER |
| 1129 | 1140 |
| 1130 DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter, | 1141 DEFVAR_LISP ("byte-code-meter", &Vbyte_code_meter, |
| 1131 "a vector of vectors which holds a histogram of byte-code usage."); | 1142 "A vector of vectors which holds a histogram of byte-code usage."); |
| 1132 DEFVAR_BOOL ("byte-metering-on", &byte_metering_on, ""); | 1143 DEFVAR_BOOL ("byte-metering-on", &byte_metering_on, ""); |
| 1133 | 1144 |
| 1134 byte_metering_on = 0; | 1145 byte_metering_on = 0; |
| 1135 Vbyte_code_meter = Fmake_vector(make_number(256), make_number(0)); | 1146 Vbyte_code_meter = Fmake_vector (make_number (256), make_number (0)); |
| 1147 Qbyte_code_meter = intern ("byte-code-meter"); | |
| 1136 staticpro (&Qbyte_code_meter); | 1148 staticpro (&Qbyte_code_meter); |
| 1137 { | 1149 { |
| 1138 int i = 256; | 1150 int i = 256; |
| 1139 while (i--) | 1151 while (i--) |
| 1140 XVECTOR(Vbyte_code_meter)->contents[i] = | 1152 XVECTOR (Vbyte_code_meter)->contents[i] = |
| 1141 Fmake_vector(make_number(256), make_number(0)); | 1153 Fmake_vector (make_number (256), make_number (0)); |
| 1142 } | 1154 } |
| 1143 #endif | 1155 #endif |
| 1144 } | 1156 } |
