summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2022-02-28 12:56:29 (GMT)
committerGitHub <noreply@github.com>2022-02-28 12:56:29 (GMT)
commit4558af5a8f8e56a9b0dc11f6e834c47e0fd05f9e (patch)
tree32365218607a600a23378350b533a307474cb628 /Python
parentda7d99a4de72aac8d436cecedf16ab2676f9b785 (diff)
downloadcpython-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.c38
-rw-r--r--Python/compile.c4
-rw-r--r--Python/specialize.c28
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;
}