mirror of
https://github.com/python/cpython.git
synced 2025-07-19 09:15:34 +00:00
bpo-46841: Move the cache for LOAD_GLOBAL
inline. (GH-31575)
This commit is contained in:
parent
da7d99a4de
commit
4558af5a8f
10 changed files with 284 additions and 232 deletions
|
@ -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)
|
||||
|
|
|
@ -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)).
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue