From 2c79dbb4666ed97ed3543f9d0976a39d2a0487c0 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 10:49:01 -0800 Subject: [PATCH 01/12] Modernize LOAD_ATTR_INSTANCE_VALUE --- Python/bytecodes.c | 34 +++++++++++++++++----------------- Python/generated_cases.c.h | 20 +++++++++++--------- Python/opcode_metadata.h | 6 +++--- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 336088e08197de..caf25bef75050f 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1436,6 +1436,20 @@ dummy_func( PREDICT(JUMP_BACKWARD); } + family(load_attr) = { + LOAD_ATTR, + // LOAD_ATTR_CLASS, + // LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, + LOAD_ATTR_INSTANCE_VALUE, + // LOAD_ATTR_MODULE, + // LOAD_ATTR_PROPERTY, + // LOAD_ATTR_SLOT, + // LOAD_ATTR_WITH_HINT, + // LOAD_ATTR_METHOD_LAZY_DICT, + // LOAD_ATTR_METHOD_NO_DICT, + // LOAD_ATTR_METHOD_WITH_VALUES, + }; + inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) { #if ENABLE_SPECIALIZATION _PyAttrCache *cache = (_PyAttrCache *)next_instr; @@ -1485,29 +1499,21 @@ dummy_func( } } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_INSTANCE_VALUE) { + inst(LOAD_ATTR_INSTANCE_VALUE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); - PyObject *res; PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); assert(tp->tp_dictoffset < 0); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - res = _PyDictOrValues_GetValues(dorv)->values[cache->index]; + res = _PyDictOrValues_GetValues(dorv)->values[index]; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } // error: LOAD_ATTR has irregular stack effect @@ -3276,12 +3282,6 @@ family(call) = { family(for_iter) = { FOR_ITER, FOR_ITER_LIST, FOR_ITER_RANGE }; -family(load_attr) = { - LOAD_ATTR, LOAD_ATTR_CLASS, - LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_MODULE, - LOAD_ATTR_PROPERTY, LOAD_ATTR_SLOT, LOAD_ATTR_WITH_HINT, - LOAD_ATTR_METHOD_LAZY_DICT, LOAD_ATTR_METHOD_NO_DICT, - LOAD_ATTR_METHOD_WITH_VALUES }; family(load_global) = { LOAD_GLOBAL, LOAD_GLOBAL_BUILTIN, LOAD_GLOBAL_MODULE }; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index d70d64ecbdd5c1..68f3bb397c39d3 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1805,27 +1805,29 @@ } TARGET(LOAD_ATTR_INSTANCE_VALUE) { - assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); + PyObject *owner = PEEK(1); + PyObject *res2 = NULL; PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint16_t index = read_u16(&next_instr[3].cache); + assert(cframe.use_tracing == 0); PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); assert(tp->tp_dictoffset < 0); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner); DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); - res = _PyDictOrValues_GetValues(dorv)->values[cache->index]; + res = _PyDictOrValues_GetValues(dorv)->values[index]; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 171fed363d3be0..43e7d25b2eb1b8 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -187,7 +187,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR: return 1; case LOAD_ATTR_INSTANCE_VALUE: - return -1; + return 1; case LOAD_ATTR_MODULE: return -1; case LOAD_ATTR_WITH_HINT: @@ -533,7 +533,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_INSTANCE_VALUE: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_MODULE: return -1; case LOAD_ATTR_WITH_HINT: @@ -792,7 +792,7 @@ struct opcode_metadata { [DICT_MERGE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [MAP_ADD] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From 0915f2d71dddb2b7d97314def7af7f82a1ade213 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 10:58:19 -0800 Subject: [PATCH 02/12] Modernize LOAD_ATTR_MODULE --- Python/bytecodes.c | 20 ++++++-------------- Python/generated_cases.c.h | 24 +++++++++++++----------- Python/opcode_metadata.h | 6 +++--- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index caf25bef75050f..fd4275b482bc87 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1441,7 +1441,7 @@ dummy_func( // LOAD_ATTR_CLASS, // LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, LOAD_ATTR_INSTANCE_VALUE, - // LOAD_ATTR_MODULE, + LOAD_ATTR_MODULE, // LOAD_ATTR_PROPERTY, // LOAD_ATTR_SLOT, // LOAD_ATTR_WITH_HINT, @@ -1516,29 +1516,21 @@ dummy_func( Py_DECREF(owner); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_MODULE) { + inst(LOAD_ATTR_MODULE, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); - PyObject *res; - _PyAttrCache *cache = (_PyAttrCache *)next_instr; DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; assert(dict != NULL); - DEOPT_IF(dict->ma_keys->dk_version != read_u32(cache->version), - LOAD_ATTR); + DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR); assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE); - assert(cache->index < dict->ma_keys->dk_nentries); - PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + cache->index; + assert(index < dict->ma_keys->dk_nentries); + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index; res = ep->me_value; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } // error: LOAD_ATTR has irregular stack effect diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 68f3bb397c39d3..25a317c997ee1a 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1832,27 +1832,29 @@ } TARGET(LOAD_ATTR_MODULE) { - assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); + PyObject *owner = PEEK(1); + PyObject *res2 = NULL; PyObject *res; - _PyAttrCache *cache = (_PyAttrCache *)next_instr; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint16_t index = read_u16(&next_instr[3].cache); + assert(cframe.use_tracing == 0); DEOPT_IF(!PyModule_CheckExact(owner), LOAD_ATTR); PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict; assert(dict != NULL); - DEOPT_IF(dict->ma_keys->dk_version != read_u32(cache->version), - LOAD_ATTR); + DEOPT_IF(dict->ma_keys->dk_version != type_version, LOAD_ATTR); assert(dict->ma_keys->dk_kind == DICT_KEYS_UNICODE); - assert(cache->index < dict->ma_keys->dk_nentries); - PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + cache->index; + assert(index < dict->ma_keys->dk_nentries); + PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index; res = ep->me_value; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 43e7d25b2eb1b8..2878110e167249 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -189,7 +189,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR_INSTANCE_VALUE: return 1; case LOAD_ATTR_MODULE: - return -1; + return 1; case LOAD_ATTR_WITH_HINT: return -1; case LOAD_ATTR_SLOT: @@ -535,7 +535,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_INSTANCE_VALUE: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_MODULE: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_WITH_HINT: return -1; case LOAD_ATTR_SLOT: @@ -793,7 +793,7 @@ struct opcode_metadata { [MAP_ADD] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From f24eb1d0951a556bd8e78e92fea776c2688116bc Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 13:00:38 -0800 Subject: [PATCH 03/12] Modernize LOAD_ATTR_WITH_HINT --- Python/bytecodes.c | 16 ++++------------ Python/generated_cases.c.h | 20 +++++++++++--------- Python/opcode_metadata.h | 6 +++--- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index fd4275b482bc87..5dbf33f71ce54d 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1444,7 +1444,7 @@ dummy_func( LOAD_ATTR_MODULE, // LOAD_ATTR_PROPERTY, // LOAD_ATTR_SLOT, - // LOAD_ATTR_WITH_HINT, + LOAD_ATTR_WITH_HINT, // LOAD_ATTR_METHOD_LAZY_DICT, // LOAD_ATTR_METHOD_NO_DICT, // LOAD_ATTR_METHOD_WITH_VALUES, @@ -1533,14 +1533,9 @@ dummy_func( Py_DECREF(owner); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_WITH_HINT) { + inst(LOAD_ATTR_WITH_HINT, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); - PyObject *res; PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -1550,7 +1545,7 @@ dummy_func( DEOPT_IF(dict == NULL, LOAD_ATTR); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(names, oparg>>1); - uint16_t hint = cache->index; + uint16_t hint = index; DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR); if (DK_IS_UNICODE(dict->ma_keys)) { PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; @@ -1565,11 +1560,8 @@ dummy_func( DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } // error: LOAD_ATTR has irregular stack effect diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 25a317c997ee1a..b854b074a104e0 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1859,12 +1859,13 @@ } TARGET(LOAD_ATTR_WITH_HINT) { - assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); + PyObject *owner = PEEK(1); + PyObject *res2 = NULL; PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint16_t index = read_u16(&next_instr[3].cache); + assert(cframe.use_tracing == 0); PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); assert(tp->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -1874,7 +1875,7 @@ DEOPT_IF(dict == NULL, LOAD_ATTR); assert(PyDict_CheckExact((PyObject *)dict)); PyObject *name = GETITEM(names, oparg>>1); - uint16_t hint = cache->index; + uint16_t hint = index; DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, LOAD_ATTR); if (DK_IS_UNICODE(dict->ma_keys)) { PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint; @@ -1889,11 +1890,12 @@ DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 2878110e167249..3dfb9ab652cbf2 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -191,7 +191,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR_MODULE: return 1; case LOAD_ATTR_WITH_HINT: - return -1; + return 1; case LOAD_ATTR_SLOT: return -1; case LOAD_ATTR_CLASS: @@ -537,7 +537,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_MODULE: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_WITH_HINT: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_SLOT: return -1; case LOAD_ATTR_CLASS: @@ -794,7 +794,7 @@ struct opcode_metadata { [LOAD_ATTR] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From 2a417e965b25d3fdaea04f4aa30b89f47e3a2434 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 13:08:48 -0800 Subject: [PATCH 04/12] Modernize LOAD_ATTR_SLOT --- Python/bytecodes.c | 16 ++++------------ Python/generated_cases.c.h | 20 +++++++++++--------- Python/opcode_metadata.h | 6 +++--- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 5dbf33f71ce54d..f2476f396caca6 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1443,7 +1443,7 @@ dummy_func( LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_MODULE, // LOAD_ATTR_PROPERTY, - // LOAD_ATTR_SLOT, + LOAD_ATTR_SLOT, LOAD_ATTR_WITH_HINT, // LOAD_ATTR_METHOD_LAZY_DICT, // LOAD_ATTR_METHOD_NO_DICT, @@ -1564,26 +1564,18 @@ dummy_func( Py_DECREF(owner); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_SLOT) { + inst(LOAD_ATTR_SLOT, (unused/1, type_version/2, index/1, unused/5, owner -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); - PyObject *res; PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); - char *addr = (char *)owner + cache->index; + char *addr = (char *)owner + index; res = *(PyObject **)addr; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } // error: LOAD_ATTR has irregular stack effect diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index b854b074a104e0..fa435d0437036f 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1900,24 +1900,26 @@ } TARGET(LOAD_ATTR_SLOT) { - assert(cframe.use_tracing == 0); - PyObject *owner = TOP(); + PyObject *owner = PEEK(1); + PyObject *res2 = NULL; PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint16_t index = read_u16(&next_instr[3].cache); + assert(cframe.use_tracing == 0); PyTypeObject *tp = Py_TYPE(owner); - _PyAttrCache *cache = (_PyAttrCache *)next_instr; - uint32_t type_version = read_u32(cache->version); assert(type_version != 0); DEOPT_IF(tp->tp_version_tag != type_version, LOAD_ATTR); - char *addr = (char *)owner + cache->index; + char *addr = (char *)owner + index; res = *(PyObject **)addr; DEOPT_IF(res == NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); + res2 = NULL; Py_DECREF(owner); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 3dfb9ab652cbf2..5bf46debdb9e70 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -193,7 +193,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR_WITH_HINT: return 1; case LOAD_ATTR_SLOT: - return -1; + return 1; case LOAD_ATTR_CLASS: return -1; case LOAD_ATTR_PROPERTY: @@ -539,7 +539,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_WITH_HINT: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_SLOT: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_CLASS: return -1; case LOAD_ATTR_PROPERTY: @@ -795,7 +795,7 @@ struct opcode_metadata { [LOAD_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From fb0a638e2e1e544e1da9a365648e201fa29d417d Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 13:10:38 -0800 Subject: [PATCH 05/12] Reorder family to correspond to definition order --- Python/bytecodes.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index f2476f396caca6..aa2a5246b1218e 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1438,16 +1438,16 @@ dummy_func( family(load_attr) = { LOAD_ATTR, - // LOAD_ATTR_CLASS, - // LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_MODULE, - // LOAD_ATTR_PROPERTY, - LOAD_ATTR_SLOT, LOAD_ATTR_WITH_HINT, - // LOAD_ATTR_METHOD_LAZY_DICT, - // LOAD_ATTR_METHOD_NO_DICT, + LOAD_ATTR_SLOT, + // LOAD_ATTR_CLASS, + // LOAD_ATTR_PROPERTY, + // LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, // LOAD_ATTR_METHOD_WITH_VALUES, + // LOAD_ATTR_METHOD_NO_DICT, + // LOAD_ATTR_METHOD_LAZY_DICT, }; inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) { From 26acc639e3b94c74775979e0441fc979993bd5d9 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 13:38:49 -0800 Subject: [PATCH 06/12] Add cache size symbols for most families --- Python/bytecodes.c | 15 ++++++++------- Python/generated_cases.c.h | 3 +++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index aa2a5246b1218e..e35f78d6fb160c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -436,7 +436,7 @@ dummy_func( PREDICT(JUMP_BACKWARD); } - family(store_subscr) = { + family(store_subscr, INLINE_CACHE_ENTRIES_STORE_SUBSCR) = { STORE_SUBSCR, STORE_SUBSCR_DICT, STORE_SUBSCR_LIST_INT, @@ -950,7 +950,7 @@ dummy_func( Py_DECREF(seq); } - family(store_attr) = { + family(store_attr, INLINE_CACHE_ENTRIES_STORE_ATTR) = { STORE_ATTR, STORE_ATTR_INSTANCE_VALUE, STORE_ATTR_SLOT, @@ -1436,7 +1436,7 @@ dummy_func( PREDICT(JUMP_BACKWARD); } - family(load_attr) = { + family(load_attr, INLINE_CACHE_ENTRIES_LOAD_ATTR) = { LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_MODULE, @@ -1750,6 +1750,7 @@ dummy_func( ERROR_IF(res == NULL, error); } + // No cache size here, since this is a family of super-instructions. family(compare_and_branch) = { COMPARE_AND_BRANCH, COMPARE_AND_BRANCH_FLOAT, @@ -3247,7 +3248,7 @@ dummy_func( // Future families go below this point // -family(call) = { +family(call, INLINE_CACHE_ENTRIES_CALL) = { CALL, CALL_PY_EXACT_ARGS, CALL_PY_WITH_DEFAULTS, CALL_BOUND_METHOD_EXACT_ARGS, CALL_BUILTIN_CLASS, CALL_BUILTIN_FAST_WITH_KEYWORDS, CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, CALL_NO_KW_BUILTIN_FAST, @@ -3255,13 +3256,13 @@ family(call) = { CALL_NO_KW_LIST_APPEND, CALL_NO_KW_METHOD_DESCRIPTOR_FAST, CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, CALL_NO_KW_METHOD_DESCRIPTOR_O, CALL_NO_KW_STR_1, CALL_NO_KW_TUPLE_1, CALL_NO_KW_TYPE_1 }; -family(for_iter) = { +family(for_iter, INLINE_CACHE_ENTRIES_FOR_ITER) = { FOR_ITER, FOR_ITER_LIST, FOR_ITER_RANGE }; -family(load_global) = { +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(unpack_sequence) = { +family(unpack_sequence, INLINE_CACHE_ENTRIES_UNPACK_SEQUENCE) = { UNPACK_SEQUENCE, UNPACK_SEQUENCE_LIST, UNPACK_SEQUENCE_TUPLE, UNPACK_SEQUENCE_TWO_TUPLE }; diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index fa435d0437036f..e3535e95b6bf67 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -596,6 +596,7 @@ TARGET(STORE_SUBSCR) { PREDICTED(STORE_SUBSCR); + static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size"); PyObject *sub = PEEK(1); PyObject *container = PEEK(2); PyObject *v = PEEK(3); @@ -1180,6 +1181,7 @@ TARGET(STORE_ATTR) { PREDICTED(STORE_ATTR); + static_assert(INLINE_CACHE_ENTRIES_STORE_ATTR == 4, "incorrect cache size"); PyObject *owner = PEEK(1); PyObject *v = PEEK(2); uint16_t counter = read_u16(&next_instr[0].cache); @@ -1748,6 +1750,7 @@ TARGET(LOAD_ATTR) { PREDICTED(LOAD_ATTR); + static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size"); PyObject *owner = PEEK(1); PyObject *res2 = NULL; PyObject *res; From f0bd9efa9bba416d6baf0f57339c0b752e0166c6 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 13:49:55 -0800 Subject: [PATCH 07/12] Modernize LOAD_ATTR_CLASS --- Python/bytecodes.c | 15 ++++----------- Python/generated_cases.c.h | 19 +++++++++++-------- Python/opcode_metadata.h | 6 +++--- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index e35f78d6fb160c..1d73a9f0039ad7 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1442,7 +1442,7 @@ dummy_func( LOAD_ATTR_MODULE, LOAD_ATTR_WITH_HINT, LOAD_ATTR_SLOT, - // LOAD_ATTR_CLASS, + LOAD_ATTR_CLASS, // LOAD_ATTR_PROPERTY, // LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, // LOAD_ATTR_METHOD_WITH_VALUES, @@ -1578,27 +1578,20 @@ dummy_func( Py_DECREF(owner); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_CLASS) { + inst(LOAD_ATTR_CLASS, (unused/1, type_version/2, unused/2, descr/4, cls -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *cls = TOP(); DEOPT_IF(!PyType_Check(cls), LOAD_ATTR); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); + res2 = NULL; + res = descr; assert(res != NULL); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); Py_DECREF(cls); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); } // error: LOAD_ATTR has irregular stack effect diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index e3535e95b6bf67..3125c0f3ae7330 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1927,25 +1927,28 @@ } TARGET(LOAD_ATTR_CLASS) { + PyObject *cls = PEEK(1); + PyObject *res2 = NULL; + PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + PyObject *descr = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *cls = TOP(); DEOPT_IF(!PyType_Check(cls), LOAD_ATTR); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(((PyTypeObject *)cls)->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); + res2 = NULL; + res = descr; assert(res != NULL); Py_INCREF(res); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); Py_DECREF(cls); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 5bf46debdb9e70..2c3d7f6b7291b7 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -195,7 +195,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR_SLOT: return 1; case LOAD_ATTR_CLASS: - return -1; + return 1; case LOAD_ATTR_PROPERTY: return -1; case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: @@ -541,7 +541,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_SLOT: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_CLASS: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_PROPERTY: return -1; case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: @@ -796,7 +796,7 @@ struct opcode_metadata { [LOAD_ATTR_MODULE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [STORE_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 }, From 41a86d68d707183ea7a1cc961be9a5cde575936a Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 17:59:21 -0800 Subject: [PATCH 08/12] Modernize LOAD_ATTR_PROPERTY --- Python/bytecodes.c | 11 +++-------- Python/generated_cases.c.h | 10 +++++----- Python/opcode_metadata.h | 6 +++--- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 1d73a9f0039ad7..8e2f1d61f540bd 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1443,7 +1443,7 @@ dummy_func( LOAD_ATTR_WITH_HINT, LOAD_ATTR_SLOT, LOAD_ATTR_CLASS, - // LOAD_ATTR_PROPERTY, + LOAD_ATTR_PROPERTY, // LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, // LOAD_ATTR_METHOD_WITH_VALUES, // LOAD_ATTR_METHOD_NO_DICT, @@ -1594,21 +1594,15 @@ dummy_func( Py_DECREF(cls); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_PROPERTY) { + inst(LOAD_ATTR_PROPERTY, (unused/1, type_version/2, func_version/2, fget/4, owner -- unused if (oparg & 1), unused)) { assert(cframe.use_tracing == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *owner = TOP(); PyTypeObject *cls = Py_TYPE(owner); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *fget = read_obj(cache->descr); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; - uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); DEOPT_IF(f->func_version != func_version, LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; @@ -1617,6 +1611,7 @@ dummy_func( STAT_INC(LOAD_ATTR, hit); Py_INCREF(fget); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). SET_TOP(NULL); int shrink_stack = !(oparg & 1); STACK_SHRINK(shrink_stack); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 3125c0f3ae7330..072b70159d2732 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1953,19 +1953,18 @@ } TARGET(LOAD_ATTR_PROPERTY) { + PyObject *owner = PEEK(1); + uint32_t type_version = read_u32(&next_instr[1].cache); + uint32_t func_version = read_u32(&next_instr[3].cache); + PyObject *fget = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *owner = TOP(); PyTypeObject *cls = Py_TYPE(owner); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *fget = read_obj(cache->descr); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; - uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); DEOPT_IF(f->func_version != func_version, LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; @@ -1974,6 +1973,7 @@ STAT_INC(LOAD_ATTR, hit); Py_INCREF(fget); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 1); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). SET_TOP(NULL); int shrink_stack = !(oparg & 1); STACK_SHRINK(shrink_stack); diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 2c3d7f6b7291b7..c877d2f4531ae3 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -197,7 +197,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR_CLASS: return 1; case LOAD_ATTR_PROPERTY: - return -1; + return 1; case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: return -1; case STORE_ATTR_INSTANCE_VALUE: @@ -543,7 +543,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_CLASS: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_PROPERTY: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: return -1; case STORE_ATTR_INSTANCE_VALUE: @@ -797,7 +797,7 @@ struct opcode_metadata { [LOAD_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [STORE_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 }, [STORE_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 }, From d44375383408c854fee7d03da77c1edcf71147c9 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 18:10:03 -0800 Subject: [PATCH 09/12] Modernize LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN --- Python/bytecodes.c | 11 +++-------- Python/generated_cases.c.h | 10 +++++----- Python/opcode_metadata.h | 6 +++--- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 8e2f1d61f540bd..117fc36b70a576 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1444,7 +1444,7 @@ dummy_func( LOAD_ATTR_SLOT, LOAD_ATTR_CLASS, LOAD_ATTR_PROPERTY, - // LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, + LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, // LOAD_ATTR_METHOD_WITH_VALUES, // LOAD_ATTR_METHOD_NO_DICT, // LOAD_ATTR_METHOD_LAZY_DICT, @@ -1620,20 +1620,14 @@ dummy_func( DISPATCH_INLINED(new_frame); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) { + inst(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, (unused/1, type_version/2, func_version/2, getattribute/4, owner -- unused if (oparg & 1), unused)) { assert(cframe.use_tracing == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *owner = TOP(); PyTypeObject *cls = Py_TYPE(owner); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *getattribute = read_obj(cache->descr); assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)getattribute; - uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); DEOPT_IF(f->func_version != func_version, LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; @@ -1644,6 +1638,7 @@ dummy_func( PyObject *name = GETITEM(names, oparg >> 1); Py_INCREF(f); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). SET_TOP(NULL); int shrink_stack = !(oparg & 1); STACK_SHRINK(shrink_stack); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 072b70159d2732..5d1a8e5d7ff6e5 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1983,18 +1983,17 @@ } TARGET(LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN) { + PyObject *owner = PEEK(1); + uint32_t type_version = read_u32(&next_instr[1].cache); + uint32_t func_version = read_u32(&next_instr[3].cache); + PyObject *getattribute = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - PyObject *owner = TOP(); PyTypeObject *cls = Py_TYPE(owner); - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *getattribute = read_obj(cache->descr); assert(Py_IS_TYPE(getattribute, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)getattribute; - uint32_t func_version = read_u32(cache->keys_version); assert(func_version != 0); DEOPT_IF(f->func_version != func_version, LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; @@ -2005,6 +2004,7 @@ PyObject *name = GETITEM(names, oparg >> 1); Py_INCREF(f); _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2); + // Manipulate stack directly because we exit with DISPATCH_INLINED(). SET_TOP(NULL); int shrink_stack = !(oparg & 1); STACK_SHRINK(shrink_stack); diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index c877d2f4531ae3..aa1e9b2fe1ce2b 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -199,7 +199,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR_PROPERTY: return 1; case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: - return -1; + return 1; case STORE_ATTR_INSTANCE_VALUE: return 2; case STORE_ATTR_WITH_HINT: @@ -545,7 +545,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_PROPERTY: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case STORE_ATTR_INSTANCE_VALUE: return 0; case STORE_ATTR_WITH_HINT: @@ -798,7 +798,7 @@ struct opcode_metadata { [LOAD_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_CLASS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_PROPERTY] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, + [LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [STORE_ATTR_INSTANCE_VALUE] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 }, [STORE_ATTR_WITH_HINT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC000 }, [STORE_ATTR_SLOT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 }, From f675fccfbed9b20c50643e44f714406e5378f08c Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 31 Jan 2023 22:03:10 -0800 Subject: [PATCH 10/12] Modernize LOAD_ATTR_METHOD_WITH_VALUES --- Python/bytecodes.c | 21 ++++++++------------- Python/generated_cases.c.h | 26 ++++++++++++++++---------- Python/opcode_metadata.h | 6 +++--- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 117fc36b70a576..05e0bc4c3a157d 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1445,7 +1445,7 @@ dummy_func( LOAD_ATTR_CLASS, LOAD_ATTR_PROPERTY, LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, - // LOAD_ATTR_METHOD_WITH_VALUES, + LOAD_ATTR_METHOD_WITH_VALUES, // LOAD_ATTR_METHOD_NO_DICT, // LOAD_ATTR_METHOD_LAZY_DICT, }; @@ -2339,14 +2339,10 @@ dummy_func( } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_METHOD_WITH_VALUES) { + inst(LOAD_ATTR_METHOD_WITH_VALUES, (unused/1, type_version/2, keys_version/2, descr/4, self -- res2 if (oparg & 1), res)) { /* Cached method object */ assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); assert(type_version != 0); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -2354,14 +2350,13 @@ dummy_func( DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != - read_u32(cache->keys_version), LOAD_ATTR); + keys_version, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + res2 = Py_NewRef(descr); + assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res = self; + assert(oparg & 1); } // error: LOAD_ATTR has irregular stack effect diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 5d1a8e5d7ff6e5..ffef83f8d8ba8b 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2845,12 +2845,15 @@ } TARGET(LOAD_ATTR_METHOD_WITH_VALUES) { + PyObject *self = PEEK(1); + PyObject *res2 = NULL; + PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + uint32_t keys_version = read_u32(&next_instr[3].cache); + PyObject *descr = read_obj(&next_instr[5].cache); /* Cached method object */ assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); assert(type_version != 0); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_flags & Py_TPFLAGS_MANAGED_DICT); @@ -2858,14 +2861,17 @@ DEOPT_IF(!_PyDictOrValues_IsValues(dorv), LOAD_ATTR); PyHeapTypeObject *self_heap_type = (PyHeapTypeObject *)self_cls; DEOPT_IF(self_heap_type->ht_cached_keys->dk_version != - read_u32(cache->keys_version), LOAD_ATTR); + keys_version, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + res2 = Py_NewRef(descr); + assert(_PyType_HasFeature(Py_TYPE(res2), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res = self; + assert(oparg & 1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index aa1e9b2fe1ce2b..3ac46aae6df336 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -279,7 +279,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case PUSH_EXC_INFO: return -1; case LOAD_ATTR_METHOD_WITH_VALUES: - return -1; + return 1; case LOAD_ATTR_METHOD_NO_DICT: return -1; case LOAD_ATTR_METHOD_LAZY_DICT: @@ -625,7 +625,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case PUSH_EXC_INFO: return -1; case LOAD_ATTR_METHOD_WITH_VALUES: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_METHOD_NO_DICT: return -1; case LOAD_ATTR_METHOD_LAZY_DICT: @@ -838,7 +838,7 @@ struct opcode_metadata { [BEFORE_WITH] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [WITH_EXCEPT_START] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [PUSH_EXC_INFO] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, - [LOAD_ATTR_METHOD_WITH_VALUES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, + [LOAD_ATTR_METHOD_WITH_VALUES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_METHOD_NO_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [LOAD_ATTR_METHOD_LAZY_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [CALL_BOUND_METHOD_EXACT_ARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From ba7ec518ef139fa0f7f9f1494dcd3796749f4582 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 1 Feb 2023 08:47:38 -0800 Subject: [PATCH 11/12] Modernize LOAD_ATTR_METHOD_NO_DICT --- Python/bytecodes.c | 19 +++++++------------ Python/generated_cases.c.h | 23 ++++++++++++++--------- Python/opcode_metadata.h | 6 +++--- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 05e0bc4c3a157d..bfe083562904da 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1446,7 +1446,7 @@ dummy_func( LOAD_ATTR_PROPERTY, LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, LOAD_ATTR_METHOD_WITH_VALUES, - // LOAD_ATTR_METHOD_NO_DICT, + LOAD_ATTR_METHOD_NO_DICT, // LOAD_ATTR_METHOD_LAZY_DICT, }; @@ -2359,22 +2359,17 @@ dummy_func( assert(oparg & 1); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_METHOD_NO_DICT) { + inst(LOAD_ATTR_METHOD_NO_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res2 = Py_NewRef(descr); + res = self; + assert(oparg & 1); } // error: LOAD_ATTR has irregular stack effect diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index ffef83f8d8ba8b..7d6d1c5084da95 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2876,20 +2876,25 @@ } TARGET(LOAD_ATTR_METHOD_NO_DICT) { + PyObject *self = PEEK(1); + PyObject *res2 = NULL; + PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + PyObject *descr = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); assert(self_cls->tp_dictoffset == 0); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res2 = Py_NewRef(descr); + res = self; + assert(oparg & 1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index 3ac46aae6df336..f6af3287fe2261 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -281,7 +281,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR_METHOD_WITH_VALUES: return 1; case LOAD_ATTR_METHOD_NO_DICT: - return -1; + return 1; case LOAD_ATTR_METHOD_LAZY_DICT: return -1; case CALL_BOUND_METHOD_EXACT_ARGS: @@ -627,7 +627,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_METHOD_WITH_VALUES: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_METHOD_NO_DICT: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_METHOD_LAZY_DICT: return -1; case CALL_BOUND_METHOD_EXACT_ARGS: @@ -839,7 +839,7 @@ struct opcode_metadata { [WITH_EXCEPT_START] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [PUSH_EXC_INFO] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [LOAD_ATTR_METHOD_WITH_VALUES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_METHOD_NO_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, + [LOAD_ATTR_METHOD_NO_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_METHOD_LAZY_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [CALL_BOUND_METHOD_EXACT_ARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [KW_NAMES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, From ab74331854b5ae6058c3a4fe766b2d962709ae3b Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 1 Feb 2023 08:55:41 -0800 Subject: [PATCH 12/12] Modernize LOAD_ATTR_METHOD_LAZY_DICT This concludes the LOAD_ATTR family. --- Python/bytecodes.c | 19 +++++++------------ Python/generated_cases.c.h | 23 ++++++++++++++--------- Python/opcode_metadata.h | 6 +++--- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Python/bytecodes.c b/Python/bytecodes.c index bfe083562904da..bb1deaf3fbeb4b 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -1447,7 +1447,7 @@ dummy_func( LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN, LOAD_ATTR_METHOD_WITH_VALUES, LOAD_ATTR_METHOD_NO_DICT, - // LOAD_ATTR_METHOD_LAZY_DICT, + LOAD_ATTR_METHOD_LAZY_DICT, }; inst(LOAD_ATTR, (unused/9, owner -- res2 if (oparg & 1), res)) { @@ -2372,13 +2372,9 @@ dummy_func( assert(oparg & 1); } - // error: LOAD_ATTR has irregular stack effect - inst(LOAD_ATTR_METHOD_LAZY_DICT) { + inst(LOAD_ATTR_METHOD_LAZY_DICT, (unused/1, type_version/2, unused/2, descr/4, self -- res2 if (oparg & 1), res)) { assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); Py_ssize_t dictoffset = self_cls->tp_dictoffset; assert(dictoffset > 0); @@ -2386,12 +2382,11 @@ dummy_func( /* This object has a __dict__, just not yet created */ DEOPT_IF(dict != NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res2 = Py_NewRef(descr); + res = self; + assert(oparg & 1); } // stack effect: (__0, __array[oparg] -- ) diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 7d6d1c5084da95..e5c5c7e557a37c 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -2899,11 +2899,13 @@ } TARGET(LOAD_ATTR_METHOD_LAZY_DICT) { + PyObject *self = PEEK(1); + PyObject *res2 = NULL; + PyObject *res; + uint32_t type_version = read_u32(&next_instr[1].cache); + PyObject *descr = read_obj(&next_instr[5].cache); assert(cframe.use_tracing == 0); - PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; - uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(self_cls->tp_version_tag != type_version, LOAD_ATTR); Py_ssize_t dictoffset = self_cls->tp_dictoffset; assert(dictoffset > 0); @@ -2911,12 +2913,15 @@ /* This object has a __dict__, just not yet created */ DEOPT_IF(dict != NULL, LOAD_ATTR); STAT_INC(LOAD_ATTR, hit); - PyObject *res = read_obj(cache->descr); - assert(res != NULL); - assert(_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)); - SET_TOP(Py_NewRef(res)); - PUSH(self); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + assert(descr != NULL); + assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)); + res2 = Py_NewRef(descr); + res = self; + assert(oparg & 1); + STACK_GROW(((oparg & 1) ? 1 : 0)); + POKE(1, res); + if (oparg & 1) { POKE(1 + ((oparg & 1) ? 1 : 0), res2); } + JUMPBY(9); DISPATCH(); } diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h index f6af3287fe2261..96e57be8cf5dea 100644 --- a/Python/opcode_metadata.h +++ b/Python/opcode_metadata.h @@ -283,7 +283,7 @@ _PyOpcode_num_popped(int opcode, int oparg) { case LOAD_ATTR_METHOD_NO_DICT: return 1; case LOAD_ATTR_METHOD_LAZY_DICT: - return -1; + return 1; case CALL_BOUND_METHOD_EXACT_ARGS: return -1; case KW_NAMES: @@ -629,7 +629,7 @@ _PyOpcode_num_pushed(int opcode, int oparg) { case LOAD_ATTR_METHOD_NO_DICT: return ((oparg & 1) ? 1 : 0) + 1; case LOAD_ATTR_METHOD_LAZY_DICT: - return -1; + return ((oparg & 1) ? 1 : 0) + 1; case CALL_BOUND_METHOD_EXACT_ARGS: return -1; case KW_NAMES: @@ -840,7 +840,7 @@ struct opcode_metadata { [PUSH_EXC_INFO] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, [LOAD_ATTR_METHOD_WITH_VALUES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [LOAD_ATTR_METHOD_NO_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, - [LOAD_ATTR_METHOD_LAZY_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX }, + [LOAD_ATTR_METHOD_LAZY_DICT] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IBC00000000 }, [CALL_BOUND_METHOD_EXACT_ARGS] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [KW_NAMES] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB }, [CALL] = { DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },