diff options
| author | Mattias EngdegÄrd | 2025-09-22 18:33:01 +0200 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2025-10-16 19:27:17 +0200 |
| commit | 58a5a1f0988790b94bf08cfa73864427a698ef64 (patch) | |
| tree | f1edc7024b0adba2f35b3283e2e76bd99273cf57 /src/bytecode.c | |
| parent | 888a910bc9a840ea8007abe04d610b66e8de56db (diff) | |
| download | emacs-58a5a1f0988790b94bf08cfa73864427a698ef64.tar.gz emacs-58a5a1f0988790b94bf08cfa73864427a698ef64.zip | |
exec_byte_code: reduce use of semi-global 'op' (bug#79610)
* src/bytecode.c (exec_byte_code):
Re-type op from int to ptrdiff_t, which avoids some useless conversions.
Reduce its use by using local variables for intra-block use,
and another variable (arg) where it doesn't need to be alive across
instruction dispatch. We also eliminate it where performance doesn't
matter by re-fetching it from the instruction stream.
All this should help the register allocator.
Diffstat (limited to 'src/bytecode.c')
| -rw-r--r-- | src/bytecode.c | 121 |
1 files changed, 65 insertions, 56 deletions
diff --git a/src/bytecode.c b/src/bytecode.c index 424d00f20ec..6230897939e 100644 --- a/src/bytecode.c +++ b/src/bytecode.c | |||
| @@ -533,7 +533,8 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 533 | 533 | ||
| 534 | while (true) | 534 | while (true) |
| 535 | { | 535 | { |
| 536 | int op; | 536 | ptrdiff_t op; |
| 537 | ptrdiff_t arg; | ||
| 537 | enum handlertype type; | 538 | enum handlertype type; |
| 538 | 539 | ||
| 539 | if (BYTE_CODE_SAFE && !valid_sp (bc, top)) | 540 | if (BYTE_CODE_SAFE && !valid_sp (bc, top)) |
| @@ -601,7 +602,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 601 | FIRST | 602 | FIRST |
| 602 | { | 603 | { |
| 603 | CASE (Bvarref7): | 604 | CASE (Bvarref7): |
| 604 | op = FETCH2; | 605 | arg = FETCH2; |
| 605 | goto varref; | 606 | goto varref; |
| 606 | 607 | ||
| 607 | CASE (Bvarref): | 608 | CASE (Bvarref): |
| @@ -610,16 +611,16 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 610 | CASE (Bvarref3): | 611 | CASE (Bvarref3): |
| 611 | CASE (Bvarref4): | 612 | CASE (Bvarref4): |
| 612 | CASE (Bvarref5): | 613 | CASE (Bvarref5): |
| 613 | op -= Bvarref; | 614 | arg = op - Bvarref; |
| 614 | goto varref; | 615 | goto varref; |
| 615 | 616 | ||
| 616 | /* This seems to be the most frequently executed byte-code | 617 | /* This seems to be the most frequently executed byte-code |
| 617 | among the Bvarref's, so avoid a goto here. */ | 618 | among the Bvarref's, so avoid a goto here. */ |
| 618 | CASE (Bvarref6): | 619 | CASE (Bvarref6): |
| 619 | op = FETCH; | 620 | arg = FETCH; |
| 620 | varref: | 621 | varref: |
| 621 | { | 622 | { |
| 622 | Lisp_Object v1 = vectorp[op], v2; | 623 | Lisp_Object v1 = vectorp[arg], v2; |
| 623 | if (XBARE_SYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL | 624 | if (XBARE_SYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL |
| 624 | || (v2 = XBARE_SYMBOL (v1)->u.s.val.value, | 625 | || (v2 = XBARE_SYMBOL (v1)->u.s.val.value, |
| 625 | BASE_EQ (v2, Qunbound))) | 626 | BASE_EQ (v2, Qunbound))) |
| @@ -631,7 +632,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 631 | CASE (Bgotoifnil): | 632 | CASE (Bgotoifnil): |
| 632 | { | 633 | { |
| 633 | Lisp_Object v1 = POP; | 634 | Lisp_Object v1 = POP; |
| 634 | op = FETCH2; | 635 | arg = FETCH2; |
| 635 | if (NILP (v1)) | 636 | if (NILP (v1)) |
| 636 | goto op_branch; | 637 | goto op_branch; |
| 637 | NEXT; | 638 | NEXT; |
| @@ -679,18 +680,18 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 679 | CASE (Bvarset3): | 680 | CASE (Bvarset3): |
| 680 | CASE (Bvarset4): | 681 | CASE (Bvarset4): |
| 681 | CASE (Bvarset5): | 682 | CASE (Bvarset5): |
| 682 | op -= Bvarset; | 683 | arg = op - Bvarset; |
| 683 | goto varset; | 684 | goto varset; |
| 684 | 685 | ||
| 685 | CASE (Bvarset7): | 686 | CASE (Bvarset7): |
| 686 | op = FETCH2; | 687 | arg = FETCH2; |
| 687 | goto varset; | 688 | goto varset; |
| 688 | 689 | ||
| 689 | CASE (Bvarset6): | 690 | CASE (Bvarset6): |
| 690 | op = FETCH; | 691 | arg = FETCH; |
| 691 | varset: | 692 | varset: |
| 692 | { | 693 | { |
| 693 | Lisp_Object sym = vectorp[op]; | 694 | Lisp_Object sym = vectorp[arg]; |
| 694 | Lisp_Object val = POP; | 695 | Lisp_Object val = POP; |
| 695 | if (XBARE_SYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL | 696 | if (XBARE_SYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL |
| 696 | && !XBARE_SYMBOL (sym)->u.s.trapped_write) | 697 | && !XBARE_SYMBOL (sym)->u.s.trapped_write) |
| @@ -710,11 +711,11 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 710 | /* ------------------ */ | 711 | /* ------------------ */ |
| 711 | 712 | ||
| 712 | CASE (Bvarbind6): | 713 | CASE (Bvarbind6): |
| 713 | op = FETCH; | 714 | arg = FETCH; |
| 714 | goto varbind; | 715 | goto varbind; |
| 715 | 716 | ||
| 716 | CASE (Bvarbind7): | 717 | CASE (Bvarbind7): |
| 717 | op = FETCH2; | 718 | arg = FETCH2; |
| 718 | goto varbind; | 719 | goto varbind; |
| 719 | 720 | ||
| 720 | CASE (Bvarbind): | 721 | CASE (Bvarbind): |
| @@ -723,18 +724,18 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 723 | CASE (Bvarbind3): | 724 | CASE (Bvarbind3): |
| 724 | CASE (Bvarbind4): | 725 | CASE (Bvarbind4): |
| 725 | CASE (Bvarbind5): | 726 | CASE (Bvarbind5): |
| 726 | op -= Bvarbind; | 727 | arg = op - Bvarbind; |
| 727 | varbind: | 728 | varbind: |
| 728 | /* Specbind can signal and thus GC. */ | 729 | /* Specbind can signal and thus GC. */ |
| 729 | specbind (vectorp[op], POP); | 730 | specbind (vectorp[arg], POP); |
| 730 | NEXT; | 731 | NEXT; |
| 731 | 732 | ||
| 732 | CASE (Bcall6): | 733 | CASE (Bcall6): |
| 733 | op = FETCH; | 734 | arg = FETCH; |
| 734 | goto docall; | 735 | goto docall; |
| 735 | 736 | ||
| 736 | CASE (Bcall7): | 737 | CASE (Bcall7): |
| 737 | op = FETCH2; | 738 | arg = FETCH2; |
| 738 | goto docall; | 739 | goto docall; |
| 739 | 740 | ||
| 740 | CASE (Bcall): | 741 | CASE (Bcall): |
| @@ -743,10 +744,10 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 743 | CASE (Bcall3): | 744 | CASE (Bcall3): |
| 744 | CASE (Bcall4): | 745 | CASE (Bcall4): |
| 745 | CASE (Bcall5): | 746 | CASE (Bcall5): |
| 746 | op -= Bcall; | 747 | arg = op - Bcall; |
| 747 | docall: | 748 | docall: |
| 748 | { | 749 | { |
| 749 | DISCARD (op); | 750 | DISCARD (arg); |
| 750 | #ifdef BYTE_CODE_METER | 751 | #ifdef BYTE_CODE_METER |
| 751 | if (byte_metering_on && SYMBOLP (TOP)) | 752 | if (byte_metering_on && SYMBOLP (TOP)) |
| 752 | { | 753 | { |
| @@ -770,7 +771,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 770 | error ("Lisp nesting exceeds `max-lisp-eval-depth'"); | 771 | error ("Lisp nesting exceeds `max-lisp-eval-depth'"); |
| 771 | } | 772 | } |
| 772 | 773 | ||
| 773 | ptrdiff_t call_nargs = op; | 774 | ptrdiff_t call_nargs = arg; |
| 774 | Lisp_Object call_fun = TOP; | 775 | Lisp_Object call_fun = TOP; |
| 775 | Lisp_Object *call_args = &TOP + 1; | 776 | Lisp_Object *call_args = &TOP + 1; |
| 776 | 777 | ||
| @@ -815,11 +816,11 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 815 | } | 816 | } |
| 816 | 817 | ||
| 817 | CASE (Bunbind6): | 818 | CASE (Bunbind6): |
| 818 | op = FETCH; | 819 | arg = FETCH; |
| 819 | goto dounbind; | 820 | goto dounbind; |
| 820 | 821 | ||
| 821 | CASE (Bunbind7): | 822 | CASE (Bunbind7): |
| 822 | op = FETCH2; | 823 | arg = FETCH2; |
| 823 | goto dounbind; | 824 | goto dounbind; |
| 824 | 825 | ||
| 825 | CASE (Bunbind): | 826 | CASE (Bunbind): |
| @@ -828,44 +829,44 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 828 | CASE (Bunbind3): | 829 | CASE (Bunbind3): |
| 829 | CASE (Bunbind4): | 830 | CASE (Bunbind4): |
| 830 | CASE (Bunbind5): | 831 | CASE (Bunbind5): |
| 831 | op -= Bunbind; | 832 | arg = op - Bunbind; |
| 832 | dounbind: | 833 | dounbind: |
| 833 | unbind_to (specpdl_ref_add (SPECPDL_INDEX (), -op), Qnil); | 834 | unbind_to (specpdl_ref_add (SPECPDL_INDEX (), -arg), Qnil); |
| 834 | NEXT; | 835 | NEXT; |
| 835 | 836 | ||
| 836 | CASE (Bgoto): | 837 | CASE (Bgoto): |
| 837 | op = FETCH2; | 838 | arg = FETCH2; |
| 838 | op_branch: | 839 | op_branch: |
| 839 | op -= pc - bytestr_data; | 840 | arg -= pc - bytestr_data; |
| 840 | if (BYTE_CODE_SAFE | 841 | if (BYTE_CODE_SAFE |
| 841 | && ! (bytestr_data - pc <= op | 842 | && ! (bytestr_data - pc <= arg |
| 842 | && op < bytestr_data + bytestr_length - pc)) | 843 | && arg < bytestr_data + bytestr_length - pc)) |
| 843 | emacs_abort (); | 844 | emacs_abort (); |
| 844 | quitcounter += op < 0; | 845 | quitcounter += arg < 0; |
| 845 | if (!quitcounter) | 846 | if (!quitcounter) |
| 846 | { | 847 | { |
| 847 | quitcounter = 1; | 848 | quitcounter = 1; |
| 848 | maybe_gc (); | 849 | maybe_gc (); |
| 849 | maybe_quit (); | 850 | maybe_quit (); |
| 850 | } | 851 | } |
| 851 | pc += op; | 852 | pc += arg; |
| 852 | NEXT; | 853 | NEXT; |
| 853 | 854 | ||
| 854 | CASE (Bgotoifnonnil): | 855 | CASE (Bgotoifnonnil): |
| 855 | op = FETCH2; | 856 | arg = FETCH2; |
| 856 | if (!NILP (POP)) | 857 | if (!NILP (POP)) |
| 857 | goto op_branch; | 858 | goto op_branch; |
| 858 | NEXT; | 859 | NEXT; |
| 859 | 860 | ||
| 860 | CASE (Bgotoifnilelsepop): | 861 | CASE (Bgotoifnilelsepop): |
| 861 | op = FETCH2; | 862 | arg = FETCH2; |
| 862 | if (NILP (TOP)) | 863 | if (NILP (TOP)) |
| 863 | goto op_branch; | 864 | goto op_branch; |
| 864 | DISCARD (1); | 865 | DISCARD (1); |
| 865 | NEXT; | 866 | NEXT; |
| 866 | 867 | ||
| 867 | CASE (Bgotoifnonnilelsepop): | 868 | CASE (Bgotoifnonnilelsepop): |
| 868 | op = FETCH2; | 869 | arg = FETCH2; |
| 869 | if (!NILP (TOP)) | 870 | if (!NILP (TOP)) |
| 870 | goto op_branch; | 871 | goto op_branch; |
| 871 | DISCARD (1); | 872 | DISCARD (1); |
| @@ -965,7 +966,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 965 | struct handler *c = handlerlist; | 966 | struct handler *c = handlerlist; |
| 966 | handlerlist = c->next; | 967 | handlerlist = c->next; |
| 967 | top = c->bytecode_top; | 968 | top = c->bytecode_top; |
| 968 | op = c->bytecode_dest; | 969 | arg = c->bytecode_dest; |
| 969 | bc = ¤t_thread->bc; | 970 | bc = ¤t_thread->bc; |
| 970 | struct bc_frame *fp = bc->fp; | 971 | struct bc_frame *fp = bc->fp; |
| 971 | 972 | ||
| @@ -1105,10 +1106,12 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1105 | NEXT; | 1106 | NEXT; |
| 1106 | 1107 | ||
| 1107 | CASE (BlistN): | 1108 | CASE (BlistN): |
| 1108 | op = FETCH; | 1109 | { |
| 1109 | DISCARD (op - 1); | 1110 | ptrdiff_t n = FETCH; |
| 1110 | TOP = Flist (op, &TOP); | 1111 | DISCARD (n - 1); |
| 1111 | NEXT; | 1112 | TOP = Flist (n, &TOP); |
| 1113 | NEXT; | ||
| 1114 | } | ||
| 1112 | 1115 | ||
| 1113 | CASE (Blength): | 1116 | CASE (Blength): |
| 1114 | TOP = Flength (TOP); | 1117 | TOP = Flength (TOP); |
| @@ -1224,10 +1227,12 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1224 | NEXT; | 1227 | NEXT; |
| 1225 | 1228 | ||
| 1226 | CASE (BconcatN): | 1229 | CASE (BconcatN): |
| 1227 | op = FETCH; | 1230 | { |
| 1228 | DISCARD (op - 1); | 1231 | ptrdiff_t n = FETCH; |
| 1229 | TOP = Fconcat (op, &TOP); | 1232 | DISCARD (n - 1); |
| 1230 | NEXT; | 1233 | TOP = Fconcat (n, &TOP); |
| 1234 | NEXT; | ||
| 1235 | } | ||
| 1231 | 1236 | ||
| 1232 | CASE (Bsub1): | 1237 | CASE (Bsub1): |
| 1233 | TOP = (FIXNUMP (TOP) && XFIXNUM (TOP) != MOST_NEGATIVE_FIXNUM | 1238 | TOP = (FIXNUMP (TOP) && XFIXNUM (TOP) != MOST_NEGATIVE_FIXNUM |
| @@ -1410,10 +1415,12 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1410 | NEXT; | 1415 | NEXT; |
| 1411 | 1416 | ||
| 1412 | CASE (BinsertN): | 1417 | CASE (BinsertN): |
| 1413 | op = FETCH; | 1418 | { |
| 1414 | DISCARD (op - 1); | 1419 | ptrdiff_t n = FETCH; |
| 1415 | TOP = Finsert (op, &TOP); | 1420 | DISCARD (n - 1); |
| 1416 | NEXT; | 1421 | TOP = Finsert (n, &TOP); |
| 1422 | NEXT; | ||
| 1423 | } | ||
| 1417 | 1424 | ||
| 1418 | CASE (Bpoint_max): | 1425 | CASE (Bpoint_max): |
| 1419 | PUSH (make_fixed_natnum (ZV)); | 1426 | PUSH (make_fixed_natnum (ZV)); |
| @@ -1676,7 +1683,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1676 | for that instead. */ | 1683 | for that instead. */ |
| 1677 | /* CASE (Bstack_ref): */ | 1684 | /* CASE (Bstack_ref): */ |
| 1678 | error ("Invalid byte opcode: op=%d, ptr=%"pD"d", | 1685 | error ("Invalid byte opcode: op=%d, ptr=%"pD"d", |
| 1679 | op, pc - 1 - bytestr_data); | 1686 | pc[-1], pc - 1 - bytestr_data); |
| 1680 | 1687 | ||
| 1681 | /* Handy byte-codes for lexical binding. */ | 1688 | /* Handy byte-codes for lexical binding. */ |
| 1682 | CASE (Bstack_ref1): | 1689 | CASE (Bstack_ref1): |
| @@ -1715,14 +1722,16 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1715 | NEXT; | 1722 | NEXT; |
| 1716 | } | 1723 | } |
| 1717 | CASE (BdiscardN): | 1724 | CASE (BdiscardN): |
| 1718 | op = FETCH; | 1725 | { |
| 1719 | if (op & 0x80) | 1726 | ptrdiff_t n = FETCH; |
| 1720 | { | 1727 | if (n & 0x80) |
| 1721 | op &= 0x7F; | 1728 | { |
| 1722 | top[-op] = TOP; | 1729 | n &= 0x7F; |
| 1723 | } | 1730 | top[-n] = TOP; |
| 1724 | DISCARD (op); | 1731 | } |
| 1725 | NEXT; | 1732 | DISCARD (n); |
| 1733 | NEXT; | ||
| 1734 | } | ||
| 1726 | 1735 | ||
| 1727 | CASE (Bswitch): | 1736 | CASE (Bswitch): |
| 1728 | { | 1737 | { |
| @@ -1750,7 +1759,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1750 | for (ptrdiff_t i = h->count - 1; i >= 0; i--) | 1759 | for (ptrdiff_t i = h->count - 1; i >= 0; i--) |
| 1751 | if (BASE_EQ (v1, HASH_KEY (h, i))) | 1760 | if (BASE_EQ (v1, HASH_KEY (h, i))) |
| 1752 | { | 1761 | { |
| 1753 | op = XFIXNUM (HASH_VALUE (h, i)); | 1762 | arg = XFIXNUM (HASH_VALUE (h, i)); |
| 1754 | goto op_branch; | 1763 | goto op_branch; |
| 1755 | } | 1764 | } |
| 1756 | } | 1765 | } |
| @@ -1759,7 +1768,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, | |||
| 1759 | ptrdiff_t i = hash_find (h, v1); | 1768 | ptrdiff_t i = hash_find (h, v1); |
| 1760 | if (i >= 0) | 1769 | if (i >= 0) |
| 1761 | { | 1770 | { |
| 1762 | op = XFIXNUM (HASH_VALUE (h, i)); | 1771 | arg = XFIXNUM (HASH_VALUE (h, i)); |
| 1763 | goto op_branch; | 1772 | goto op_branch; |
| 1764 | } | 1773 | } |
| 1765 | } | 1774 | } |