diff options
author | Mark Shannon <mark@hotpy.org> | 2022-02-28 12:56:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-28 12:56:29 (GMT) |
commit | 4558af5a8f8e56a9b0dc11f6e834c47e0fd05f9e (patch) | |
tree | 32365218607a600a23378350b533a307474cb628 /Python | |
parent | da7d99a4de72aac8d436cecedf16ab2676f9b785 (diff) | |
download | cpython-4558af5a8f8e56a9b0dc11f6e834c47e0fd05f9e.zip cpython-4558af5a8f8e56a9b0dc11f6e834c47e0fd05f9e.tar.gz cpython-4558af5a8f8e56a9b0dc11f6e834c47e0fd05f9e.tar.bz2 |
bpo-46841: Move the cache for `LOAD_GLOBAL` inline. (GH-31575)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 38 | ||||
-rw-r--r-- | Python/compile.c | 4 | ||||
-rw-r--r-- | Python/specialize.c | 28 |
3 files changed, 38 insertions, 32 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index fe75782..6f1165b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2993,25 +2993,26 @@ handle_eval_breaker: } } } + /* Skip over inline cache */ + JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); PUSH(v); DISPATCH(); } TARGET(LOAD_GLOBAL_ADAPTIVE) { assert(cframe.use_tracing == 0); - SpecializedCacheEntry *cache = GET_CACHE(); - if (cache->adaptive.counter == 0) { - PyObject *name = GETITEM(names, cache->adaptive.original_oparg); + uint16_t counter = *next_instr; + if (counter == 0) { + PyObject *name = GETITEM(names, oparg); next_instr--; - if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name, cache) < 0) { + if (_Py_Specialize_LoadGlobal(GLOBALS(), BUILTINS(), next_instr, name) < 0) { goto error; } DISPATCH(); } else { STAT_INC(LOAD_GLOBAL, deferred); - cache->adaptive.counter--; - oparg = cache->adaptive.original_oparg; + *next_instr = counter-1; JUMP_TO_INSTRUCTION(LOAD_GLOBAL); } } @@ -3020,13 +3021,13 @@ handle_eval_breaker: assert(cframe.use_tracing == 0); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); PyDictObject *dict = (PyDictObject *)GLOBALS(); - SpecializedCacheEntry *caches = GET_CACHE(); - _PyAdaptiveEntry *cache0 = &caches[0].adaptive; - _PyLoadGlobalCache *cache1 = &caches[-1].load_global; - DEOPT_IF(dict->ma_keys->dk_version != cache1->module_keys_version, LOAD_GLOBAL); - PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + cache0->index; + _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; + uint32_t version = read32(&cache->module_keys_version); + DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); + PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + cache->index; PyObject *res = ep->me_value; DEOPT_IF(res == NULL, LOAD_GLOBAL); + JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); STAT_INC(LOAD_GLOBAL, hit); Py_INCREF(res); PUSH(res); @@ -3039,14 +3040,15 @@ handle_eval_breaker: DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL); PyDictObject *mdict = (PyDictObject *)GLOBALS(); PyDictObject *bdict = (PyDictObject *)BUILTINS(); - SpecializedCacheEntry *caches = GET_CACHE(); - _PyAdaptiveEntry *cache0 = &caches[0].adaptive; - _PyLoadGlobalCache *cache1 = &caches[-1].load_global; - DEOPT_IF(mdict->ma_keys->dk_version != cache1->module_keys_version, LOAD_GLOBAL); - DEOPT_IF(bdict->ma_keys->dk_version != cache1->builtin_keys_version, LOAD_GLOBAL); - PyDictKeyEntry *ep = DK_ENTRIES(bdict->ma_keys) + cache0->index; + _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; + uint32_t mod_version = read32(&cache->module_keys_version); + uint16_t bltn_version = cache->builtin_keys_version; + DEOPT_IF(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL); + DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL); + PyDictKeyEntry *ep = DK_ENTRIES(bdict->ma_keys) + cache->index; PyObject *res = ep->me_value; DEOPT_IF(res == NULL, LOAD_GLOBAL); + JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); STAT_INC(LOAD_GLOBAL, hit); Py_INCREF(res); PUSH(res); @@ -5594,7 +5596,7 @@ opname ## _miss: \ MISS_WITH_CACHE(LOAD_ATTR) MISS_WITH_CACHE(STORE_ATTR) -MISS_WITH_CACHE(LOAD_GLOBAL) +MISS_WITH_INLINE_CACHE(LOAD_GLOBAL) MISS_WITH_CACHE(LOAD_METHOD) MISS_WITH_CACHE(PRECALL) MISS_WITH_CACHE(CALL) diff --git a/Python/compile.c b/Python/compile.c index 8ae4d44..ea9c3c8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -31,7 +31,7 @@ #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_symtable.h" // PySTEntryObject -#define NEED_OPCODE_JUMP_TABLES +#define NEED_OPCODE_TABLES #include "opcode.h" // EXTENDED_ARG @@ -108,7 +108,7 @@ typedef struct exceptstack { #define MASK_LOW_LOG_BITS 31 static inline int -is_bit_set_in_table(uint32_t *table, int bitindex) { +is_bit_set_in_table(const uint32_t *table, int bitindex) { /* Is the relevant bit set in the relevant word? */ /* 256 bits fit into 8 32-bits words. * Word is indexed by (bitindex>>ln(size of int in bits)). diff --git a/Python/specialize.c b/Python/specialize.c index b88c5d5..38907f6 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -59,7 +59,6 @@ static uint8_t adaptive_opcodes[256] = { /* The number of cache entries required for a "family" of instructions. */ static uint8_t cache_requirements[256] = { [LOAD_ATTR] = 1, // _PyAdaptiveEntry - [LOAD_GLOBAL] = 2, /* _PyAdaptiveEntry and _PyLoadGlobalCache */ [LOAD_METHOD] = 3, /* _PyAdaptiveEntry, _PyAttrCache and _PyObjectCache */ [BINARY_SUBSCR] = 2, /* _PyAdaptiveEntry, _PyObjectCache */ [STORE_SUBSCR] = 0, @@ -1208,11 +1207,12 @@ fail: int _Py_Specialize_LoadGlobal( PyObject *globals, PyObject *builtins, - _Py_CODEUNIT *instr, PyObject *name, - SpecializedCacheEntry *cache) + _Py_CODEUNIT *instr, PyObject *name) { - _PyAdaptiveEntry *cache0 = &cache->adaptive; - _PyLoadGlobalCache *cache1 = &cache[-1].load_global; + assert(_PyOpcode_InlineCacheEntries[LOAD_GLOBAL] == + INLINE_CACHE_ENTRIES_LOAD_GLOBAL); + /* Use inline cache */ + _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)(instr + 1); assert(PyUnicode_CheckExact(name)); if (!PyDict_CheckExact(globals)) { goto fail; @@ -1231,8 +1231,8 @@ _Py_Specialize_LoadGlobal( if (keys_version == 0) { goto fail; } - cache1->module_keys_version = keys_version; - cache0->index = (uint16_t)index; + cache->index = (uint16_t)index; + write32(&cache->module_keys_version, keys_version); *instr = _Py_MAKECODEUNIT(LOAD_GLOBAL_MODULE, _Py_OPARG(*instr)); goto success; } @@ -1258,20 +1258,24 @@ _Py_Specialize_LoadGlobal( SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_VERSIONS); goto fail; } - cache1->module_keys_version = globals_version; - cache1->builtin_keys_version = builtins_version; - cache0->index = (uint16_t)index; + if (builtins_version > UINT16_MAX) { + SPECIALIZATION_FAIL(LOAD_GLOBAL, SPEC_FAIL_OUT_OF_RANGE); + goto fail; + } + cache->index = (uint16_t)index; + write32(&cache->module_keys_version, globals_version); + cache->builtin_keys_version = (uint16_t)builtins_version; *instr = _Py_MAKECODEUNIT(LOAD_GLOBAL_BUILTIN, _Py_OPARG(*instr)); goto success; fail: STAT_INC(LOAD_GLOBAL, failure); assert(!PyErr_Occurred()); - cache_backoff(cache0); + cache->counter = ADAPTIVE_CACHE_BACKOFF; return 0; success: STAT_INC(LOAD_GLOBAL, success); assert(!PyErr_Occurred()); - cache0->counter = initial_counter_value(); + cache->counter = initial_counter_value(); return 0; } |