Skip to content

Commit f5a3d91

Browse files
authored
gh-98831: Support conditional effects; use for LOAD_ATTR (#101333)
1 parent c4170c3 commit f5a3d91

File tree

6 files changed

+194
-120
lines changed

6 files changed

+194
-120
lines changed

Python/bytecodes.c

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
// Dummy variables for stack effects.
5353
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
54-
static PyObject *container, *start, *stop, *v, *lhs, *rhs;
54+
static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2;
5555
static PyObject *list, *tuple, *dict, *owner, *set, *str, *tup, *map, *keys;
5656
static PyObject *exit_func, *lasti, *val, *retval, *obj, *iter;
5757
static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc;
@@ -1438,13 +1438,11 @@ dummy_func(
14381438
PREDICT(JUMP_BACKWARD);
14391439
}
14401440

1441-
// error: LOAD_ATTR has irregular stack effect
1442-
inst(LOAD_ATTR) {
1441+
inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) {
14431442
#if ENABLE_SPECIALIZATION
14441443
_PyAttrCache *cache = (_PyAttrCache *)next_instr;
14451444
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
14461445
assert(cframe.use_tracing == 0);
1447-
PyObject *owner = TOP();
14481446
PyObject *name = GETITEM(names, oparg>>1);
14491447
next_instr--;
14501448
_Py_Specialize_LoadAttr(owner, next_instr, name);
@@ -1454,26 +1452,18 @@ dummy_func(
14541452
DECREMENT_ADAPTIVE_COUNTER(cache->counter);
14551453
#endif /* ENABLE_SPECIALIZATION */
14561454
PyObject *name = GETITEM(names, oparg >> 1);
1457-
PyObject *owner = TOP();
14581455
if (oparg & 1) {
1459-
/* Designed to work in tandem with CALL. */
1456+
/* Designed to work in tandem with CALL, pushes two values. */
14601457
PyObject* meth = NULL;
1461-
1462-
int meth_found = _PyObject_GetMethod(owner, name, &meth);
1463-
1464-
if (meth == NULL) {
1465-
/* Most likely attribute wasn't found. */
1466-
goto error;
1467-
}
1468-
1469-
if (meth_found) {
1458+
if (_PyObject_GetMethod(owner, name, &meth)) {
14701459
/* We can bypass temporary bound method object.
14711460
meth is unbound method and obj is self.
14721461
14731462
meth | self | arg1 | ... | argN
14741463
*/
1475-
SET_TOP(meth);
1476-
PUSH(owner); // self
1464+
assert(meth != NULL); // No errors on this branch
1465+
res2 = meth;
1466+
res = owner; // Transfer ownership
14771467
}
14781468
else {
14791469
/* meth is not an unbound method (but a regular attr, or
@@ -1483,20 +1473,18 @@ dummy_func(
14831473
14841474
NULL | meth | arg1 | ... | argN
14851475
*/
1486-
SET_TOP(NULL);
14871476
Py_DECREF(owner);
1488-
PUSH(meth);
1477+
ERROR_IF(meth == NULL, error);
1478+
res2 = NULL;
1479+
res = meth;
14891480
}
14901481
}
14911482
else {
1492-
PyObject *res = PyObject_GetAttr(owner, name);
1493-
if (res == NULL) {
1494-
goto error;
1495-
}
1483+
/* Classic, pushes one value. */
1484+
res = PyObject_GetAttr(owner, name);
14961485
Py_DECREF(owner);
1497-
SET_TOP(res);
1486+
ERROR_IF(res == NULL, error);
14981487
}
1499-
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR);
15001488
}
15011489

15021490
// error: LOAD_ATTR has irregular stack effect

Python/generated_cases.c.h

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

Python/opcode_metadata.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ _PyOpcode_num_popped(int opcode, int oparg) {
185185
case MAP_ADD:
186186
return 2;
187187
case LOAD_ATTR:
188-
return -1;
188+
return 1;
189189
case LOAD_ATTR_INSTANCE_VALUE:
190190
return -1;
191191
case LOAD_ATTR_MODULE:
@@ -531,7 +531,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) {
531531
case MAP_ADD:
532532
return 0;
533533
case LOAD_ATTR:
534-
return -1;
534+
return ((oparg & 1) ? 1 : 0) + 1;
535535
case LOAD_ATTR_INSTANCE_VALUE:
536536
return -1;
537537
case LOAD_ATTR_MODULE:
@@ -694,7 +694,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) {
694694
}
695695
#endif
696696
enum Direction { DIR_NONE, DIR_READ, DIR_WRITE };
697-
enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 };
697+
enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBC00000000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 };
698698
struct opcode_metadata {
699699
enum Direction dir_op1;
700700
enum Direction dir_op2;
@@ -791,7 +791,7 @@ struct opcode_metadata {
791791
[DICT_UPDATE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
792792
[DICT_MERGE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
793793
[MAP_ADD] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
794-
[LOAD_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
794+
[LOAD_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 },
795795
[LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
796796
[LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
797797
[LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },

0 commit comments

Comments
 (0)