mirror of https://github.com/python/cpython
Shrink the LOAD_METHOD cache by one codeunit. (#93537)
This commit is contained in:
parent
75ceae05c1
commit
f012df706c
|
@ -65,7 +65,6 @@ typedef struct {
|
|||
typedef struct {
|
||||
_Py_CODEUNIT counter;
|
||||
_Py_CODEUNIT type_version[2];
|
||||
_Py_CODEUNIT dict_offset;
|
||||
_Py_CODEUNIT keys_version[2];
|
||||
_Py_CODEUNIT descr[4];
|
||||
} _PyLoadMethodCache;
|
||||
|
|
|
@ -49,7 +49,7 @@ const uint8_t _PyOpcode_Caches[256] = {
|
|||
[COMPARE_OP] = 2,
|
||||
[LOAD_GLOBAL] = 5,
|
||||
[BINARY_OP] = 1,
|
||||
[LOAD_METHOD] = 10,
|
||||
[LOAD_METHOD] = 9,
|
||||
[CALL] = 4,
|
||||
};
|
||||
|
||||
|
|
|
@ -407,6 +407,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Python 3.12a1 3500 (Remove PRECALL opcode)
|
||||
# Python 3.12a1 3501 (YIELD_VALUE oparg == stack_depth)
|
||||
# Python 3.12a1 3502 (LOAD_FAST_CHECK, no NULL-check in LOAD_FAST)
|
||||
# Python 3.12a1 3503 (Shrink LOAD_METHOD cache)
|
||||
|
||||
# Python 3.13 will start with 3550
|
||||
|
||||
|
@ -420,7 +421,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
||||
# in PC/launcher.c must also be updated.
|
||||
|
||||
MAGIC_NUMBER = (3502).to_bytes(2, 'little') + b'\r\n'
|
||||
MAGIC_NUMBER = (3503).to_bytes(2, 'little') + b'\r\n'
|
||||
|
||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||
|
||||
|
|
|
@ -383,7 +383,6 @@ _cache_format = {
|
|||
"LOAD_METHOD": {
|
||||
"counter": 1,
|
||||
"type_version": 2,
|
||||
"dict_offset": 1,
|
||||
"keys_version": 2,
|
||||
"descr": 4,
|
||||
},
|
||||
|
|
|
@ -1047,7 +1047,7 @@ class DisTests(DisTestBase):
|
|||
for cache in caches:
|
||||
self.assertRegex(cache, pattern)
|
||||
self.assertEqual(caches.count(""), 8)
|
||||
self.assertEqual(len(caches), 23)
|
||||
self.assertEqual(len(caches), 22)
|
||||
|
||||
|
||||
class DisWithFileTests(DisTests):
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Reduce the size of the inline cache for ``LOAD_METHOD`` by 2 bytes.
|
|
@ -4581,12 +4581,9 @@ handle_eval_breaker:
|
|||
DEOPT_IF(self_cls->tp_version_tag != read_u32(cache->type_version),
|
||||
LOAD_METHOD);
|
||||
/* Treat index as a signed 16 bit value */
|
||||
int dictoffset = *(int16_t *)&cache->dict_offset;
|
||||
int dictoffset = self_cls->tp_dictoffset;
|
||||
assert(dictoffset > 0);
|
||||
PyDictObject **dictptr = (PyDictObject**)(((char *)self)+dictoffset);
|
||||
assert(
|
||||
dictoffset == MANAGED_DICT_OFFSET ||
|
||||
(dictoffset == self_cls->tp_dictoffset && dictoffset > 0)
|
||||
);
|
||||
PyDictObject *dict = *dictptr;
|
||||
DEOPT_IF(dict == NULL, LOAD_METHOD);
|
||||
DEOPT_IF(dict->ma_keys->dk_version != read_u32(cache->keys_version),
|
||||
|
@ -4628,9 +4625,9 @@ handle_eval_breaker:
|
|||
_PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr;
|
||||
uint32_t type_version = read_u32(cache->type_version);
|
||||
DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_METHOD);
|
||||
int dictoffset = cache->dict_offset;
|
||||
int dictoffset = self_cls->tp_dictoffset;
|
||||
assert(dictoffset > 0);
|
||||
PyObject *dict = *(PyObject **)((char *)self + dictoffset);
|
||||
assert(dictoffset == self_cls->tp_dictoffset && dictoffset > 0);
|
||||
/* This object has a __dict__, just not yet created */
|
||||
DEOPT_IF(dict != NULL, LOAD_METHOD);
|
||||
STAT_INC(LOAD_METHOD, hit);
|
||||
|
|
|
@ -986,7 +986,7 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (dictkind == MANAGED_VALUES || dictkind == MANAGED_DICT || dictkind == OFFSET_DICT) {
|
||||
if (dictkind == MANAGED_VALUES || dictkind == OFFSET_DICT) {
|
||||
Py_ssize_t index = _PyDictKeys_StringLookup(keys, name);
|
||||
if (index != DKIX_EMPTY) {
|
||||
SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_LOAD_METHOD_IS_ATTR);
|
||||
|
@ -1007,17 +1007,14 @@ _Py_Specialize_LoadMethod(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
|
|||
_Py_SET_OPCODE(*instr, LOAD_METHOD_WITH_VALUES);
|
||||
break;
|
||||
case MANAGED_DICT:
|
||||
*(int16_t *)&cache->dict_offset = (int16_t)MANAGED_DICT_OFFSET;
|
||||
_Py_SET_OPCODE(*instr, LOAD_METHOD_WITH_DICT);
|
||||
break;
|
||||
SPECIALIZATION_FAIL(LOAD_METHOD, SPEC_FAIL_LOAD_METHOD_HAS_MANAGED_DICT);
|
||||
goto fail;
|
||||
case OFFSET_DICT:
|
||||
assert(owner_cls->tp_dictoffset > 0 && owner_cls->tp_dictoffset <= INT16_MAX);
|
||||
cache->dict_offset = (uint16_t)owner_cls->tp_dictoffset;
|
||||
_Py_SET_OPCODE(*instr, LOAD_METHOD_WITH_DICT);
|
||||
break;
|
||||
case LAZY_DICT:
|
||||
assert(owner_cls->tp_dictoffset > 0 && owner_cls->tp_dictoffset <= INT16_MAX);
|
||||
cache->dict_offset = (uint16_t)owner_cls->tp_dictoffset;
|
||||
_Py_SET_OPCODE(*instr, LOAD_METHOD_LAZY_DICT);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue