Skip to content

Commit 8e9a1a0

Browse files
authored
gh-106603: Make uop struct a triple (opcode, oparg, operand) (#106794)
1 parent 7e96370 commit 8e9a1a0

File tree

9 files changed

+190
-109
lines changed

9 files changed

+190
-109
lines changed

Include/internal/pycore_opcode_metadata.h

Lines changed: 26 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uops.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ extern "C" {
1111
#define _Py_UOP_MAX_TRACE_LENGTH 32
1212

1313
typedef struct {
14-
int opcode;
15-
uint64_t operand; // Sometimes oparg, sometimes a cache entry
14+
uint32_t opcode;
15+
uint32_t oparg;
16+
uint64_t operand; // A cache entry
1617
} _PyUOpInstruction;
1718

1819
typedef struct {

Lib/test/test_capi/test_misc.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2448,7 +2448,7 @@ def testfunc(x):
24482448

24492449
ex = get_first_executor(testfunc)
24502450
self.assertIsNotNone(ex)
2451-
uops = {opname for opname, _ in ex}
2451+
uops = {opname for opname, _, _ in ex}
24522452
self.assertIn("SAVE_IP", uops)
24532453
self.assertIn("LOAD_FAST", uops)
24542454

@@ -2493,7 +2493,7 @@ def many_vars():
24932493

24942494
ex = get_first_executor(many_vars)
24952495
self.assertIsNotNone(ex)
2496-
self.assertIn(("LOAD_FAST", 259), list(ex))
2496+
self.assertIn(("LOAD_FAST", 259, 0), list(ex))
24972497

24982498
def test_unspecialized_unpack(self):
24992499
# An example of an unspecialized opcode
@@ -2514,7 +2514,7 @@ def testfunc(x):
25142514

25152515
ex = get_first_executor(testfunc)
25162516
self.assertIsNotNone(ex)
2517-
uops = {opname for opname, _ in ex}
2517+
uops = {opname for opname, _, _ in ex}
25182518
self.assertIn("UNPACK_SEQUENCE", uops)
25192519

25202520
def test_pop_jump_if_false(self):
@@ -2529,7 +2529,7 @@ def testfunc(n):
25292529

25302530
ex = get_first_executor(testfunc)
25312531
self.assertIsNotNone(ex)
2532-
uops = {opname for opname, _ in ex}
2532+
uops = {opname for opname, _, _ in ex}
25332533
self.assertIn("_POP_JUMP_IF_FALSE", uops)
25342534

25352535
def test_pop_jump_if_none(self):
@@ -2544,7 +2544,7 @@ def testfunc(a):
25442544

25452545
ex = get_first_executor(testfunc)
25462546
self.assertIsNotNone(ex)
2547-
uops = {opname for opname, _ in ex}
2547+
uops = {opname for opname, _, _ in ex}
25482548
self.assertIn("_POP_JUMP_IF_TRUE", uops)
25492549

25502550
def test_pop_jump_if_not_none(self):
@@ -2559,7 +2559,7 @@ def testfunc(a):
25592559

25602560
ex = get_first_executor(testfunc)
25612561
self.assertIsNotNone(ex)
2562-
uops = {opname for opname, _ in ex}
2562+
uops = {opname for opname, _, _ in ex}
25632563
self.assertIn("_POP_JUMP_IF_FALSE", uops)
25642564

25652565
def test_pop_jump_if_true(self):
@@ -2574,7 +2574,7 @@ def testfunc(n):
25742574

25752575
ex = get_first_executor(testfunc)
25762576
self.assertIsNotNone(ex)
2577-
uops = {opname for opname, _ in ex}
2577+
uops = {opname for opname, _, _ in ex}
25782578
self.assertIn("_POP_JUMP_IF_TRUE", uops)
25792579

25802580
def test_jump_backward(self):
@@ -2589,7 +2589,7 @@ def testfunc(n):
25892589

25902590
ex = get_first_executor(testfunc)
25912591
self.assertIsNotNone(ex)
2592-
uops = {opname for opname, _ in ex}
2592+
uops = {opname for opname, _, _ in ex}
25932593
self.assertIn("JUMP_TO_TOP", uops)
25942594

25952595
def test_jump_forward(self):
@@ -2609,7 +2609,7 @@ def testfunc(n):
26092609

26102610
ex = get_first_executor(testfunc)
26112611
self.assertIsNotNone(ex)
2612-
uops = {opname for opname, _ in ex}
2612+
uops = {opname for opname, _, _ in ex}
26132613
# Since there is no JUMP_FORWARD instruction,
26142614
# look for indirect evidence: the += operator
26152615
self.assertIn("_BINARY_OP_ADD_INT", uops)
@@ -2630,7 +2630,7 @@ def testfunc(n):
26302630
self.assertIsNotNone(ex)
26312631
# for i, (opname, oparg) in enumerate(ex):
26322632
# print(f"{i:4d}: {opname:<20s} {oparg:3d}")
2633-
uops = {opname for opname, _ in ex}
2633+
uops = {opname for opname, _, _ in ex}
26342634
self.assertIn("_IS_ITER_EXHAUSTED_RANGE", uops)
26352635
# Verification that the jump goes past END_FOR
26362636
# is done by manual inspection of the output
@@ -2652,7 +2652,7 @@ def testfunc(a):
26522652
self.assertIsNotNone(ex)
26532653
# for i, (opname, oparg) in enumerate(ex):
26542654
# print(f"{i:4d}: {opname:<20s} {oparg:3d}")
2655-
uops = {opname for opname, _ in ex}
2655+
uops = {opname for opname, _, _ in ex}
26562656
self.assertIn("_IS_ITER_EXHAUSTED_LIST", uops)
26572657
# Verification that the jump goes past END_FOR
26582658
# is done by manual inspection of the output
@@ -2674,7 +2674,7 @@ def testfunc(a):
26742674
self.assertIsNotNone(ex)
26752675
# for i, (opname, oparg) in enumerate(ex):
26762676
# print(f"{i:4d}: {opname:<20s} {oparg:3d}")
2677-
uops = {opname for opname, _ in ex}
2677+
uops = {opname for opname, _, _ in ex}
26782678
self.assertIn("_IS_ITER_EXHAUSTED_TUPLE", uops)
26792679
# Verification that the jump goes past END_FOR
26802680
# is done by manual inspection of the output

Python/bytecodes.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -645,18 +645,16 @@ dummy_func(
645645
STORE_SUBSCR_LIST_INT,
646646
};
647647

648-
inst(STORE_SUBSCR, (counter/1, v, container, sub -- )) {
648+
inst(STORE_SUBSCR, (unused/1, v, container, sub -- )) {
649649
#if ENABLE_SPECIALIZATION
650-
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
650+
_PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr;
651+
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
651652
next_instr--;
652653
_Py_Specialize_StoreSubscr(container, sub, next_instr);
653654
DISPATCH_SAME_OPARG();
654655
}
655656
STAT_INC(STORE_SUBSCR, deferred);
656-
_PyStoreSubscrCache *cache = (_PyStoreSubscrCache *)next_instr;
657657
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
658-
#else
659-
(void)counter; // Unused.
660658
#endif /* ENABLE_SPECIALIZATION */
661659
/* container[sub] = v */
662660
int err = PyObject_SetItem(container, sub, v);
@@ -1198,19 +1196,17 @@ dummy_func(
11981196
STORE_ATTR_WITH_HINT,
11991197
};
12001198

1201-
inst(STORE_ATTR, (counter/1, unused/3, v, owner --)) {
1199+
inst(STORE_ATTR, (unused/1, unused/3, v, owner --)) {
12021200
#if ENABLE_SPECIALIZATION
1203-
if (ADAPTIVE_COUNTER_IS_ZERO(counter)) {
1201+
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
1202+
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
12041203
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
12051204
next_instr--;
12061205
_Py_Specialize_StoreAttr(owner, next_instr, name);
12071206
DISPATCH_SAME_OPARG();
12081207
}
12091208
STAT_INC(STORE_ATTR, deferred);
1210-
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
12111209
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
1212-
#else
1213-
(void)counter; // Unused.
12141210
#endif /* ENABLE_SPECIALIZATION */
12151211
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
12161212
int err = PyObject_SetAttr(owner, name, v);

Python/ceval.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2747,17 +2747,18 @@ _PyUopExecute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject
27472747
_Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive;
27482748
int pc = 0;
27492749
int opcode;
2750-
uint64_t operand;
27512750
int oparg;
2751+
uint64_t operand;
27522752

27532753
for (;;) {
27542754
opcode = self->trace[pc].opcode;
2755+
oparg = self->trace[pc].oparg;
27552756
operand = self->trace[pc].operand;
2756-
oparg = (int)operand;
27572757
DPRINTF(3,
2758-
"%4d: uop %s, operand %" PRIu64 ", stack_level %d\n",
2758+
"%4d: uop %s, oparg %d, operand %" PRIu64 ", stack_level %d\n",
27592759
pc,
27602760
opcode < 256 ? _PyOpcode_OpName[opcode] : _PyOpcode_uop_name[opcode],
2761+
oparg,
27612762
operand,
27622763
(int)(stack_pointer - _PyFrame_Stackbase(frame)));
27632764
pc++;

Python/executor_cases.c.h

Lines changed: 80 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)