aboutsummaryrefslogtreecommitdiffstats
path: root/src/bytecode.c
diff options
context:
space:
mode:
authorMattias EngdegÄrd2025-09-22 18:33:01 +0200
committerMattias EngdegÄrd2025-10-16 19:27:17 +0200
commit58a5a1f0988790b94bf08cfa73864427a698ef64 (patch)
treef1edc7024b0adba2f35b3283e2e76bd99273cf57 /src/bytecode.c
parent888a910bc9a840ea8007abe04d610b66e8de56db (diff)
downloademacs-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.c121
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 = &current_thread->bc; 970 bc = &current_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 }