Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Include/internal/pycore_opcode_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Include/internal/pycore_uop_ids.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,26 @@ class C:
self.assertNotIn("_POP_TOP", uops)
self.assertIn("_POP_TOP_NOP", uops)

def test_store_attr_with_hint(self):
def testfunc(n):
class C:
pass
c = C()
for i in range(_testinternalcapi.SHARED_KEYS_MAX_SIZE - 1):
setattr(c, f"_{i}", None)

for i in range(n):
c.x = i
return c.x
res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
self.assertEqual(res, TIER2_THRESHOLD - 1)
self.assertIsNotNone(ex)
uops = get_opnames(ex)

self.assertIn("_STORE_ATTR_WITH_HINT", uops)
self.assertNotIn("_POP_TOP", uops)
self.assertIn("_POP_TOP_NOP", uops)

def test_store_subscr_int(self):
def testfunc(n):
l = [0, 0, 0, 0]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Eliminate redundant refcounting from ``_STORE_ATTR_WITH_HINT``.
8 changes: 5 additions & 3 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2601,7 +2601,7 @@ dummy_func(
_STORE_ATTR_INSTANCE_VALUE +
POP_TOP;

op(_STORE_ATTR_WITH_HINT, (hint/1, value, owner --)) {
op(_STORE_ATTR_WITH_HINT, (hint/1, value, owner -- o)) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
assert(Py_TYPE(owner_o)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
PyDictObject *dict = _PyObject_GetManagedDict(owner_o);
Expand Down Expand Up @@ -2631,14 +2631,16 @@ dummy_func(
// old_value should be DECREFed after GC track checking is done, if not, it could raise a segmentation fault,
// when dict only holds the strong reference to value in ep->me_value.
STAT_INC(STORE_ATTR, hit);
PyStackRef_CLOSE(owner);
o = owner;
DEAD(owner);
Py_XDECREF(old_value);
}

macro(STORE_ATTR_WITH_HINT) =
unused/1 +
_GUARD_TYPE_VERSION +
_STORE_ATTR_WITH_HINT;
_STORE_ATTR_WITH_HINT +
POP_TOP;

op(_STORE_ATTR_SLOT, (index/1, value, owner --)) {
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
Expand Down
14 changes: 9 additions & 5 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 13 additions & 2 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ dummy_func(void) {
o = owner;
}

op(_STORE_ATTR_WITH_HINT, (hint/1, value, owner -- o)) {
(void)value;
o = owner;
}

op(_STORE_FAST, (value --)) {
GETLOCAL(oparg) = value;
}
Expand Down
13 changes: 11 additions & 2 deletions Python/optimizer_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading