diff options
Diffstat (limited to 'src/bytecode.c')
| -rw-r--r-- | src/bytecode.c | 163 |
1 files changed, 143 insertions, 20 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 5a62c913a40..5879d312b07 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -80,9 +80,11 @@ Lisp_Object Qbyte_code_meter; | |||
| 80 | 80 | ||
| 81 | 81 | ||
| 82 | Lisp_Object Qbytecode; | 82 | Lisp_Object Qbytecode; |
| 83 | extern Lisp_Object Qand_optional, Qand_rest; | ||
| 83 | 84 | ||
| 84 | /* Byte codes: */ | 85 | /* Byte codes: */ |
| 85 | 86 | ||
| 87 | #define Bstack_ref 0 /* Actually, Bstack_ref+0 is not implemented: use dup. */ | ||
| 86 | #define Bvarref 010 | 88 | #define Bvarref 010 |
| 87 | #define Bvarset 020 | 89 | #define Bvarset 020 |
| 88 | #define Bvarbind 030 | 90 | #define Bvarbind 030 |
| @@ -132,7 +134,7 @@ Lisp_Object Qbytecode; | |||
| 132 | 134 | ||
| 133 | #define Bpoint 0140 | 135 | #define Bpoint 0140 |
| 134 | /* Was Bmark in v17. */ | 136 | /* Was Bmark in v17. */ |
| 135 | #define Bsave_current_buffer 0141 | 137 | #define Bsave_current_buffer 0141 /* Obsolete. */ |
| 136 | #define Bgoto_char 0142 | 138 | #define Bgoto_char 0142 |
| 137 | #define Binsert 0143 | 139 | #define Binsert 0143 |
| 138 | #define Bpoint_max 0144 | 140 | #define Bpoint_max 0144 |
| @@ -158,7 +160,7 @@ Lisp_Object Qbytecode; | |||
| 158 | #ifdef BYTE_CODE_SAFE | 160 | #ifdef BYTE_CODE_SAFE |
| 159 | #define Bset_mark 0163 /* this loser is no longer generated as of v18 */ | 161 | #define Bset_mark 0163 /* this loser is no longer generated as of v18 */ |
| 160 | #endif | 162 | #endif |
| 161 | #define Binteractive_p 0164 /* Needed since interactive-p takes unevalled args */ | 163 | #define Binteractive_p 0164 /* Obsolete since Emacs-24.1. */ |
| 162 | 164 | ||
| 163 | #define Bforward_char 0165 | 165 | #define Bforward_char 0165 |
| 164 | #define Bforward_word 0166 | 166 | #define Bforward_word 0166 |
| @@ -183,16 +185,16 @@ Lisp_Object Qbytecode; | |||
| 183 | #define Bdup 0211 | 185 | #define Bdup 0211 |
| 184 | 186 | ||
| 185 | #define Bsave_excursion 0212 | 187 | #define Bsave_excursion 0212 |
| 186 | #define Bsave_window_excursion 0213 | 188 | #define Bsave_window_excursion 0213 /* Obsolete since Emacs-24.1. */ |
| 187 | #define Bsave_restriction 0214 | 189 | #define Bsave_restriction 0214 |
| 188 | #define Bcatch 0215 | 190 | #define Bcatch 0215 |
| 189 | 191 | ||
| 190 | #define Bunwind_protect 0216 | 192 | #define Bunwind_protect 0216 |
| 191 | #define Bcondition_case 0217 | 193 | #define Bcondition_case 0217 |
| 192 | #define Btemp_output_buffer_setup 0220 | 194 | #define Btemp_output_buffer_setup 0220 /* Obsolete since Emacs-24.1. */ |
| 193 | #define Btemp_output_buffer_show 0221 | 195 | #define Btemp_output_buffer_show 0221 /* Obsolete since Emacs-24.1. */ |
| 194 | 196 | ||
| 195 | #define Bunbind_all 0222 | 197 | #define Bunbind_all 0222 /* Obsolete. Never used. */ |
| 196 | 198 | ||
| 197 | #define Bset_marker 0223 | 199 | #define Bset_marker 0223 |
| 198 | #define Bmatch_beginning 0224 | 200 | #define Bmatch_beginning 0224 |
| @@ -228,6 +230,11 @@ Lisp_Object Qbytecode; | |||
| 228 | #define BconcatN 0260 | 230 | #define BconcatN 0260 |
| 229 | #define BinsertN 0261 | 231 | #define BinsertN 0261 |
| 230 | 232 | ||
| 233 | /* Bstack_ref is code 0. */ | ||
| 234 | #define Bstack_set 0262 | ||
| 235 | #define Bstack_set2 0263 | ||
| 236 | #define BdiscardN 0266 | ||
| 237 | |||
| 231 | #define Bconstant 0300 | 238 | #define Bconstant 0300 |
| 232 | 239 | ||
| 233 | /* Whether to maintain a `top' and `bottom' field in the stack frame. */ | 240 | /* Whether to maintain a `top' and `bottom' field in the stack frame. */ |
| @@ -414,6 +421,21 @@ the third, MAXDEPTH, the maximum stack depth used in this function. | |||
| 414 | If the third argument is incorrect, Emacs may crash. */) | 421 | If the third argument is incorrect, Emacs may crash. */) |
| 415 | (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth) | 422 | (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth) |
| 416 | { | 423 | { |
| 424 | return exec_byte_code (bytestr, vector, maxdepth, Qnil, 0, NULL); | ||
| 425 | } | ||
| 426 | |||
| 427 | /* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and | ||
| 428 | MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect, | ||
| 429 | emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp | ||
| 430 | argument list (including &rest, &optional, etc.), and ARGS, of size | ||
| 431 | NARGS, should be a vector of the actual arguments. The arguments in | ||
| 432 | ARGS are pushed on the stack according to ARGS_TEMPLATE before | ||
| 433 | executing BYTESTR. */ | ||
| 434 | |||
| 435 | Lisp_Object | ||
| 436 | exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | ||
| 437 | Lisp_Object args_template, int nargs, Lisp_Object *args) | ||
| 438 | { | ||
| 417 | int count = SPECPDL_INDEX (); | 439 | int count = SPECPDL_INDEX (); |
| 418 | #ifdef BYTE_CODE_METER | 440 | #ifdef BYTE_CODE_METER |
| 419 | int this_op = 0; | 441 | int this_op = 0; |
| @@ -475,6 +497,52 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 475 | stacke = stack.bottom - 1 + XFASTINT (maxdepth); | 497 | stacke = stack.bottom - 1 + XFASTINT (maxdepth); |
| 476 | #endif | 498 | #endif |
| 477 | 499 | ||
| 500 | if (INTEGERP (args_template)) | ||
| 501 | { | ||
| 502 | int at = XINT (args_template); | ||
| 503 | int rest = at & 128; | ||
| 504 | int mandatory = at & 127; | ||
| 505 | int nonrest = at >> 8; | ||
| 506 | eassert (mandatory <= nonrest); | ||
| 507 | if (nargs <= nonrest) | ||
| 508 | { | ||
| 509 | int i; | ||
| 510 | for (i = 0 ; i < nargs; i++, args++) | ||
| 511 | PUSH (*args); | ||
| 512 | if (nargs < mandatory) | ||
| 513 | /* Too few arguments. */ | ||
| 514 | Fsignal (Qwrong_number_of_arguments, | ||
| 515 | Fcons (Fcons (make_number (mandatory), | ||
| 516 | rest ? Qand_rest : make_number (nonrest)), | ||
| 517 | Fcons (make_number (nargs), Qnil))); | ||
| 518 | else | ||
| 519 | { | ||
| 520 | for (; i < nonrest; i++) | ||
| 521 | PUSH (Qnil); | ||
| 522 | if (rest) | ||
| 523 | PUSH (Qnil); | ||
| 524 | } | ||
| 525 | } | ||
| 526 | else if (rest) | ||
| 527 | { | ||
| 528 | int i; | ||
| 529 | for (i = 0 ; i < nonrest; i++, args++) | ||
| 530 | PUSH (*args); | ||
| 531 | PUSH (Flist (nargs - nonrest, args)); | ||
| 532 | } | ||
| 533 | else | ||
| 534 | /* Too many arguments. */ | ||
| 535 | Fsignal (Qwrong_number_of_arguments, | ||
| 536 | Fcons (Fcons (make_number (mandatory), | ||
| 537 | make_number (nonrest)), | ||
| 538 | Fcons (make_number (nargs), Qnil))); | ||
| 539 | } | ||
| 540 | else if (! NILP (args_template)) | ||
| 541 | /* We should push some arguments on the stack. */ | ||
| 542 | { | ||
| 543 | error ("Unknown args template!"); | ||
| 544 | } | ||
| 545 | |||
| 478 | while (1) | 546 | while (1) |
| 479 | { | 547 | { |
| 480 | #ifdef BYTE_CODE_SAFE | 548 | #ifdef BYTE_CODE_SAFE |
| @@ -735,7 +803,7 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 735 | AFTER_POTENTIAL_GC (); | 803 | AFTER_POTENTIAL_GC (); |
| 736 | break; | 804 | break; |
| 737 | 805 | ||
| 738 | case Bunbind_all: | 806 | case Bunbind_all: /* Obsolete. Never used. */ |
| 739 | /* To unbind back to the beginning of this frame. Not used yet, | 807 | /* To unbind back to the beginning of this frame. Not used yet, |
| 740 | but will be needed for tail-recursion elimination. */ | 808 | but will be needed for tail-recursion elimination. */ |
| 741 | BEFORE_POTENTIAL_GC (); | 809 | BEFORE_POTENTIAL_GC (); |
| @@ -863,37 +931,43 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 863 | save_excursion_save ()); | 931 | save_excursion_save ()); |
| 864 | break; | 932 | break; |
| 865 | 933 | ||
| 866 | case Bsave_current_buffer: | 934 | case Bsave_current_buffer: /* Obsolete since ??. */ |
| 867 | case Bsave_current_buffer_1: | 935 | case Bsave_current_buffer_1: |
| 868 | record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ()); | 936 | record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ()); |
| 869 | break; | 937 | break; |
| 870 | 938 | ||
| 871 | case Bsave_window_excursion: | 939 | case Bsave_window_excursion: /* Obsolete since 24.1. */ |
| 872 | BEFORE_POTENTIAL_GC (); | 940 | { |
| 873 | TOP = Fsave_window_excursion (TOP); | 941 | register int count = SPECPDL_INDEX (); |
| 874 | AFTER_POTENTIAL_GC (); | 942 | record_unwind_protect (Fset_window_configuration, |
| 875 | break; | 943 | Fcurrent_window_configuration (Qnil)); |
| 944 | BEFORE_POTENTIAL_GC (); | ||
| 945 | TOP = Fprogn (TOP); | ||
| 946 | unbind_to (count, TOP); | ||
| 947 | AFTER_POTENTIAL_GC (); | ||
| 948 | break; | ||
| 949 | } | ||
| 876 | 950 | ||
| 877 | case Bsave_restriction: | 951 | case Bsave_restriction: |
| 878 | record_unwind_protect (save_restriction_restore, | 952 | record_unwind_protect (save_restriction_restore, |
| 879 | save_restriction_save ()); | 953 | save_restriction_save ()); |
| 880 | break; | 954 | break; |
| 881 | 955 | ||
| 882 | case Bcatch: | 956 | case Bcatch: /* FIXME: ill-suited for lexbind */ |
| 883 | { | 957 | { |
| 884 | Lisp_Object v1; | 958 | Lisp_Object v1; |
| 885 | BEFORE_POTENTIAL_GC (); | 959 | BEFORE_POTENTIAL_GC (); |
| 886 | v1 = POP; | 960 | v1 = POP; |
| 887 | TOP = internal_catch (TOP, Feval, v1); | 961 | TOP = internal_catch (TOP, eval_sub, v1); |
| 888 | AFTER_POTENTIAL_GC (); | 962 | AFTER_POTENTIAL_GC (); |
| 889 | break; | 963 | break; |
| 890 | } | 964 | } |
| 891 | 965 | ||
| 892 | case Bunwind_protect: | 966 | case Bunwind_protect: /* FIXME: avoid closure for lexbind */ |
| 893 | record_unwind_protect (Fprogn, POP); | 967 | record_unwind_protect (Fprogn, POP); |
| 894 | break; | 968 | break; |
| 895 | 969 | ||
| 896 | case Bcondition_case: | 970 | case Bcondition_case: /* FIXME: ill-suited for lexbind */ |
| 897 | { | 971 | { |
| 898 | Lisp_Object handlers, body; | 972 | Lisp_Object handlers, body; |
| 899 | handlers = POP; | 973 | handlers = POP; |
| @@ -904,7 +978,7 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 904 | break; | 978 | break; |
| 905 | } | 979 | } |
| 906 | 980 | ||
| 907 | case Btemp_output_buffer_setup: | 981 | case Btemp_output_buffer_setup: /* Obsolete since 24.1. */ |
| 908 | BEFORE_POTENTIAL_GC (); | 982 | BEFORE_POTENTIAL_GC (); |
| 909 | CHECK_STRING (TOP); | 983 | CHECK_STRING (TOP); |
| 910 | temp_output_buffer_setup (SSDATA (TOP)); | 984 | temp_output_buffer_setup (SSDATA (TOP)); |
| @@ -912,7 +986,7 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 912 | TOP = Vstandard_output; | 986 | TOP = Vstandard_output; |
| 913 | break; | 987 | break; |
| 914 | 988 | ||
| 915 | case Btemp_output_buffer_show: | 989 | case Btemp_output_buffer_show: /* Obsolete since 24.1. */ |
| 916 | { | 990 | { |
| 917 | Lisp_Object v1; | 991 | Lisp_Object v1; |
| 918 | BEFORE_POTENTIAL_GC (); | 992 | BEFORE_POTENTIAL_GC (); |
| @@ -1384,7 +1458,7 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 1384 | AFTER_POTENTIAL_GC (); | 1458 | AFTER_POTENTIAL_GC (); |
| 1385 | break; | 1459 | break; |
| 1386 | 1460 | ||
| 1387 | case Binteractive_p: | 1461 | case Binteractive_p: /* Obsolete since 24.1. */ |
| 1388 | PUSH (Finteractive_p ()); | 1462 | PUSH (Finteractive_p ()); |
| 1389 | break; | 1463 | break; |
| 1390 | 1464 | ||
| @@ -1674,8 +1748,57 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 1674 | #endif | 1748 | #endif |
| 1675 | 1749 | ||
| 1676 | case 0: | 1750 | case 0: |
| 1751 | /* Actually this is Bstack_ref with offset 0, but we use Bdup | ||
| 1752 | for that instead. */ | ||
| 1753 | /* case Bstack_ref: */ | ||
| 1677 | abort (); | 1754 | abort (); |
| 1678 | 1755 | ||
| 1756 | /* Handy byte-codes for lexical binding. */ | ||
| 1757 | case Bstack_ref+1: | ||
| 1758 | case Bstack_ref+2: | ||
| 1759 | case Bstack_ref+3: | ||
| 1760 | case Bstack_ref+4: | ||
| 1761 | case Bstack_ref+5: | ||
| 1762 | { | ||
| 1763 | Lisp_Object *ptr = top - (op - Bstack_ref); | ||
| 1764 | PUSH (*ptr); | ||
| 1765 | break; | ||
| 1766 | } | ||
| 1767 | case Bstack_ref+6: | ||
| 1768 | { | ||
| 1769 | Lisp_Object *ptr = top - (FETCH); | ||
| 1770 | PUSH (*ptr); | ||
| 1771 | break; | ||
| 1772 | } | ||
| 1773 | case Bstack_ref+7: | ||
| 1774 | { | ||
| 1775 | Lisp_Object *ptr = top - (FETCH2); | ||
| 1776 | PUSH (*ptr); | ||
| 1777 | break; | ||
| 1778 | } | ||
| 1779 | /* stack-set-0 = discard; stack-set-1 = discard-1-preserve-tos. */ | ||
| 1780 | case Bstack_set: | ||
| 1781 | { | ||
| 1782 | Lisp_Object *ptr = top - (FETCH); | ||
| 1783 | *ptr = POP; | ||
| 1784 | break; | ||
| 1785 | } | ||
| 1786 | case Bstack_set2: | ||
| 1787 | { | ||
| 1788 | Lisp_Object *ptr = top - (FETCH2); | ||
| 1789 | *ptr = POP; | ||
| 1790 | break; | ||
| 1791 | } | ||
| 1792 | case BdiscardN: | ||
| 1793 | op = FETCH; | ||
| 1794 | if (op & 0x80) | ||
| 1795 | { | ||
| 1796 | op &= 0x7F; | ||
| 1797 | top[-op] = TOP; | ||
| 1798 | } | ||
| 1799 | DISCARD (op); | ||
| 1800 | break; | ||
| 1801 | |||
| 1679 | case 255: | 1802 | case 255: |
| 1680 | default: | 1803 | default: |
| 1681 | #ifdef BYTE_CODE_SAFE | 1804 | #ifdef BYTE_CODE_SAFE |