Skip to content

Commit

Permalink
pythongh-87729: specialize LOAD_SUPER_ATTR_METHOD (python#103809)
Browse files Browse the repository at this point in the history
  • Loading branch information
carljm committed Apr 25, 2023
1 parent cef542c commit ef25feb
Show file tree
Hide file tree
Showing 14 changed files with 540 additions and 358 deletions.
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

0 comments on commit ef25feb

Please sign in to comment.