gh-98831: Modernize the LOAD_GLOBAL family (#101502)

This commit is contained in:
Guido van Rossum 2023-02-01 13:12:49 -08:00 committed by GitHub
parent eda60916bc
commit ae9b38f424
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 77 deletions

View file

@ -1068,8 +1068,13 @@ dummy_func(
} }
} }
// error: LOAD_GLOBAL has irregular stack effect family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
inst(LOAD_GLOBAL) { LOAD_GLOBAL,
LOAD_GLOBAL_MODULE,
LOAD_GLOBAL_BUILTIN,
};
inst(LOAD_GLOBAL, (unused/1, unused/1, unused/2, unused/1 -- null if (oparg & 1), v)) {
#if ENABLE_SPECIALIZATION #if ENABLE_SPECIALIZATION
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@ -1082,10 +1087,7 @@ dummy_func(
STAT_INC(LOAD_GLOBAL, deferred); STAT_INC(LOAD_GLOBAL, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter); DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */ #endif /* ENABLE_SPECIALIZATION */
int push_null = oparg & 1;
PEEK(0) = NULL;
PyObject *name = GETITEM(names, oparg>>1); PyObject *name = GETITEM(names, oparg>>1);
PyObject *v;
if (PyDict_CheckExact(GLOBALS()) if (PyDict_CheckExact(GLOBALS())
&& PyDict_CheckExact(BUILTINS())) && PyDict_CheckExact(BUILTINS()))
{ {
@ -1099,7 +1101,7 @@ dummy_func(
format_exc_check_arg(tstate, PyExc_NameError, format_exc_check_arg(tstate, PyExc_NameError,
NAME_ERROR_MSG, name); NAME_ERROR_MSG, name);
} }
goto error; ERROR_IF(true, error);
} }
Py_INCREF(v); Py_INCREF(v);
} }
@ -1109,9 +1111,7 @@ dummy_func(
/* namespace 1: globals */ /* namespace 1: globals */
v = PyObject_GetItem(GLOBALS(), name); v = PyObject_GetItem(GLOBALS(), name);
if (v == NULL) { if (v == NULL) {
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error);
goto error;
}
_PyErr_Clear(tstate); _PyErr_Clear(tstate);
/* namespace 2: builtins */ /* namespace 2: builtins */
@ -1122,58 +1122,42 @@ dummy_func(
tstate, PyExc_NameError, tstate, PyExc_NameError,
NAME_ERROR_MSG, name); NAME_ERROR_MSG, name);
} }
goto error; ERROR_IF(true, error);
} }
} }
} }
/* Skip over inline cache */ null = NULL;
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
STACK_GROW(push_null);
PUSH(v);
} }
// error: LOAD_GLOBAL has irregular stack effect inst(LOAD_GLOBAL_MODULE, (unused/1, index/1, version/2, unused/1 -- null if (oparg & 1), res)) {
inst(LOAD_GLOBAL_MODULE) {
assert(cframe.use_tracing == 0); assert(cframe.use_tracing == 0);
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
PyDictObject *dict = (PyDictObject *)GLOBALS(); PyDictObject *dict = (PyDictObject *)GLOBALS();
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
uint32_t version = read_u32(cache->module_keys_version);
DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
assert(DK_IS_UNICODE(dict->ma_keys)); assert(DK_IS_UNICODE(dict->ma_keys));
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
PyObject *res = entries[cache->index].me_value; res = entries[index].me_value;
DEOPT_IF(res == NULL, LOAD_GLOBAL); DEOPT_IF(res == NULL, LOAD_GLOBAL);
int push_null = oparg & 1; Py_INCREF(res);
PEEK(0) = NULL;
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
STAT_INC(LOAD_GLOBAL, hit); STAT_INC(LOAD_GLOBAL, hit);
STACK_GROW(push_null+1); null = NULL;
SET_TOP(Py_NewRef(res));
} }
// error: LOAD_GLOBAL has irregular stack effect inst(LOAD_GLOBAL_BUILTIN, (unused/1, index/1, mod_version/2, bltn_version/1 -- null if (oparg & 1), res)) {
inst(LOAD_GLOBAL_BUILTIN) {
assert(cframe.use_tracing == 0); assert(cframe.use_tracing == 0);
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);
PyDictObject *mdict = (PyDictObject *)GLOBALS(); PyDictObject *mdict = (PyDictObject *)GLOBALS();
PyDictObject *bdict = (PyDictObject *)BUILTINS(); PyDictObject *bdict = (PyDictObject *)BUILTINS();
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
uint32_t mod_version = read_u32(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(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL);
DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL); DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL);
assert(DK_IS_UNICODE(bdict->ma_keys)); assert(DK_IS_UNICODE(bdict->ma_keys));
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);
PyObject *res = entries[cache->index].me_value; res = entries[index].me_value;
DEOPT_IF(res == NULL, LOAD_GLOBAL); DEOPT_IF(res == NULL, LOAD_GLOBAL);
int push_null = oparg & 1; Py_INCREF(res);
PEEK(0) = NULL;
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
STAT_INC(LOAD_GLOBAL, hit); STAT_INC(LOAD_GLOBAL, hit);
STACK_GROW(push_null+1); null = NULL;
SET_TOP(Py_NewRef(res));
} }
inst(DELETE_FAST, (--)) { inst(DELETE_FAST, (--)) {
@ -3212,9 +3196,6 @@ family(call, INLINE_CACHE_ENTRIES_CALL) = {
family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = { family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = {
FOR_ITER, FOR_ITER_LIST, FOR_ITER, FOR_ITER_LIST,
FOR_ITER_RANGE }; FOR_ITER_RANGE };
family(load_global, INLINE_CACHE_ENTRIES_LOAD_GLOBAL) = {
LOAD_GLOBAL, LOAD_GLOBAL_BUILTIN,
LOAD_GLOBAL_MODULE };
family(store_fast) = { STORE_FAST, STORE_FAST__LOAD_FAST, STORE_FAST__STORE_FAST }; family(store_fast) = { STORE_FAST, STORE_FAST__LOAD_FAST, STORE_FAST__STORE_FAST };
family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = { family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = {
UNPACK_SEQUENCE, UNPACK_SEQUENCE_LIST, UNPACK_SEQUENCE, UNPACK_SEQUENCE_LIST,

View file

@ -1311,6 +1311,9 @@
TARGET(LOAD_GLOBAL) { TARGET(LOAD_GLOBAL) {
PREDICTED(LOAD_GLOBAL); PREDICTED(LOAD_GLOBAL);
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 5, "incorrect cache size");
PyObject *null = NULL;
PyObject *v;
#if ENABLE_SPECIALIZATION #if ENABLE_SPECIALIZATION
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr; _PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) { if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
@ -1323,10 +1326,7 @@
STAT_INC(LOAD_GLOBAL, deferred); STAT_INC(LOAD_GLOBAL, deferred);
DECREMENT_ADAPTIVE_COUNTER(cache->counter); DECREMENT_ADAPTIVE_COUNTER(cache->counter);
#endif /* ENABLE_SPECIALIZATION */ #endif /* ENABLE_SPECIALIZATION */
int push_null = oparg & 1;
PEEK(0) = NULL;
PyObject *name = GETITEM(names, oparg>>1); PyObject *name = GETITEM(names, oparg>>1);
PyObject *v;
if (PyDict_CheckExact(GLOBALS()) if (PyDict_CheckExact(GLOBALS())
&& PyDict_CheckExact(BUILTINS())) && PyDict_CheckExact(BUILTINS()))
{ {
@ -1340,7 +1340,7 @@
format_exc_check_arg(tstate, PyExc_NameError, format_exc_check_arg(tstate, PyExc_NameError,
NAME_ERROR_MSG, name); NAME_ERROR_MSG, name);
} }
goto error; if (true) goto error;
} }
Py_INCREF(v); Py_INCREF(v);
} }
@ -1350,9 +1350,7 @@
/* namespace 1: globals */ /* namespace 1: globals */
v = PyObject_GetItem(GLOBALS(), name); v = PyObject_GetItem(GLOBALS(), name);
if (v == NULL) { if (v == NULL) {
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) { if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error;
goto error;
}
_PyErr_Clear(tstate); _PyErr_Clear(tstate);
/* namespace 2: builtins */ /* namespace 2: builtins */
@ -1363,58 +1361,68 @@
tstate, PyExc_NameError, tstate, PyExc_NameError,
NAME_ERROR_MSG, name); NAME_ERROR_MSG, name);
} }
goto error; if (true) goto error;
} }
} }
} }
/* Skip over inline cache */ null = NULL;
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL); STACK_GROW(1);
STACK_GROW(push_null); STACK_GROW(((oparg & 1) ? 1 : 0));
PUSH(v); POKE(1, v);
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), null); }
JUMPBY(5);
DISPATCH(); DISPATCH();
} }
TARGET(LOAD_GLOBAL_MODULE) { TARGET(LOAD_GLOBAL_MODULE) {
PyObject *null = NULL;
PyObject *res;
uint16_t index = read_u16(&next_instr[1].cache);
uint32_t version = read_u32(&next_instr[2].cache);
assert(cframe.use_tracing == 0); assert(cframe.use_tracing == 0);
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
PyDictObject *dict = (PyDictObject *)GLOBALS(); PyDictObject *dict = (PyDictObject *)GLOBALS();
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
uint32_t version = read_u32(cache->module_keys_version);
DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL); DEOPT_IF(dict->ma_keys->dk_version != version, LOAD_GLOBAL);
assert(DK_IS_UNICODE(dict->ma_keys)); assert(DK_IS_UNICODE(dict->ma_keys));
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
PyObject *res = entries[cache->index].me_value; res = entries[index].me_value;
DEOPT_IF(res == NULL, LOAD_GLOBAL); DEOPT_IF(res == NULL, LOAD_GLOBAL);
int push_null = oparg & 1; Py_INCREF(res);
PEEK(0) = NULL;
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
STAT_INC(LOAD_GLOBAL, hit); STAT_INC(LOAD_GLOBAL, hit);
STACK_GROW(push_null+1); null = NULL;
SET_TOP(Py_NewRef(res)); STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
POKE(1, res);
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), null); }
JUMPBY(5);
DISPATCH(); DISPATCH();
} }
TARGET(LOAD_GLOBAL_BUILTIN) { TARGET(LOAD_GLOBAL_BUILTIN) {
PyObject *null = NULL;
PyObject *res;
uint16_t index = read_u16(&next_instr[1].cache);
uint32_t mod_version = read_u32(&next_instr[2].cache);
uint16_t bltn_version = read_u16(&next_instr[4].cache);
assert(cframe.use_tracing == 0); assert(cframe.use_tracing == 0);
DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(GLOBALS()), LOAD_GLOBAL);
DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL); DEOPT_IF(!PyDict_CheckExact(BUILTINS()), LOAD_GLOBAL);
PyDictObject *mdict = (PyDictObject *)GLOBALS(); PyDictObject *mdict = (PyDictObject *)GLOBALS();
PyDictObject *bdict = (PyDictObject *)BUILTINS(); PyDictObject *bdict = (PyDictObject *)BUILTINS();
_PyLoadGlobalCache *cache = (_PyLoadGlobalCache *)next_instr;
uint32_t mod_version = read_u32(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(mdict->ma_keys->dk_version != mod_version, LOAD_GLOBAL);
DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL); DEOPT_IF(bdict->ma_keys->dk_version != bltn_version, LOAD_GLOBAL);
assert(DK_IS_UNICODE(bdict->ma_keys)); assert(DK_IS_UNICODE(bdict->ma_keys));
PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys); PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);
PyObject *res = entries[cache->index].me_value; res = entries[index].me_value;
DEOPT_IF(res == NULL, LOAD_GLOBAL); DEOPT_IF(res == NULL, LOAD_GLOBAL);
int push_null = oparg & 1; Py_INCREF(res);
PEEK(0) = NULL;
JUMPBY(INLINE_CACHE_ENTRIES_LOAD_GLOBAL);
STAT_INC(LOAD_GLOBAL, hit); STAT_INC(LOAD_GLOBAL, hit);
STACK_GROW(push_null+1); null = NULL;
SET_TOP(Py_NewRef(res)); STACK_GROW(1);
STACK_GROW(((oparg & 1) ? 1 : 0));
POKE(1, res);
if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), null); }
JUMPBY(5);
DISPATCH(); DISPATCH();
} }

View file

@ -141,11 +141,11 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
case LOAD_NAME: case LOAD_NAME:
return 0; return 0;
case LOAD_GLOBAL: case LOAD_GLOBAL:
return -1; return 0;
case LOAD_GLOBAL_MODULE: case LOAD_GLOBAL_MODULE:
return -1; return 0;
case LOAD_GLOBAL_BUILTIN: case LOAD_GLOBAL_BUILTIN:
return -1; return 0;
case DELETE_FAST: case DELETE_FAST:
return 0; return 0;
case MAKE_CELL: case MAKE_CELL:
@ -487,11 +487,11 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
case LOAD_NAME: case LOAD_NAME:
return 1; return 1;
case LOAD_GLOBAL: case LOAD_GLOBAL:
return -1; return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_GLOBAL_MODULE: case LOAD_GLOBAL_MODULE:
return -1; return ((oparg & 1) ? 1 : 0) + 1;
case LOAD_GLOBAL_BUILTIN: case LOAD_GLOBAL_BUILTIN:
return -1; return ((oparg & 1) ? 1 : 0) + 1;
case DELETE_FAST: case DELETE_FAST:
return 0; return 0;
case MAKE_CELL: case MAKE_CELL:
@ -694,7 +694,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
} }
#endif #endif
enum Direction { DIR_NONE, DIR_READ, DIR_WRITE }; enum Direction { DIR_NONE, DIR_READ, DIR_WRITE };
enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBC00000000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 }; enum InstructionFormat { INSTR_FMT_IB, INSTR_FMT_IBC, INSTR_FMT_IBC0, INSTR_FMT_IBC000, INSTR_FMT_IBC0000, INSTR_FMT_IBC00000000, INSTR_FMT_IBIB, INSTR_FMT_IX, INSTR_FMT_IXC, INSTR_FMT_IXC000 };
struct opcode_metadata { struct opcode_metadata {
enum Direction dir_op1; enum Direction dir_op1;
enum Direction dir_op2; enum Direction dir_op2;
@ -769,9 +769,9 @@ struct opcode_metadata {
[STORE_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [STORE_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
[DELETE_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [DELETE_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
[LOAD_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_NAME] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
[LOAD_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_GLOBAL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0000 },
[LOAD_GLOBAL_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_GLOBAL_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0000 },
[LOAD_GLOBAL_BUILTIN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_GLOBAL_BUILTIN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC0000 },
[DELETE_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [DELETE_FAST] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
[MAKE_CELL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [MAKE_CELL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
[DELETE_DEREF] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [DELETE_DEREF] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },