diff options
| author | Eli Zaretskii | 2016-12-04 19:59:17 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-12-04 19:59:17 +0200 |
| commit | de4624c99ea5bbe38ad5aff7b6461cc5c740d0be (patch) | |
| tree | 1b57de9e769cdb695cb2cecf157b50f7dea9cfe5 /src/bytecode.c | |
| parent | a486fabb41cdbaa5813c2687fd4008945297d71d (diff) | |
| parent | e7bde34e939451d87fb42a36195086bdbe48b5e1 (diff) | |
| download | emacs-de4624c99ea5bbe38ad5aff7b6461cc5c740d0be.tar.gz emacs-de4624c99ea5bbe38ad5aff7b6461cc5c740d0be.zip | |
Merge branch 'concurrency'
Conflicts (resolved):
configure.ac
src/Makefile.in
src/alloc.c
src/bytecode.c
src/emacs.c
src/eval.c
src/lisp.h
src/process.c
src/regex.c
src/regex.h
Diffstat (limited to 'src/bytecode.c')
| -rw-r--r-- | src/bytecode.c | 200 |
1 files changed, 153 insertions, 47 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 868c0148d30..3ac94055f33 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 | ||
| @@ -666,72 +753,85 @@ 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 | } | ||
| 698 | NEXT; | 781 | NEXT; |
| 699 | 782 | ||
| 700 | CASE (Bgotoifnonnilelsepop): | 783 | CASE (Bgotoifnonnilelsepop): |
| 701 | op = FETCH2; | 784 | op = FETCH2; |
| 702 | if (!NILP (TOP)) | 785 | if (!NILP (TOP)) |
| 703 | goto op_branch; | 786 | { |
| 704 | DISCARD (1); | 787 | BYTE_CODE_QUIT; |
| 788 | CHECK_RANGE (op); | ||
| 789 | stack.pc = stack.byte_string_start + op; | ||
| 790 | } | ||
| 791 | else DISCARD (1); | ||
| 705 | NEXT; | 792 | NEXT; |
| 706 | 793 | ||
| 707 | CASE (BRgoto): | 794 | CASE (BRgoto): |
| 708 | op = FETCH - 128; | 795 | BYTE_CODE_QUIT; |
| 709 | goto op_relative_branch; | 796 | stack.pc += (int) *stack.pc - 127; |
| 797 | NEXT; | ||
| 710 | 798 | ||
| 711 | CASE (BRgotoifnil): | 799 | CASE (BRgotoifnil): |
| 712 | op = FETCH - 128; | ||
| 713 | if (NILP (POP)) | 800 | if (NILP (POP)) |
| 714 | goto op_relative_branch; | 801 | { |
| 802 | BYTE_CODE_QUIT; | ||
| 803 | stack.pc += (int) *stack.pc - 128; | ||
| 804 | } | ||
| 805 | stack.pc++; | ||
| 715 | NEXT; | 806 | NEXT; |
| 716 | 807 | ||
| 717 | CASE (BRgotoifnonnil): | 808 | CASE (BRgotoifnonnil): |
| 718 | op = FETCH - 128; | ||
| 719 | if (!NILP (POP)) | 809 | if (!NILP (POP)) |
| 720 | goto op_relative_branch; | 810 | { |
| 811 | BYTE_CODE_QUIT; | ||
| 812 | stack.pc += (int) *stack.pc - 128; | ||
| 813 | } | ||
| 814 | stack.pc++; | ||
| 721 | NEXT; | 815 | NEXT; |
| 722 | 816 | ||
| 723 | CASE (BRgotoifnilelsepop): | 817 | CASE (BRgotoifnilelsepop): |
| 724 | op = FETCH - 128; | 818 | op = *stack.pc++; |
| 725 | if (NILP (TOP)) | 819 | if (NILP (TOP)) |
| 726 | goto op_relative_branch; | 820 | { |
| 727 | DISCARD (1); | 821 | BYTE_CODE_QUIT; |
| 822 | stack.pc += op - 128; | ||
| 823 | } | ||
| 824 | else DISCARD (1); | ||
| 728 | NEXT; | 825 | NEXT; |
| 729 | 826 | ||
| 730 | CASE (BRgotoifnonnilelsepop): | 827 | CASE (BRgotoifnonnilelsepop): |
| 731 | op = FETCH - 128; | 828 | op = *stack.pc++; |
| 732 | if (!NILP (TOP)) | 829 | if (!NILP (TOP)) |
| 733 | goto op_relative_branch; | 830 | { |
| 734 | DISCARD (1); | 831 | BYTE_CODE_QUIT; |
| 832 | stack.pc += op - 128; | ||
| 833 | } | ||
| 834 | else DISCARD (1); | ||
| 735 | NEXT; | 835 | NEXT; |
| 736 | 836 | ||
| 737 | CASE (Breturn): | 837 | CASE (Breturn): |
| @@ -791,11 +891,15 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 791 | if (sys_setjmp (c->jmp)) | 891 | if (sys_setjmp (c->jmp)) |
| 792 | { | 892 | { |
| 793 | struct handler *c = handlerlist; | 893 | struct handler *c = handlerlist; |
| 894 | int desc; | ||
| 794 | top = c->bytecode_top; | 895 | top = c->bytecode_top; |
| 795 | op = c->bytecode_dest; | 896 | dest = c->bytecode_dest; |
| 796 | handlerlist = c->next; | 897 | handlerlist = c->next; |
| 797 | PUSH (c->val); | 898 | PUSH (c->val); |
| 798 | goto op_branch; | 899 | CHECK_RANGE (dest); |
| 900 | /* Might have been re-set by longjmp! */ | ||
| 901 | stack.byte_string_start = SDATA (stack.byte_string); | ||
| 902 | stack.pc = stack.byte_string_start + dest; | ||
| 799 | } | 903 | } |
| 800 | 904 | ||
| 801 | NEXT; | 905 | NEXT; |
| @@ -1364,7 +1468,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1364 | call3 (Qerror, | 1468 | call3 (Qerror, |
| 1365 | build_string ("Invalid byte opcode: op=%s, ptr=%d"), | 1469 | build_string ("Invalid byte opcode: op=%s, ptr=%d"), |
| 1366 | make_number (op), | 1470 | make_number (op), |
| 1367 | make_number (pc - 1 - bytestr_data)); | 1471 | make_number (stack.pc - 1 - stack.byte_string_start)); |
| 1368 | 1472 | ||
| 1369 | /* Handy byte-codes for lexical binding. */ | 1473 | /* Handy byte-codes for lexical binding. */ |
| 1370 | CASE (Bstack_ref1): | 1474 | CASE (Bstack_ref1): |
| @@ -1424,6 +1528,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, | |||
| 1424 | 1528 | ||
| 1425 | exit: | 1529 | exit: |
| 1426 | 1530 | ||
| 1531 | byte_stack_list = byte_stack_list->next; | ||
| 1532 | |||
| 1427 | /* Binds and unbinds are supposed to be compiled balanced. */ | 1533 | /* Binds and unbinds are supposed to be compiled balanced. */ |
| 1428 | if (SPECPDL_INDEX () != count) | 1534 | if (SPECPDL_INDEX () != count) |
| 1429 | { | 1535 | { |