diff options
Diffstat (limited to 'src/bytecode.c')
| -rw-r--r-- | src/bytecode.c | 128 |
1 files changed, 122 insertions, 6 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index c53c5acdbb3..fec855c0b83 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -87,9 +87,11 @@ int byte_metering_on; | |||
| 87 | 87 | ||
| 88 | 88 | ||
| 89 | Lisp_Object Qbytecode; | 89 | Lisp_Object Qbytecode; |
| 90 | extern Lisp_Object Qand_optional, Qand_rest; | ||
| 90 | 91 | ||
| 91 | /* Byte codes: */ | 92 | /* Byte codes: */ |
| 92 | 93 | ||
| 94 | #define Bstack_ref 0 | ||
| 93 | #define Bvarref 010 | 95 | #define Bvarref 010 |
| 94 | #define Bvarset 020 | 96 | #define Bvarset 020 |
| 95 | #define Bvarbind 030 | 97 | #define Bvarbind 030 |
| @@ -229,6 +231,13 @@ Lisp_Object Qbytecode; | |||
| 229 | #define BconcatN 0260 | 231 | #define BconcatN 0260 |
| 230 | #define BinsertN 0261 | 232 | #define BinsertN 0261 |
| 231 | 233 | ||
| 234 | /* Bstack_ref is code 0. */ | ||
| 235 | #define Bstack_set 0262 | ||
| 236 | #define Bstack_set2 0263 | ||
| 237 | #define Bvec_ref 0264 | ||
| 238 | #define Bvec_set 0265 | ||
| 239 | #define BdiscardN 0266 | ||
| 240 | |||
| 232 | #define Bconstant 0300 | 241 | #define Bconstant 0300 |
| 233 | #define CONSTANTLIM 0100 | 242 | #define CONSTANTLIM 0100 |
| 234 | 243 | ||
| @@ -397,14 +406,41 @@ unmark_byte_stack () | |||
| 397 | } while (0) | 406 | } while (0) |
| 398 | 407 | ||
| 399 | 408 | ||
| 400 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, | 409 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, MANY, 0, |
| 401 | doc: /* Function used internally in byte-compiled code. | 410 | doc: /* Function used internally in byte-compiled code. |
| 402 | The first argument, BYTESTR, is a string of byte code; | 411 | The first argument, BYTESTR, is a string of byte code; |
| 403 | the second, VECTOR, a vector of constants; | 412 | the second, VECTOR, a vector of constants; |
| 404 | the third, MAXDEPTH, the maximum stack depth used in this function. | 413 | the third, MAXDEPTH, the maximum stack depth used in this function. |
| 405 | If the third argument is incorrect, Emacs may crash. */) | 414 | If the third argument is incorrect, Emacs may crash. |
| 406 | (bytestr, vector, maxdepth) | 415 | |
| 407 | Lisp_Object bytestr, vector, maxdepth; | 416 | If ARGS-TEMPLATE is specified, it is an argument list specification, |
| 417 | according to which any remaining arguments are pushed on the stack | ||
| 418 | before executing BYTESTR. | ||
| 419 | |||
| 420 | usage: (byte-code BYTESTR VECTOR MAXDEP &optional ARGS-TEMPLATE &rest ARGS) */) | ||
| 421 | (nargs, args) | ||
| 422 | int nargs; | ||
| 423 | Lisp_Object *args; | ||
| 424 | { | ||
| 425 | Lisp_Object args_tmpl = nargs >= 4 ? args[3] : Qnil; | ||
| 426 | int pnargs = nargs >= 4 ? nargs - 4 : 0; | ||
| 427 | Lisp_Object *pargs = nargs >= 4 ? args + 4 : 0; | ||
| 428 | return exec_byte_code (args[0], args[1], args[2], args_tmpl, pnargs, pargs); | ||
| 429 | } | ||
| 430 | |||
| 431 | /* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and | ||
| 432 | MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect, | ||
| 433 | emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp | ||
| 434 | argument list (including &rest, &optional, etc.), and ARGS, of size | ||
| 435 | NARGS, should be a vector of the actual arguments. The arguments in | ||
| 436 | ARGS are pushed on the stack according to ARGS_TEMPLATE before | ||
| 437 | executing BYTESTR. */ | ||
| 438 | |||
| 439 | Lisp_Object | ||
| 440 | exec_byte_code (bytestr, vector, maxdepth, args_template, nargs, args) | ||
| 441 | Lisp_Object bytestr, vector, maxdepth, args_template; | ||
| 442 | int nargs; | ||
| 443 | Lisp_Object *args; | ||
| 408 | { | 444 | { |
| 409 | int count = SPECPDL_INDEX (); | 445 | int count = SPECPDL_INDEX (); |
| 410 | #ifdef BYTE_CODE_METER | 446 | #ifdef BYTE_CODE_METER |
| @@ -462,6 +498,37 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 462 | stacke = stack.bottom - 1 + XFASTINT (maxdepth); | 498 | stacke = stack.bottom - 1 + XFASTINT (maxdepth); |
| 463 | #endif | 499 | #endif |
| 464 | 500 | ||
| 501 | if (! NILP (args_template)) | ||
| 502 | /* We should push some arguments on the stack. */ | ||
| 503 | { | ||
| 504 | Lisp_Object at; | ||
| 505 | int pushed = 0, optional = 0; | ||
| 506 | |||
| 507 | for (at = args_template; CONSP (at); at = XCDR (at)) | ||
| 508 | if (EQ (XCAR (at), Qand_optional)) | ||
| 509 | optional = 1; | ||
| 510 | else if (EQ (XCAR (at), Qand_rest)) | ||
| 511 | { | ||
| 512 | PUSH (Flist (nargs, args)); | ||
| 513 | pushed = nargs; | ||
| 514 | at = Qnil; | ||
| 515 | break; | ||
| 516 | } | ||
| 517 | else if (pushed < nargs) | ||
| 518 | { | ||
| 519 | PUSH (*args++); | ||
| 520 | pushed++; | ||
| 521 | } | ||
| 522 | else if (optional) | ||
| 523 | PUSH (Qnil); | ||
| 524 | else | ||
| 525 | break; | ||
| 526 | |||
| 527 | if (pushed != nargs || !NILP (at)) | ||
| 528 | Fsignal (Qwrong_number_of_arguments, | ||
| 529 | Fcons (args_template, Fcons (make_number (nargs), Qnil))); | ||
| 530 | } | ||
| 531 | |||
| 465 | while (1) | 532 | while (1) |
| 466 | { | 533 | { |
| 467 | #ifdef BYTE_CODE_SAFE | 534 | #ifdef BYTE_CODE_SAFE |
| @@ -1641,8 +1708,57 @@ If the third argument is incorrect, Emacs may crash. */) | |||
| 1641 | break; | 1708 | break; |
| 1642 | #endif | 1709 | #endif |
| 1643 | 1710 | ||
| 1644 | case 0: | 1711 | /* Handy byte-codes for lexical binding. */ |
| 1645 | abort (); | 1712 | case Bstack_ref: |
| 1713 | case Bstack_ref+1: | ||
| 1714 | case Bstack_ref+2: | ||
| 1715 | case Bstack_ref+3: | ||
| 1716 | case Bstack_ref+4: | ||
| 1717 | case Bstack_ref+5: | ||
| 1718 | PUSH (stack.bottom[op - Bstack_ref]); | ||
| 1719 | break; | ||
| 1720 | case Bstack_ref+6: | ||
| 1721 | PUSH (stack.bottom[FETCH]); | ||
| 1722 | break; | ||
| 1723 | case Bstack_ref+7: | ||
| 1724 | PUSH (stack.bottom[FETCH2]); | ||
| 1725 | break; | ||
| 1726 | case Bstack_set: | ||
| 1727 | stack.bottom[FETCH] = POP; | ||
| 1728 | break; | ||
| 1729 | case Bstack_set2: | ||
| 1730 | stack.bottom[FETCH2] = POP; | ||
| 1731 | break; | ||
| 1732 | case Bvec_ref: | ||
| 1733 | case Bvec_set: | ||
| 1734 | /* These byte-codes used mostly for variable references to | ||
| 1735 | lexically bound variables that are in an environment vector | ||
| 1736 | instead of on the byte-interpreter stack (generally those | ||
| 1737 | variables which might be shared with a closure). */ | ||
| 1738 | { | ||
| 1739 | int index = FETCH; | ||
| 1740 | Lisp_Object vec = POP; | ||
| 1741 | |||
| 1742 | if (! VECTORP (vec)) | ||
| 1743 | wrong_type_argument (Qvectorp, vec); | ||
| 1744 | else if (index < 0 || index >= XVECTOR (vec)->size) | ||
| 1745 | args_out_of_range (vec, index); | ||
| 1746 | |||
| 1747 | if (op == Bvec_ref) | ||
| 1748 | PUSH (XVECTOR (vec)->contents[index]); | ||
| 1749 | else | ||
| 1750 | XVECTOR (vec)->contents[index] = POP; | ||
| 1751 | } | ||
| 1752 | break; | ||
| 1753 | case BdiscardN: | ||
| 1754 | op = FETCH; | ||
| 1755 | if (op & 0x80) | ||
| 1756 | { | ||
| 1757 | op &= 0x7F; | ||
| 1758 | top[-op] = TOP; | ||
| 1759 | } | ||
| 1760 | DISCARD (op); | ||
| 1761 | break; | ||
| 1646 | 1762 | ||
| 1647 | case 255: | 1763 | case 255: |
| 1648 | default: | 1764 | default: |