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 }, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy