diff options
| author | Alan Mackenzie | 2016-12-23 20:28:21 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2016-12-23 20:28:21 +0000 |
| commit | 441e3b78c7b4a874e98bbc436f2b8d9771ca9d4e (patch) | |
| tree | dcad6019cc15c5bc39eb0385e5c54f4170d07d23 /src/bytecode.c | |
| parent | de077da39da7d143f904d6405b62919e5f3e72d6 (diff) | |
| parent | eff901b8a39f42ddedf4c1db833b9071cae5962f (diff) | |
| download | emacs-441e3b78c7b4a874e98bbc436f2b8d9771ca9d4e.tar.gz emacs-441e3b78c7b4a874e98bbc436f2b8d9771ca9d4e.zip | |
Merge branch 'master' into comment-cache
Diffstat (limited to 'src/bytecode.c')
| -rw-r--r-- | src/bytecode.c | 203 |
1 files changed, 155 insertions, 48 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 71ecdbf2cc0..c581ed6d982 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -280,10 +280,68 @@ enum byte_code_op | |||
| 280 | Bset_mark = 0163, /* this loser is no longer generated as of v18 */ | 280 | Bset_mark = 0163, /* this loser is no longer generated as of v18 */ |
| 281 | #endif | 281 | #endif |
| 282 | }; | 282 | }; |
| 283 | |||
| 284 | /* Whether to maintain a `top' and `bottom' field in the stack frame. */ | ||
| 285 | #define BYTE_MAINTAIN_TOP BYTE_CODE_SAFE | ||
| 283 | 286 | ||
| 284 | /* Fetch the next byte from the bytecode stream. */ | 287 | /* Structure describing a value stack used during byte-code execution |
| 288 | in Fbyte_code. */ | ||
| 289 | |||
| 290 | struct byte_stack | ||
| 291 | { | ||
| 292 | /* Program counter. This points into the byte_string below | ||
| 293 | and is relocated when that string is relocated. */ | ||
| 294 | const unsigned char *pc; | ||
| 295 | |||
| 296 | /* Top and bottom of stack. The bottom points to an area of memory | ||
| 297 | allocated with alloca in Fbyte_code. */ | ||
| 298 | #if BYTE_MAINTAIN_TOP | ||
| 299 | Lisp_Object *top, *bottom; | ||
| 300 | #endif | ||
| 301 | |||
| 302 | /* The string containing the byte-code, and its current address. | ||
| 303 | Storing this here protects it from GC because mark_byte_stack | ||
| 304 | marks it. */ | ||
| 305 | Lisp_Object byte_string; | ||
| 306 | const unsigned char *byte_string_start; | ||
| 307 | |||
| 308 | /* Next entry in byte_stack_list. */ | ||
| 309 | struct byte_stack *next; | ||
| 310 | }; | ||
| 311 | |||
| 312 | /* A list of currently active byte-code execution value stacks. | ||
| 313 | Fbyte_code adds an entry to the head of this list before it starts | ||
| 314 | processing byte-code, and it removes the entry again when it is | ||
| 315 | done. Signaling an error truncates the list. | ||
| 316 | |||
| 317 | byte_stack_list is a macro defined in thread.h. */ | ||
| 318 | /* struct byte_stack *byte_stack_list; */ | ||
| 319 | |||
| 320 | |||
| 321 | /* Relocate program counters in the stacks on byte_stack_list. Called | ||
| 322 | when GC has completed. */ | ||
| 323 | |||
| 324 | void | ||
| 325 | relocate_byte_stack (struct byte_stack *stack) | ||
| 326 | { | ||
| 327 | for (; stack; stack = stack->next) | ||
| 328 | { | ||
| 329 | if (stack->byte_string_start != SDATA (stack->byte_string)) | ||
| 330 | { | ||
| 331 | ptrdiff_t offset = stack->pc - stack->byte_string_start; | ||
| 332 | stack->byte_string_start = SDATA (stack->byte_string); | ||
| 333 | stack->pc = stack->byte_string_start + offset; | ||
| 334 | } | ||
| 335 | } | ||
| 336 | } | ||
| 285 | 337 | ||
| 286 | #define FETCH (*pc++) | 338 | |
| 339 | /* Fetch the next byte from the bytecode stream. */ | ||
| 340 | #ifdef BYTE_CODE_SAFE | ||
| 341 | #define FETCH (eassert (stack.byte_string_start == SDATA (stack.byte_string)), *stack.pc++) | ||
| 342 | #else | ||
| 343 | #define FETCH *stack.pc++ | ||
| 344 | #endif | ||
| 287 | 345 | ||
| 288 | /* Fetch two bytes from the bytecode stream and make a 16-bit number | 346 | /* Fetch two bytes from the bytecode stream and make a 16-bit number |
| 289 | out of them. */ | 347 | out of them. */ |
| @@ -308,6 +366,29 @@ enum byte_code_op | |||
| 308 | 366 | ||
| 309 | #define TOP (*top) | 367 | #define TOP (*top) |
| 310 | 368 | ||
| 369 | #define CHECK_RANGE(ARG) \ | ||
| 370 | (BYTE_CODE_SAFE && bytestr_length <= (ARG) ? emacs_abort () : (void) 0) | ||
| 371 | |||
| 372 | /* A version of the QUIT macro which makes sure that the stack top is | ||
| 373 | set before signaling `quit'. */ | ||
| 374 | #define BYTE_CODE_QUIT \ | ||
| 375 | do { \ | ||
| 376 | if (quitcounter++) \ | ||
| 377 | break; \ | ||
| 378 | maybe_gc (); \ | ||
| 379 | if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \ | ||
| 380 | { \ | ||
| 381 | Lisp_Object flag = Vquit_flag; \ | ||
| 382 | Vquit_flag = Qnil; \ | ||
| 383 | if (EQ (Vthrow_on_input, flag)) \ | ||
| 384 | Fthrow (Vthrow_on_input, Qt); \ | ||
| 385 | quit (); \ | ||
| 386 | } \ | ||
| 387 | else if (pending_signals) \ | ||
| 388 | process_pending_signals (); \ | ||
| 389 | } while (0) | ||
| 390 | |||
| 391 | |||
| 311 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, | 392 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, |
| 312 | doc: /* Function used internally in byte-compiled code. | 393 | doc: /* Function used internally in byte-compiled code. |
| 313 | The first argument, BYTESTR, is a string of byte code; | 394 | The first argument, BYTESTR, is a string of byte code; |
| @@ -357,18 +438,19 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 357 | 438 | ||
| 358 | ptrdiff_t bytestr_length = SBYTES (bytestr); | 439 | ptrdiff_t bytestr_length = SBYTES (bytestr); |
| 359 | Lisp_Object *vectorp = XVECTOR (vector)->contents; | 440 | Lisp_Object *vectorp = XVECTOR (vector)->contents; |
| 441 | struct byte_stack stack; | ||
| 360 | 442 | ||
| 361 | unsigned char quitcounter = 1; | 443 | stack.byte_string = bytestr; |
| 444 | stack.pc = stack.byte_string_start = SDATA (bytestr); | ||
| 445 | unsigned char quitcounter = 0; | ||
| 362 | EMACS_INT stack_items = XFASTINT (maxdepth) + 1; | 446 | EMACS_INT stack_items = XFASTINT (maxdepth) + 1; |
| 363 | USE_SAFE_ALLOCA; | 447 | USE_SAFE_ALLOCA; |
| 364 | Lisp_Object *stack_base; | 448 | Lisp_Object *stack_base; |
| 365 | SAFE_ALLOCA_LISP_EXTRA (stack_base, stack_items, bytestr_length); | 449 | SAFE_ALLOCA_LISP (stack_base, stack_items); |
| 366 | Lisp_Object *stack_lim = stack_base + stack_items; | 450 | Lisp_Object *stack_lim = stack_base + stack_items; |
| 367 | Lisp_Object *top = stack_base; | 451 | Lisp_Object *top = stack_base; |
| 368 | memcpy (stack_lim, SDATA (bytestr), bytestr_length); | 452 | stack.next = byte_stack_list; |
| 369 | void *void_stack_lim = stack_lim; | 453 | byte_stack_list = &stack; |
| 370 | unsigned char const *bytestr_data = void_stack_lim; | ||
| 371 | unsigned char const *pc = bytestr_data; | ||
| 372 | ptrdiff_t count = SPECPDL_INDEX (); | 454 | ptrdiff_t count = SPECPDL_INDEX (); |
| 373 | 455 | ||
| 374 | if (!NILP (args_template)) | 456 | if (!NILP (args_template)) |
| @@ -508,10 +590,15 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 508 | 590 | ||
| 509 | CASE (Bgotoifnil): | 591 | CASE (Bgotoifnil): |
| 510 | { | 592 | { |
| 511 | Lisp_Object v1 = POP; | 593 | Lisp_Object v1; |
| 512 | op = FETCH2; | 594 | op = FETCH2; |
| 595 | v1 = POP; | ||
| 513 | if (NILP (v1)) | 596 | if (NILP (v1)) |
| 514 | goto op_branch; | 597 | { |
| 598 | BYTE_CODE_QUIT; | ||
| 599 | CHECK_RANGE (op); | ||
| 600 | stack.pc = stack.byte_string_start + op; | ||
| 601 | } | ||
| 515 | NEXT; | 602 | NEXT; |
| 516 | } | 603 | } |
| 517 | 604 | ||
| @@ -569,7 +656,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 569 | if (SYMBOLP (sym) | 656 | if (SYMBOLP (sym) |
| 570 | && !EQ (val, Qunbound) | 657 | && !EQ (val, Qunbound) |
| 571 | && !XSYMBOL (sym)->redirect | 658 | && !XSYMBOL (sym)->redirect |
| 572 | && !SYMBOL_TRAPPED_WRITE_P (sym)) | 659 | && !SYMBOL_TRAPPED_WRITE_P (sym)) |
| 573 | SET_SYMBOL_VAL (XSYMBOL (sym), val); | 660 | SET_SYMBOL_VAL (XSYMBOL (sym), val); |
| 574 | else | 661 | else |
| 575 | set_internal (sym, val, Qnil, SET_INTERNAL_SET); | 662 | set_internal (sym, val, Qnil, SET_INTERNAL_SET); |
| @@ -666,72 +753,86 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 666 | NEXT; | 753 | NEXT; |
| 667 | 754 | ||
| 668 | CASE (Bgoto): | 755 | CASE (Bgoto): |
| 669 | op = FETCH2; | 756 | BYTE_CODE_QUIT; |
| 670 | op_branch: | 757 | op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */ |
| 671 | op -= pc - bytestr_data; | 758 | CHECK_RANGE (op); |
| 672 | op_relative_branch: | 759 | stack.pc = stack.byte_string_start + op; |
| 673 | if (BYTE_CODE_SAFE | ||
| 674 | && ! (bytestr_data - pc <= op | ||
| 675 | && op < bytestr_data + bytestr_length - pc)) | ||
| 676 | emacs_abort (); | ||
| 677 | quitcounter += op < 0; | ||
| 678 | if (!quitcounter) | ||
| 679 | { | ||
| 680 | quitcounter = 1; | ||
| 681 | maybe_gc (); | ||
| 682 | QUIT; | ||
| 683 | } | ||
| 684 | pc += op; | ||
| 685 | NEXT; | 760 | NEXT; |
| 686 | 761 | ||
| 687 | CASE (Bgotoifnonnil): | 762 | CASE (Bgotoifnonnil): |
| 688 | op = FETCH2; | 763 | op = FETCH2; |
| 689 | if (!NILP (POP)) | 764 | Lisp_Object v1 = POP; |
| 690 | goto op_branch; | 765 | if (!NILP (v1)) |
| 766 | { | ||
| 767 | BYTE_CODE_QUIT; | ||
| 768 | CHECK_RANGE (op); | ||
| 769 | stack.pc = stack.byte_string_start + op; | ||
| 770 | } | ||
| 691 | NEXT; | 771 | NEXT; |
| 692 | 772 | ||
| 693 | CASE (Bgotoifnilelsepop): | 773 | CASE (Bgotoifnilelsepop): |
| 694 | op = FETCH2; | 774 | op = FETCH2; |
| 695 | if (NILP (TOP)) | 775 | if (NILP (TOP)) |
| 696 | goto op_branch; | 776 | { |
| 697 | DISCARD (1); | 777 | BYTE_CODE_QUIT; |
| 778 | CHECK_RANGE (op); | ||
| 779 | stack.pc = stack.byte_string_start + op; | ||
| 780 | } | ||
| 781 | else DISCARD (1); | ||
| 698 | NEXT; | 782 | NEXT; |
| 699 | 783 | ||
| 700 | CASE (Bgotoifnonnilelsepop): | 784 | CASE (Bgotoifnonnilelsepop): |
| 701 | op = FETCH2; | 785 | op = FETCH2; |
| 702 | if (!NILP (TOP)) | 786 | if (!NILP (TOP)) |
| 703 | goto op_branch; | 787 | { |
| 704 | DISCARD (1); | 788 | BYTE_CODE_QUIT; |
| 789 | CHECK_RANGE (op); | ||
| 790 | stack.pc = stack.byte_string_start + op; | ||
| 791 | } | ||
| 792 | else DISCARD (1); | ||
| 705 | NEXT; | 793 | NEXT; |
| 706 | 794 | ||
| 707 | CASE (BRgoto): | 795 | CASE (BRgoto): |
| 708 | op = FETCH - 128; | 796 | BYTE_CODE_QUIT; |
| 709 | goto op_relative_branch; | 797 | stack.pc += (int) *stack.pc - 127; |
| 798 | NEXT; | ||
| 710 | 799 | ||
| 711 | CASE (BRgotoifnil): | 800 | CASE (BRgotoifnil): |
| 712 | op = FETCH - 128; | ||
| 713 | if (NILP (POP)) | 801 | if (NILP (POP)) |
| 714 | goto op_relative_branch; | 802 | { |
| 803 | BYTE_CODE_QUIT; | ||
| 804 | stack.pc += (int) *stack.pc - 128; | ||
| 805 | } | ||
| 806 | stack.pc++; | ||
| 715 | NEXT; | 807 | NEXT; |
| 716 | 808 | ||
| 717 | CASE (BRgotoifnonnil): | 809 | CASE (BRgotoifnonnil): |
| 718 | op = FETCH - 128; | ||
| 719 | if (!NILP (POP)) | 810 | if (!NILP (POP)) |
| 720 | goto op_relative_branch; | 811 | { |
| 812 | BYTE_CODE_QUIT; | ||
| 813 | stack.pc += (int) *stack.pc - 128; | ||
| 814 | } | ||
| 815 | stack.pc++; | ||
| 721 | NEXT; | 816 | NEXT; |
| 722 | 817 | ||
| 723 | CASE (BRgotoifnilelsepop): | 818 | CASE (BRgotoifnilelsepop): |
| 724 | op = FETCH - 128; | 819 | op = *stack.pc++; |
| 725 | if (NILP (TOP)) | 820 | if (NILP (TOP)) |
| 726 | goto op_relative_branch; | 821 | { |
| 727 | DISCARD (1); | 822 | BYTE_CODE_QUIT; |
| 823 | stack.pc += op - 128; | ||
| 824 | } | ||
| 825 | else DISCARD (1); | ||
| 728 | NEXT; | 826 | NEXT; |
| 729 | 827 | ||
| 730 | CASE (BRgotoifnonnilelsepop): | 828 | CASE (BRgotoifnonnilelsepop): |
| 731 | op = FETCH - 128; | 829 | op = *stack.pc++; |
| 732 | if (!NILP (TOP)) | 830 | if (!NILP (TOP)) |
| 733 | goto op_relative_branch; | 831 | { |
| 734 | DISCARD (1); | 832 | BYTE_CODE_QUIT; |
| 833 | stack.pc += op - 128; | ||
| 834 | } | ||
| 835 | else DISCARD (1); | ||
| 735 | NEXT; | 836 | NEXT; |
| 736 | 837 | ||
| 737 | CASE (Breturn): | 838 | CASE (Breturn): |
| @@ -791,11 +892,15 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 791 | if (sys_setjmp (c->jmp)) | 892 | if (sys_setjmp (c->jmp)) |
| 792 | { | 893 | { |
| 793 | struct handler *c = handlerlist; | 894 | struct handler *c = handlerlist; |
| 895 | int dest; | ||
| 794 | top = c->bytecode_top; | 896 | top = c->bytecode_top; |
| 795 | op = c->bytecode_dest; | 897 | dest = c->bytecode_dest; |
| 796 | handlerlist = c->next; | 898 | handlerlist = c->next; |
| 797 | PUSH (c->val); | 899 | PUSH (c->val); |
| 798 | goto op_branch; | 900 | CHECK_RANGE (dest); |
| 901 | /* Might have been re-set by longjmp! */ | ||
| 902 | stack.byte_string_start = SDATA (stack.byte_string); | ||
| 903 | stack.pc = stack.byte_string_start + dest; | ||
| 799 | } | 904 | } |
| 800 | 905 | ||
| 801 | NEXT; | 906 | NEXT; |
| @@ -1363,7 +1468,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1363 | call3 (Qerror, | 1468 | call3 (Qerror, |
| 1364 | build_string ("Invalid byte opcode: op=%s, ptr=%d"), | 1469 | build_string ("Invalid byte opcode: op=%s, ptr=%d"), |
| 1365 | make_number (op), | 1470 | make_number (op), |
| 1366 | make_number (pc - 1 - bytestr_data)); | 1471 | make_number (stack.pc - 1 - stack.byte_string_start)); |
| 1367 | 1472 | ||
| 1368 | /* Handy byte-codes for lexical binding. */ | 1473 | /* Handy byte-codes for lexical binding. */ |
| 1369 | CASE (Bstack_ref1): | 1474 | CASE (Bstack_ref1): |
| @@ -1423,6 +1528,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1423 | 1528 | ||
| 1424 | exit: | 1529 | exit: |
| 1425 | 1530 | ||
| 1531 | byte_stack_list = byte_stack_list->next; | ||
| 1532 | |||
| 1426 | /* Binds and unbinds are supposed to be compiled balanced. */ | 1533 | /* Binds and unbinds are supposed to be compiled balanced. */ |
| 1427 | if (SPECPDL_INDEX () != count) | 1534 | if (SPECPDL_INDEX () != count) |
| 1428 | { | 1535 | { |