Skip to content

gh-87729: specialize LOAD_SUPER_ATTR_METHOD #103809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0a0ebe2
gh-87729: add instruction for faster zero-arg super()
carljm Apr 10, 2023
f14a3bf
add news entry
carljm Apr 13, 2023
5625e73
document LOAD_ZERO_SUPER_ATTR
carljm Apr 13, 2023
0775efe
fix gdb test_wrapper_call
carljm Apr 13, 2023
f229b5b
optimize 2-arg super also
carljm Apr 13, 2023
626999d
fix incompatible assignment
carljm Apr 13, 2023
9384106
Merge branch 'main' into superopt
carljm Apr 13, 2023
92c943b
fix bad first arg
carljm Apr 13, 2023
09804cd
specialize LOAD_SUPER_ATTR for methods
carljm Apr 14, 2023
775ed0f
Apply suggestions from code review
carljm Apr 14, 2023
2077f1a
don't unnecessarily re-find args in error case
carljm Apr 14, 2023
64da49f
Merge branch 'main' into superopt
carljm Apr 14, 2023
4759ad9
update generated cases
carljm Apr 14, 2023
94399c2
fix incompatible types
carljm Apr 14, 2023
b73cff0
Merge branch 'superopt' into superopt_spec
carljm Apr 14, 2023
5627d66
don't double execute descriptor on specialization fail
carljm Apr 14, 2023
5136459
Merge branch 'main' into superopt
carljm Apr 17, 2023
82945b2
review comments
carljm Apr 17, 2023
3a3cb74
update generated cases with new comment
carljm Apr 17, 2023
079c65a
Merge branch 'superopt' into superopt_spec
carljm Apr 17, 2023
e4466a7
simplify oparg & 2 handling
carljm Apr 19, 2023
5c0a21c
Merge branch 'main' into superopt
carljm Apr 19, 2023
f161268
cleanup and clarification
carljm Apr 20, 2023
df442c0
move __class__ special case out of the fast path
carljm Apr 20, 2023
19b8025
Merge branch 'main' into superopt
carljm Apr 24, 2023
0de5bc6
Merge branch 'main' into superopt
carljm Apr 24, 2023
1972ca4
Merge branch 'superopt' into superopt_spec
carljm Apr 24, 2023
6858a6f
re-add comment
carljm Apr 24, 2023
dbe1665
Merge branch 'main' into superopt
carljm Apr 24, 2023
793a69a
Merge branch 'superopt' into superopt_spec
carljm Apr 24, 2023
af807d6
Merge branch 'main' into superopt_spec
carljm Apr 24, 2023
373cbc4
update previous NEWS entry
carljm Apr 24, 2023
3236f45
Merge branch 'main' into superopt_spec
carljm Apr 24, 2023
3d0e51a
credit Vlad
carljm Apr 24, 2023
c96d5c1
Merge branch 'main' into superopt_spec
ambv Apr 25, 2023
ad4008e
Merge branch 'main' into superopt_spec
carljm Apr 25, 2023
66d6271
Merge branch 'main' into superopt_spec
carljm Apr 25, 2023
fc6fcea
simplify LOAD_SUPER_ATTR, let specialization optimize
carljm Apr 25, 2023
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
11 changes: 11 additions & 0 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ typedef struct {

#define INLINE_CACHE_ENTRIES_BINARY_SUBSCR CACHE_ENTRIES(_PyBinarySubscrCache)

typedef struct {
uint16_t counter;
uint16_t class_version[2];
uint16_t self_type_version[2];
uint16_t method[4];
} _PySuperAttrCache;

#define INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR CACHE_ENTRIES(_PySuperAttrCache)

typedef struct {
uint16_t counter;
uint16_t version[2];
Expand Down Expand Up @@ -217,6 +226,8 @@ extern int _PyLineTable_PreviousAddressRange(PyCodeAddressRange *range);

/* Specialization functions */

extern void _Py_Specialize_LoadSuperAttr(PyObject *global_super, PyObject *class, PyObject *self,
_Py_CODEUNIT *instr, PyObject *name, int load_method);
extern void _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr,
PyObject *name);
extern void _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr,
Expand Down
25 changes: 13 additions & 12 deletions Include/internal/pycore_opcode.h

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

2 changes: 2 additions & 0 deletions Include/internal/pycore_typeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ PyObject *_Py_slot_tp_getattr_hook(PyObject *self, PyObject *name);

PyObject *
_PySuper_Lookup(PyTypeObject *su_type, PyObject *su_obj, PyObject *name, int *meth_found);
PyObject *
_PySuper_LookupDescr(PyTypeObject *su_type, PyObject *su_obj, PyObject *name);

#ifdef __cplusplus
}
Expand Down
53 changes: 27 additions & 26 deletions Include/opcode.h

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

5 changes: 3 additions & 2 deletions Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,8 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.12a7 3524 (Shrink the BINARY_SUBSCR caches)
# Python 3.12b1 3525 (Shrink the CALL caches)
# Python 3.12b1 3526 (Add instrumentation support)
# Python 3.12b1 3527 (Optimize super() calls)
# Python 3.12b1 3527 (Add LOAD_SUPER_ATTR)
# Python 3.12b1 3528 (Add LOAD_SUPER_ATTR_METHOD specialization)

# Python 3.13 will start with 3550

Expand All @@ -457,7 +458,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.

MAGIC_NUMBER = (3527).to_bytes(2, 'little') + b'\r\n'
MAGIC_NUMBER = (3528).to_bytes(2, 'little') + b'\r\n'

_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c

Expand Down
9 changes: 9 additions & 0 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@ def pseudo_op(name, op, real_ops):
"FOR_ITER_RANGE",
"FOR_ITER_GEN",
],
"LOAD_SUPER_ATTR": [
"LOAD_SUPER_ATTR_METHOD",
],
"LOAD_ATTR": [
# These potentially push [NULL, bound method] onto the stack.
"LOAD_ATTR_CLASS",
Expand Down Expand Up @@ -426,6 +429,12 @@ def pseudo_op(name, op, real_ops):
"FOR_ITER": {
"counter": 1,
},
"LOAD_SUPER_ATTR": {
"counter": 1,
"class_version": 2,
"self_type_version": 2,
"method": 4,
},
"LOAD_ATTR": {
"counter": 1,
"version": 2,
Expand Down
23 changes: 23 additions & 0 deletions Lib/test/test_opcache.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
import unittest


class TestLoadSuperAttrCache(unittest.TestCase):
def test_descriptor_not_double_executed_on_spec_fail(self):
calls = []
class Descriptor:
def __get__(self, instance, owner):
calls.append((instance, owner))
return lambda: 1

class C:
d = Descriptor()

class D(C):
def f(self):
return super().d()

d = D()

self.assertEqual(d.f(), 1) # warmup
calls.clear()
self.assertEqual(d.f(), 1) # try to specialize
self.assertEqual(calls, [(d, D)])


class TestLoadAttrCache(unittest.TestCase):
def test_descriptor_added_after_optimization(self):
class Descriptor:
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
Add :opcode:`LOAD_SUPER_ATTR` to speed up ``super().meth()`` and ``super().attr`` calls.
Add :opcode:`LOAD_SUPER_ATTR` (and a specialization for ``super().method()``) to
speed up ``super().method()`` and ``super().attr``. This makes
``super().method()`` roughly 2.3x faster and brings it within 20% of the
performance of a simple method call. Patch by Vladimir Matveev and Carl Meyer.
Loading