From c9966d19908cdeada6919df274acc14d042b0a7f Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 16 Jun 2022 16:46:04 +0800 Subject: [PATCH 01/14] More LOAD_ATTR specializations --- Include/descrobject.h | 2 + Include/internal/pycore_opcode.h | 44 +++++++++--------- Include/opcode.h | 58 ++++++++++++------------ Lib/opcode.py | 2 + Objects/descrobject.c | 7 +++ Python/ceval.c | 77 ++++++++++++++++++++++++++++++-- Python/opcode_targets.h | 38 ++++++++-------- Python/specialize.c | 65 ++++++++++++++++++++++++--- 8 files changed, 214 insertions(+), 79 deletions(-) diff --git a/Include/descrobject.h b/Include/descrobject.h index 77f221df07714f..eb64564317b1c2 100644 --- a/Include/descrobject.h +++ b/Include/descrobject.h @@ -32,6 +32,8 @@ PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *, PyGetSetDef *); PyAPI_FUNC(PyObject *) PyDictProxy_New(PyObject *); PyAPI_FUNC(PyObject *) PyWrapper_New(PyObject *, PyObject *); +PyObject *_PyProperty_PropGet(PyObject *prop); + #ifndef Py_LIMITED_API # define Py_CPYTHON_DESCROBJECT_H # include "cpython/descrobject.h" diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index 62db22f1952550..6436613c0aec67 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -147,12 +147,14 @@ const uint8_t _PyOpcode_Deopt[256] = { [LOAD_ATTR] = LOAD_ATTR, [LOAD_ATTR_ADAPTIVE] = LOAD_ATTR, [LOAD_ATTR_CLASS] = LOAD_ATTR, + [LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR] = LOAD_ATTR, [LOAD_ATTR_INSTANCE_VALUE] = LOAD_ATTR, [LOAD_ATTR_METHOD_LAZY_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_NO_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_WITH_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_WITH_VALUES] = LOAD_ATTR, [LOAD_ATTR_MODULE] = LOAD_ATTR, + [LOAD_ATTR_PROPERTY] = LOAD_ATTR, [LOAD_ATTR_SLOT] = LOAD_ATTR, [LOAD_ATTR_WITH_HINT] = LOAD_ATTR, [LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS, @@ -327,12 +329,14 @@ const uint8_t _PyOpcode_Original[256] = { [LOAD_ATTR] = LOAD_ATTR, [LOAD_ATTR_ADAPTIVE] = LOAD_ATTR, [LOAD_ATTR_CLASS] = LOAD_ATTR, + [LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR] = LOAD_ATTR, [LOAD_ATTR_INSTANCE_VALUE] = LOAD_ATTR, [LOAD_ATTR_METHOD_LAZY_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_NO_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_WITH_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_WITH_VALUES] = LOAD_ATTR, [LOAD_ATTR_MODULE] = LOAD_ATTR, + [LOAD_ATTR_PROPERTY] = LOAD_ATTR, [LOAD_ATTR_SLOT] = LOAD_ATTR, [LOAD_ATTR_WITH_HINT] = LOAD_ATTR, [LOAD_BUILD_CLASS] = LOAD_BUILD_CLASS, @@ -479,29 +483,29 @@ static const char *const _PyOpcode_OpName[256] = { [DELETE_SUBSCR] = "DELETE_SUBSCR", [LOAD_ATTR_ADAPTIVE] = "LOAD_ATTR_ADAPTIVE", [LOAD_ATTR_CLASS] = "LOAD_ATTR_CLASS", + [LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR] = "LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR", [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE", - [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", - [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT", + [LOAD_ATTR_PROPERTY] = "LOAD_ATTR_PROPERTY", [GET_ITER] = "GET_ITER", [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", [PRINT_EXPR] = "PRINT_EXPR", [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", - [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT", - [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT", + [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", + [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT", [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", [RETURN_GENERATOR] = "RETURN_GENERATOR", + [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT", + [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT", [LOAD_ATTR_METHOD_WITH_DICT] = "LOAD_ATTR_METHOD_WITH_DICT", [LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES", [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST", [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST", - [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", - [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", [LIST_TO_TUPLE] = "LIST_TO_TUPLE", [RETURN_VALUE] = "RETURN_VALUE", [IMPORT_STAR] = "IMPORT_STAR", [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS", - [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", + [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", [ASYNC_GEN_WRAP] = "ASYNC_GEN_WRAP", [PREP_RERAISE_STAR] = "PREP_RERAISE_STAR", [POP_EXCEPT] = "POP_EXCEPT", @@ -528,7 +532,7 @@ static const char *const _PyOpcode_OpName[256] = { [JUMP_FORWARD] = "JUMP_FORWARD", [JUMP_IF_FALSE_OR_POP] = "JUMP_IF_FALSE_OR_POP", [JUMP_IF_TRUE_OR_POP] = "JUMP_IF_TRUE_OR_POP", - [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", + [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", [POP_JUMP_FORWARD_IF_FALSE] = "POP_JUMP_FORWARD_IF_FALSE", [POP_JUMP_FORWARD_IF_TRUE] = "POP_JUMP_FORWARD_IF_TRUE", [LOAD_GLOBAL] = "LOAD_GLOBAL", @@ -536,7 +540,7 @@ static const char *const _PyOpcode_OpName[256] = { [CONTAINS_OP] = "CONTAINS_OP", [RERAISE] = "RERAISE", [COPY] = "COPY", - [RESUME_QUICK] = "RESUME_QUICK", + [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", [BINARY_OP] = "BINARY_OP", [SEND] = "SEND", [LOAD_FAST] = "LOAD_FAST", @@ -556,9 +560,9 @@ static const char *const _PyOpcode_OpName[256] = { [STORE_DEREF] = "STORE_DEREF", [DELETE_DEREF] = "DELETE_DEREF", [JUMP_BACKWARD] = "JUMP_BACKWARD", - [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", + [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", - [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", + [RESUME_QUICK] = "RESUME_QUICK", [EXTENDED_ARG] = "EXTENDED_ARG", [LIST_APPEND] = "LIST_APPEND", [SET_ADD] = "SET_ADD", @@ -568,32 +572,32 @@ static const char *const _PyOpcode_OpName[256] = { [YIELD_VALUE] = "YIELD_VALUE", [RESUME] = "RESUME", [MATCH_CLASS] = "MATCH_CLASS", - [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", - [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", + [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", + [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", [FORMAT_VALUE] = "FORMAT_VALUE", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_STRING] = "BUILD_STRING", + [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", + [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", - [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", - [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", [LIST_EXTEND] = "LIST_EXTEND", [SET_UPDATE] = "SET_UPDATE", [DICT_MERGE] = "DICT_MERGE", [DICT_UPDATE] = "DICT_UPDATE", + [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", + [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", - [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", - [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", [CALL] = "CALL", [KW_NAMES] = "KW_NAMES", [POP_JUMP_BACKWARD_IF_NOT_NONE] = "POP_JUMP_BACKWARD_IF_NOT_NONE", [POP_JUMP_BACKWARD_IF_NONE] = "POP_JUMP_BACKWARD_IF_NONE", [POP_JUMP_BACKWARD_IF_FALSE] = "POP_JUMP_BACKWARD_IF_FALSE", [POP_JUMP_BACKWARD_IF_TRUE] = "POP_JUMP_BACKWARD_IF_TRUE", - [177] = "<177>", - [178] = "<178>", + [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", + [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", [179] = "<179>", [180] = "<180>", [181] = "<181>", @@ -675,8 +679,6 @@ static const char *const _PyOpcode_OpName[256] = { #endif #define EXTRA_CASES \ - case 177: \ - case 178: \ case 179: \ case 180: \ case 181: \ diff --git a/Include/opcode.h b/Include/opcode.h index 04e5bc8310ffb3..1aef2762a21efb 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -158,34 +158,36 @@ extern "C" { #define JUMP_BACKWARD_QUICK 59 #define LOAD_ATTR_ADAPTIVE 62 #define LOAD_ATTR_CLASS 63 -#define LOAD_ATTR_INSTANCE_VALUE 64 -#define LOAD_ATTR_MODULE 65 -#define LOAD_ATTR_SLOT 66 -#define LOAD_ATTR_WITH_HINT 67 -#define LOAD_ATTR_METHOD_LAZY_DICT 72 -#define LOAD_ATTR_METHOD_NO_DICT 73 -#define LOAD_ATTR_METHOD_WITH_DICT 76 -#define LOAD_ATTR_METHOD_WITH_VALUES 77 -#define LOAD_CONST__LOAD_FAST 78 -#define LOAD_FAST__LOAD_CONST 79 -#define LOAD_FAST__LOAD_FAST 80 -#define LOAD_GLOBAL_ADAPTIVE 81 -#define LOAD_GLOBAL_BUILTIN 86 -#define LOAD_GLOBAL_MODULE 113 -#define RESUME_QUICK 121 -#define STORE_ATTR_ADAPTIVE 141 -#define STORE_ATTR_INSTANCE_VALUE 143 -#define STORE_ATTR_SLOT 153 -#define STORE_ATTR_WITH_HINT 154 -#define STORE_FAST__LOAD_FAST 158 -#define STORE_FAST__STORE_FAST 159 -#define STORE_SUBSCR_ADAPTIVE 160 -#define STORE_SUBSCR_DICT 161 -#define STORE_SUBSCR_LIST_INT 166 -#define UNPACK_SEQUENCE_ADAPTIVE 167 -#define UNPACK_SEQUENCE_LIST 168 -#define UNPACK_SEQUENCE_TUPLE 169 -#define UNPACK_SEQUENCE_TWO_TUPLE 170 +#define LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR 64 +#define LOAD_ATTR_INSTANCE_VALUE 65 +#define LOAD_ATTR_MODULE 66 +#define LOAD_ATTR_PROPERTY 67 +#define LOAD_ATTR_SLOT 72 +#define LOAD_ATTR_WITH_HINT 73 +#define LOAD_ATTR_METHOD_LAZY_DICT 76 +#define LOAD_ATTR_METHOD_NO_DICT 77 +#define LOAD_ATTR_METHOD_WITH_DICT 78 +#define LOAD_ATTR_METHOD_WITH_VALUES 79 +#define LOAD_CONST__LOAD_FAST 80 +#define LOAD_FAST__LOAD_CONST 81 +#define LOAD_FAST__LOAD_FAST 86 +#define LOAD_GLOBAL_ADAPTIVE 113 +#define LOAD_GLOBAL_BUILTIN 121 +#define LOAD_GLOBAL_MODULE 141 +#define RESUME_QUICK 143 +#define STORE_ATTR_ADAPTIVE 153 +#define STORE_ATTR_INSTANCE_VALUE 154 +#define STORE_ATTR_SLOT 158 +#define STORE_ATTR_WITH_HINT 159 +#define STORE_FAST__LOAD_FAST 160 +#define STORE_FAST__STORE_FAST 161 +#define STORE_SUBSCR_ADAPTIVE 166 +#define STORE_SUBSCR_DICT 167 +#define STORE_SUBSCR_LIST_INT 168 +#define UNPACK_SEQUENCE_ADAPTIVE 169 +#define UNPACK_SEQUENCE_LIST 170 +#define UNPACK_SEQUENCE_TUPLE 177 +#define UNPACK_SEQUENCE_TWO_TUPLE 178 #define DO_TRACING 255 #define HAS_CONST(op) (false\ diff --git a/Lib/opcode.py b/Lib/opcode.py index 912b280c49b5bc..57c255e077faed 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -285,8 +285,10 @@ def jabs_op(name, op): "LOAD_ATTR_ADAPTIVE", # These potentially push [NULL, bound method] onto the stack. "LOAD_ATTR_CLASS", + "LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR", "LOAD_ATTR_INSTANCE_VALUE", "LOAD_ATTR_MODULE", + "LOAD_ATTR_PROPERTY", "LOAD_ATTR_SLOT", "LOAD_ATTR_WITH_HINT", # These will always push [unbound method, self] onto the stack. diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 05797e72bcd41a..45e031f3b92cde 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1893,6 +1893,13 @@ property_clear(PyObject *self) return 0; } +PyObject * +_PyProperty_PropGet(PyObject *self) +{ + propertyobject *pp = (propertyobject *)self; + return pp->prop_get; +} + #include "clinic/descrobject.c.h" PyTypeObject PyDictProxy_Type = { diff --git a/Python/ceval.c b/Python/ceval.c index f9ec640ef1722a..7450ef84c3047f 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3627,7 +3627,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(LOAD_ATTR_CLASS) { - /* LOAD_METHOD, for class methods */ assert(cframe.use_tracing == 0); _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; @@ -3650,6 +3649,76 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int NOTRACE_DISPATCH(); } + TARGET(LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR) { + 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); + PyObject *descr = read_obj(cache->descr); + descrgetfunc get = Py_TYPE(descr)->tp_descr_get; + DEOPT_IF(get == NULL, LOAD_ATTR); + STAT_INC(LOAD_ATTR, hit); + PyObject *res = get(descr, NULL, cls); + if (res == NULL) { + goto error; + } + assert(res != NULL); + SET_TOP(NULL); + STACK_GROW((oparg & 1)); + SET_TOP(res); + Py_DECREF(cls); + JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + NOTRACE_DISPATCH(); + } + + TARGET(LOAD_ATTR_PROPERTY) { + assert(cframe.use_tracing == 0); + _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 *prop = read_obj(cache->descr); + assert(Py_TYPE(prop) == &PyProperty_Type); + PyObject *fget = _PyProperty_PropGet(prop); + DEOPT_IF(!PyFunction_Check(fget), LOAD_ATTR); + PyFunctionObject *f = (PyFunctionObject *)fget; + DEOPT_IF(f->func_version != cache->keys_version[0], LOAD_ATTR); + PyCodeObject *code = (PyCodeObject *)f->func_code; + size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; + assert(code->co_argcount == 1); + STAT_INC(LOAD_ATTR, hit); + + _PyInterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size); + if (new_frame == NULL) { + goto error; + } + CALL_STAT_INC(frames_pushed); + Py_INCREF(f); + _PyFrame_InitializeSpecials(new_frame, f, + NULL, code->co_nlocalsplus); + SET_TOP(NULL); + STACK_SHRINK(!(oparg & 1)); + new_frame->localsplus[0] = owner; + for (int i = 1; i < code->co_nlocalsplus; i++) { + new_frame->localsplus[i] = NULL; + } + _PyFrame_SetStackPointer(frame, stack_pointer); + JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); + frame->prev_instr = next_instr - 1; + new_frame->previous = frame; + frame = cframe.current_frame = new_frame; + CALL_STAT_INC(inlined_py_calls); + goto start_frame; + } + TARGET(STORE_ATTR_ADAPTIVE) { assert(cframe.use_tracing == 0); _PyAttrCache *cache = (_PyAttrCache *)next_instr; @@ -4549,7 +4618,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(LOAD_ATTR_METHOD_WITH_VALUES) { - /* LOAD_METHOD, with cached method object */ + /* Cached method object */ assert(cframe.use_tracing == 0); PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); @@ -4575,8 +4644,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(LOAD_ATTR_METHOD_WITH_DICT) { - /* LOAD_METHOD, with a dict - Can be either a managed dict, or a tp_dictoffset offset.*/ + /* Can be either a managed dict, or a tp_dictoffset offset.*/ assert(cframe.use_tracing == 0); PyObject *self = TOP(); PyTypeObject *self_cls = Py_TYPE(self); @@ -5527,6 +5595,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(CACHE) { + printf("cache\n"); Py_UNREACHABLE(); } diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index a6523d4af2b783..21421a8bcd4c13 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -63,29 +63,29 @@ static void *opcode_targets[256] = { &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_CLASS, + &&TARGET_LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_MODULE, - &&TARGET_LOAD_ATTR_SLOT, - &&TARGET_LOAD_ATTR_WITH_HINT, + &&TARGET_LOAD_ATTR_PROPERTY, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT, - &&TARGET_LOAD_ATTR_METHOD_NO_DICT, + &&TARGET_LOAD_ATTR_SLOT, + &&TARGET_LOAD_ATTR_WITH_HINT, &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_RETURN_GENERATOR, + &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT, + &&TARGET_LOAD_ATTR_METHOD_NO_DICT, &&TARGET_LOAD_ATTR_METHOD_WITH_DICT, &&TARGET_LOAD_ATTR_METHOD_WITH_VALUES, &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_LOAD_FAST__LOAD_CONST, - &&TARGET_LOAD_FAST__LOAD_FAST, - &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, - &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_ASYNC_GEN_WRAP, &&TARGET_PREP_RERAISE_STAR, &&TARGET_POP_EXCEPT, @@ -112,7 +112,7 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_FORWARD, &&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_LOAD_GLOBAL_MODULE, + &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_POP_JUMP_FORWARD_IF_FALSE, &&TARGET_POP_JUMP_FORWARD_IF_TRUE, &&TARGET_LOAD_GLOBAL, @@ -120,7 +120,7 @@ static void *opcode_targets[256] = { &&TARGET_CONTAINS_OP, &&TARGET_RERAISE, &&TARGET_COPY, - &&TARGET_RESUME_QUICK, + &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_BINARY_OP, &&TARGET_SEND, &&TARGET_LOAD_FAST, @@ -140,9 +140,9 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_CALL_FUNCTION_EX, - &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_RESUME_QUICK, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, @@ -152,32 +152,32 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, + &&TARGET_STORE_ATTR_ADAPTIVE, + &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, + &&TARGET_STORE_ATTR_SLOT, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_STORE_FAST__STORE_FAST, - &&TARGET_STORE_SUBSCR_ADAPTIVE, - &&TARGET_STORE_SUBSCR_DICT, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, + &&TARGET_STORE_SUBSCR_ADAPTIVE, + &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, &&TARGET_UNPACK_SEQUENCE_LIST, - &&TARGET_UNPACK_SEQUENCE_TUPLE, - &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&TARGET_CALL, &&TARGET_KW_NAMES, &&TARGET_POP_JUMP_BACKWARD_IF_NOT_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_FALSE, &&TARGET_POP_JUMP_BACKWARD_IF_TRUE, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_UNPACK_SEQUENCE_TUPLE, + &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/specialize.c b/Python/specialize.c index a3be97d40dfb5b..a440d89d2fea6c 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -331,6 +331,8 @@ miss_counter_start(void) { return 53; } +#define SIMPLE_FUNCTION 0 + /* Common */ #define SPEC_FAIL_OTHER 0 @@ -532,7 +534,8 @@ typedef enum { BUILTIN_CLASSMETHOD, /* Builtin methods with METH_CLASS */ PYTHON_CLASSMETHOD, /* Python classmethod(func) object */ NON_DESCRIPTOR, /* Is not a descriptor, and is an instance of an immutable class */ - MUTABLE, /* Instance of a mutable class; might, or might not, be a descriptor */ + MUTABLE_DESCRIPTOR, /* Instance of a mutable class; with __set__/__get__ */ + MUTABLE, /* Instance of a mutable class, but the descriptor doesn't match the operation*/ ABSENT, /* Attribute is not present on the class */ DUNDER_CLASS, /* __class__ attribute */ GETSET_OVERRIDDEN /* __getattribute__ or __setattr__ has been overridden */ @@ -561,6 +564,12 @@ analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int sto } PyTypeObject *desc_cls = Py_TYPE(descriptor); if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) { + if (!store && desc_cls->tp_descr_get) { + return MUTABLE_DESCRIPTOR; + } + if (store && desc_cls->tp_descr_set) { + return MUTABLE_DESCRIPTOR; + } return MUTABLE; } if (desc_cls->tp_descr_set) { @@ -580,7 +589,9 @@ analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int sto return DUNDER_CLASS; } } - return OVERRIDING; + if (store) { + return OVERRIDING; + } } if (desc_cls->tp_descr_get) { if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) { @@ -650,6 +661,7 @@ specialize_dict_access( static int specialize_attr_loadmethod(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name, PyObject* descr, DescriptorClassification kind); static int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name); +static int function_kind(PyCodeObject *code); int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) @@ -696,8 +708,38 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) goto fail; } case PROPERTY: - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY); - goto fail; + { + _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1); + assert(Py_TYPE(descr) == &PyProperty_Type); + PyObject *fget = _PyProperty_PropGet(descr); + if (fget == NULL || Py_TYPE(fget) != &PyFunction_Type) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR); + goto fail; + } + PyFunctionObject *func = (PyFunctionObject *)fget; + PyCodeObject *fcode = (PyCodeObject *)func->func_code; + int kind = function_kind(fcode); + if (kind != SIMPLE_FUNCTION) { + SPECIALIZATION_FAIL(LOAD_ATTR, kind); + goto fail; + } + if (fcode->co_argcount != 1) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS); + goto fail; + } + int version = _PyFunction_GetVersionForCurrentState(func); + if (version == 0 || version != (uint16_t)version) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS); + goto fail; + } + cache->keys_version[0] = version; + assert(type->tp_version_tag != 0); + write_u32(cache->type_version, type->tp_version_tag); + /* borrowed */ + write_obj(cache->descr, descr); + _Py_SET_OPCODE(*instr, LOAD_ATTR_PROPERTY); + goto success; + } case OBJECT_SLOT: { PyMemberDescrObject *member = (PyMemberDescrObject *)descr; @@ -731,6 +773,9 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT); goto fail; case MUTABLE: + case MUTABLE_DESCRIPTOR: + //_PyObject_Dump(owner); + //_PyObject_Dump(descr); SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS); goto fail; case GETSET_OVERRIDDEN: @@ -812,6 +857,7 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT); goto fail; case MUTABLE: + case MUTABLE_DESCRIPTOR: SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS); goto fail; case GETSET_OVERRIDDEN: @@ -866,6 +912,7 @@ load_attr_fail_kind(DescriptorClassification kind) case DUNDER_CLASS: return SPEC_FAIL_OTHER; case MUTABLE: + case MUTABLE_DESCRIPTOR: return SPEC_FAIL_ATTR_MUTABLE_CLASS; case GETSET_OVERRIDDEN: return SPEC_FAIL_OVERRIDDEN; @@ -895,10 +942,17 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, switch (kind) { case METHOD: case NON_DESCRIPTOR: + case MUTABLE: write_u32(cache->type_version, ((PyTypeObject *)owner)->tp_version_tag); write_obj(cache->descr, descr); _Py_SET_OPCODE(*instr, LOAD_ATTR_CLASS); return 0; + case MUTABLE_DESCRIPTOR: + return -1; + write_u32(cache->type_version, ((PyTypeObject *)owner)->tp_version_tag); + write_obj(cache->descr, descr); + _Py_SET_OPCODE(*instr, LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR); + return 0; #ifdef Py_STATS case ABSENT: if (_PyType_Lookup(Py_TYPE(owner), name) != NULL) { @@ -1145,9 +1199,6 @@ binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub) } #endif - -#define SIMPLE_FUNCTION 0 - static int function_kind(PyCodeObject *code) { int flags = code->co_flags; From e66782bf4f1e4024d0de0e5ef9b66c88470a3001 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 16 Jun 2022 08:56:26 +0000 Subject: [PATCH 02/14] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst b/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst new file mode 100644 index 00000000000000..e1cf651cd366e8 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst @@ -0,0 +1 @@ +Specialize `LOAD_ATTR` for mutable class attribute descriptors and ``property()`` attributes. From c7bde64a5c6cc62f58ae53b5e65fce875bcbf186 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 16 Jun 2022 17:39:25 +0800 Subject: [PATCH 03/14] fix compiler warnings --- Python/ceval.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 7450ef84c3047f..325f5fe3ee1c8a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1465,8 +1465,8 @@ eval_frame_handle_pending(PyThreadState *tstate) assert(STACK_LEVEL() <= STACK_SIZE()); \ } while (0) #define STACK_SHRINK(n) do { \ - assert(n >= 0); \ - assert(STACK_LEVEL() >= n); \ + assert((n) >= 0); \ + assert(STACK_LEVEL() >= (n)); \ BASIC_STACKADJ(-(n)); \ } while (0) #else @@ -5595,7 +5595,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(CACHE) { - printf("cache\n"); Py_UNREACHABLE(); } From 6a03dad976bcc74bd187e0f5dbf64011b3fc8622 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 16 Jun 2022 17:40:02 +0800 Subject: [PATCH 04/14] Fix double backticks --- .../2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst b/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst index e1cf651cd366e8..2c9747de327c8e 100644 --- a/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst +++ b/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst @@ -1 +1 @@ -Specialize `LOAD_ATTR` for mutable class attribute descriptors and ``property()`` attributes. +Specialize ``LOAD_ATTR`` for mutable class attribute descriptors and ``property()`` attributes. From c78831d54e452c13a4fce388f749b48cc8073698 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 16 Jun 2022 20:18:19 +0800 Subject: [PATCH 05/14] Apply Mark's suggestions --- Include/descrobject.h | 1 - Include/internal/pycore_descrobject.h | 26 ++++++++++++++++++++++++++ Makefile.pre.in | 1 + Objects/descrobject.c | 18 +----------------- PCbuild/pythoncore.vcxproj | 1 + PCbuild/pythoncore.vcxproj.filters | 3 +++ Python/ceval.c | 14 ++++---------- Python/specialize.c | 17 +++++++++-------- 8 files changed, 45 insertions(+), 36 deletions(-) create mode 100644 Include/internal/pycore_descrobject.h diff --git a/Include/descrobject.h b/Include/descrobject.h index eb64564317b1c2..8039b15576cc58 100644 --- a/Include/descrobject.h +++ b/Include/descrobject.h @@ -32,7 +32,6 @@ PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *, PyGetSetDef *); PyAPI_FUNC(PyObject *) PyDictProxy_New(PyObject *); PyAPI_FUNC(PyObject *) PyWrapper_New(PyObject *, PyObject *); -PyObject *_PyProperty_PropGet(PyObject *prop); #ifndef Py_LIMITED_API # define Py_CPYTHON_DESCROBJECT_H diff --git a/Include/internal/pycore_descrobject.h b/Include/internal/pycore_descrobject.h new file mode 100644 index 00000000000000..76378569df90e3 --- /dev/null +++ b/Include/internal/pycore_descrobject.h @@ -0,0 +1,26 @@ +#ifndef Py_INTERNAL_DESCROBJECT_H +#define Py_INTERNAL_DESCROBJECT_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +typedef struct { + PyObject_HEAD + PyObject *prop_get; + PyObject *prop_set; + PyObject *prop_del; + PyObject *prop_doc; + PyObject *prop_name; + int getter_doc; +} propertyobject; + +typedef propertyobject _PyPropertyObject; + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_DESCROBJECT_H */ diff --git a/Makefile.pre.in b/Makefile.pre.in index f3c70b99c9e221..ad0d09f913cea7 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1595,6 +1595,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_condvar.h \ $(srcdir)/Include/internal/pycore_context.h \ $(srcdir)/Include/internal/pycore_dict.h \ + $(srcdir)/Include/internal/pycore_descrobject.h \ $(srcdir)/Include/internal/pycore_dtoa.h \ $(srcdir)/Include/internal/pycore_exceptions.h \ $(srcdir)/Include/internal/pycore_fileutils.h \ diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 45e031f3b92cde..8ef6a82d7c6d96 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -6,6 +6,7 @@ #include "pycore_pystate.h" // _PyThreadState_GET() #include "pycore_tuple.h" // _PyTuple_ITEMS() #include "structmember.h" // PyMemberDef +#include "pycore_descrobject.h" /*[clinic input] class mappingproxy "mappingproxyobject *" "&PyDictProxy_Type" @@ -1501,16 +1502,6 @@ class property(object): */ -typedef struct { - PyObject_HEAD - PyObject *prop_get; - PyObject *prop_set; - PyObject *prop_del; - PyObject *prop_doc; - PyObject *prop_name; - int getter_doc; -} propertyobject; - static PyObject * property_copy(PyObject *, PyObject *, PyObject *, PyObject *); @@ -1893,13 +1884,6 @@ property_clear(PyObject *self) return 0; } -PyObject * -_PyProperty_PropGet(PyObject *self) -{ - propertyobject *pp = (propertyobject *)self; - return pp->prop_get; -} - #include "clinic/descrobject.c.h" PyTypeObject PyDictProxy_Type = { diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index be76f1bc55859a..2e00fa9a7735c2 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -207,6 +207,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 5573e0020491a6..9c2920cf2bd505 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -528,6 +528,9 @@ Include\internal + + Include\internal + Include\internal diff --git a/Python/ceval.c b/Python/ceval.c index 325f5fe3ee1c8a..f7e39590a68bc2 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3685,25 +3685,19 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int uint32_t type_version = read_u32(cache->type_version); DEOPT_IF(cls->tp_version_tag != type_version, LOAD_ATTR); assert(type_version != 0); - PyObject *prop = read_obj(cache->descr); - assert(Py_TYPE(prop) == &PyProperty_Type); - PyObject *fget = _PyProperty_PropGet(prop); - DEOPT_IF(!PyFunction_Check(fget), LOAD_ATTR); + PyObject *fget = read_obj(cache->descr); PyFunctionObject *f = (PyFunctionObject *)fget; DEOPT_IF(f->func_version != cache->keys_version[0], LOAD_ATTR); PyCodeObject *code = (PyCodeObject *)f->func_code; - size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; assert(code->co_argcount == 1); STAT_INC(LOAD_ATTR, hit); - _PyInterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size); + Py_INCREF(fget); + _PyInterpreterFrame *new_frame = _PyFrame_Push(tstate, f); if (new_frame == NULL) { goto error; } - CALL_STAT_INC(frames_pushed); - Py_INCREF(f); - _PyFrame_InitializeSpecials(new_frame, f, - NULL, code->co_nlocalsplus); + CALL_STAT_INC(inlined_py_calls); SET_TOP(NULL); STACK_SHRINK(!(oparg & 1)); new_frame->localsplus[0] = owner; diff --git a/Python/specialize.c b/Python/specialize.c index a440d89d2fea6c..24d192137444b4 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -8,6 +8,7 @@ #include "pycore_object.h" #include "pycore_opcode.h" // _PyOpcode_Caches #include "structmember.h" // struct PyMemberDef, T_OFFSET_EX +#include "pycore_descrobject.h" #include // rand() @@ -709,9 +710,9 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) } case PROPERTY: { - _PyLoadMethodCache *cache = (_PyLoadMethodCache *)(instr + 1); + _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1); assert(Py_TYPE(descr) == &PyProperty_Type); - PyObject *fget = _PyProperty_PropGet(descr); + PyObject *fget = ((_PyPropertyObject *)descr)->prop_get; if (fget == NULL || Py_TYPE(fget) != &PyFunction_Type) { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR); goto fail; @@ -729,14 +730,16 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) } int version = _PyFunction_GetVersionForCurrentState(func); if (version == 0 || version != (uint16_t)version) { - SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS); + SPECIALIZATION_FAIL(LOAD_ATTR, + version == 0 ? + SPEC_FAIL_OUT_OF_VERSIONS : SPEC_FAIL_OUT_OF_RANGE); goto fail; } - cache->keys_version[0] = version; + lm_cache->keys_version[0] = version; assert(type->tp_version_tag != 0); - write_u32(cache->type_version, type->tp_version_tag); + write_u32(lm_cache->type_version, type->tp_version_tag); /* borrowed */ - write_obj(cache->descr, descr); + write_obj(lm_cache->descr, fget); _Py_SET_OPCODE(*instr, LOAD_ATTR_PROPERTY); goto success; } @@ -774,8 +777,6 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) goto fail; case MUTABLE: case MUTABLE_DESCRIPTOR: - //_PyObject_Dump(owner); - //_PyObject_Dump(descr); SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS); goto fail; case GETSET_OVERRIDDEN: From d03cc611aad100f638ace01ffb1ee44f45f0d967 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 16 Jun 2022 21:39:09 +0800 Subject: [PATCH 06/14] try to fix compiler warnings --- Include/descrobject.h | 1 - Python/ceval.c | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/descrobject.h b/Include/descrobject.h index 8039b15576cc58..77f221df07714f 100644 --- a/Include/descrobject.h +++ b/Include/descrobject.h @@ -32,7 +32,6 @@ PyAPI_FUNC(PyObject *) PyDescr_NewGetSet(PyTypeObject *, PyGetSetDef *); PyAPI_FUNC(PyObject *) PyDictProxy_New(PyObject *); PyAPI_FUNC(PyObject *) PyWrapper_New(PyObject *, PyObject *); - #ifndef Py_LIMITED_API # define Py_CPYTHON_DESCROBJECT_H # include "cpython/descrobject.h" diff --git a/Python/ceval.c b/Python/ceval.c index f7e39590a68bc2..5f22a6fef9319a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1465,8 +1465,8 @@ eval_frame_handle_pending(PyThreadState *tstate) assert(STACK_LEVEL() <= STACK_SIZE()); \ } while (0) #define STACK_SHRINK(n) do { \ - assert((n) >= 0); \ - assert(STACK_LEVEL() >= (n)); \ + assert(n >= 0); \ + assert(STACK_LEVEL() >= n); \ BASIC_STACKADJ(-(n)); \ } while (0) #else @@ -3699,7 +3699,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } CALL_STAT_INC(inlined_py_calls); SET_TOP(NULL); - STACK_SHRINK(!(oparg & 1)); + int push_null = !(oparg & 1); + STACK_SHRINK(push_null); new_frame->localsplus[0] = owner; for (int i = 1; i < code->co_nlocalsplus; i++) { new_frame->localsplus[i] = NULL; From 36af644bb3a1847d1d84e81f7126a0b2adea2260 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 16 Jun 2022 21:47:42 +0800 Subject: [PATCH 07/14] re-enable LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR --- Python/specialize.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/specialize.c b/Python/specialize.c index 24d192137444b4..9ec5b2c5edbe90 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -949,7 +949,6 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, _Py_SET_OPCODE(*instr, LOAD_ATTR_CLASS); return 0; case MUTABLE_DESCRIPTOR: - return -1; write_u32(cache->type_version, ((PyTypeObject *)owner)->tp_version_tag); write_obj(cache->descr, descr); _Py_SET_OPCODE(*instr, LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR); From c20af47e67670d0ea857b8a634010834d8d68acb Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Thu, 16 Jun 2022 22:06:19 +0800 Subject: [PATCH 08/14] Remove double stat count --- Python/ceval.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Python/ceval.c b/Python/ceval.c index 5f22a6fef9319a..d75743f88cdb39 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3697,7 +3697,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (new_frame == NULL) { goto error; } - CALL_STAT_INC(inlined_py_calls); SET_TOP(NULL); int push_null = !(oparg & 1); STACK_SHRINK(push_null); From 3d5d5fd4832cfdb9e7b6a350548be1eefdf1353f Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Fri, 17 Jun 2022 00:49:10 +0800 Subject: [PATCH 09/14] remove LOAD_ATTR_MUTABLE_CLASS_DESCRIPTOR --- Include/internal/pycore_opcode.h | 27 +++++++-------- Include/opcode.h | 59 ++++++++++++++++---------------- Lib/opcode.py | 1 - Python/ceval.c | 27 --------------- Python/opcode_targets.h | 24 ++++++------- Python/specialize.c | 18 +--------- 6 files changed, 55 insertions(+), 101 deletions(-) diff --git a/Include/internal/pycore_opcode.h b/Include/internal/pycore_opcode.h index 6436613c0aec67..f0edbc731a6eed 100644 --- a/Include/internal/pycore_opcode.h +++ b/Include/internal/pycore_opcode.h @@ -147,7 +147,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [LOAD_ATTR] = LOAD_ATTR, [LOAD_ATTR_ADAPTIVE] = LOAD_ATTR, [LOAD_ATTR_CLASS] = LOAD_ATTR, - [LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR] = LOAD_ATTR, [LOAD_ATTR_INSTANCE_VALUE] = LOAD_ATTR, [LOAD_ATTR_METHOD_LAZY_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_NO_DICT] = LOAD_ATTR, @@ -329,7 +328,6 @@ const uint8_t _PyOpcode_Original[256] = { [LOAD_ATTR] = LOAD_ATTR, [LOAD_ATTR_ADAPTIVE] = LOAD_ATTR, [LOAD_ATTR_CLASS] = LOAD_ATTR, - [LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR] = LOAD_ATTR, [LOAD_ATTR_INSTANCE_VALUE] = LOAD_ATTR, [LOAD_ATTR_METHOD_LAZY_DICT] = LOAD_ATTR, [LOAD_ATTR_METHOD_NO_DICT] = LOAD_ATTR, @@ -483,29 +481,29 @@ static const char *const _PyOpcode_OpName[256] = { [DELETE_SUBSCR] = "DELETE_SUBSCR", [LOAD_ATTR_ADAPTIVE] = "LOAD_ATTR_ADAPTIVE", [LOAD_ATTR_CLASS] = "LOAD_ATTR_CLASS", - [LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR] = "LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR", [LOAD_ATTR_INSTANCE_VALUE] = "LOAD_ATTR_INSTANCE_VALUE", [LOAD_ATTR_MODULE] = "LOAD_ATTR_MODULE", [LOAD_ATTR_PROPERTY] = "LOAD_ATTR_PROPERTY", + [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", [GET_ITER] = "GET_ITER", [GET_YIELD_FROM_ITER] = "GET_YIELD_FROM_ITER", [PRINT_EXPR] = "PRINT_EXPR", [LOAD_BUILD_CLASS] = "LOAD_BUILD_CLASS", - [LOAD_ATTR_SLOT] = "LOAD_ATTR_SLOT", [LOAD_ATTR_WITH_HINT] = "LOAD_ATTR_WITH_HINT", + [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT", [LOAD_ASSERTION_ERROR] = "LOAD_ASSERTION_ERROR", [RETURN_GENERATOR] = "RETURN_GENERATOR", - [LOAD_ATTR_METHOD_LAZY_DICT] = "LOAD_ATTR_METHOD_LAZY_DICT", [LOAD_ATTR_METHOD_NO_DICT] = "LOAD_ATTR_METHOD_NO_DICT", [LOAD_ATTR_METHOD_WITH_DICT] = "LOAD_ATTR_METHOD_WITH_DICT", [LOAD_ATTR_METHOD_WITH_VALUES] = "LOAD_ATTR_METHOD_WITH_VALUES", [LOAD_CONST__LOAD_FAST] = "LOAD_CONST__LOAD_FAST", [LOAD_FAST__LOAD_CONST] = "LOAD_FAST__LOAD_CONST", + [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", [LIST_TO_TUPLE] = "LIST_TO_TUPLE", [RETURN_VALUE] = "RETURN_VALUE", [IMPORT_STAR] = "IMPORT_STAR", [SETUP_ANNOTATIONS] = "SETUP_ANNOTATIONS", - [LOAD_FAST__LOAD_FAST] = "LOAD_FAST__LOAD_FAST", + [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", [ASYNC_GEN_WRAP] = "ASYNC_GEN_WRAP", [PREP_RERAISE_STAR] = "PREP_RERAISE_STAR", [POP_EXCEPT] = "POP_EXCEPT", @@ -532,7 +530,7 @@ static const char *const _PyOpcode_OpName[256] = { [JUMP_FORWARD] = "JUMP_FORWARD", [JUMP_IF_FALSE_OR_POP] = "JUMP_IF_FALSE_OR_POP", [JUMP_IF_TRUE_OR_POP] = "JUMP_IF_TRUE_OR_POP", - [LOAD_GLOBAL_ADAPTIVE] = "LOAD_GLOBAL_ADAPTIVE", + [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", [POP_JUMP_FORWARD_IF_FALSE] = "POP_JUMP_FORWARD_IF_FALSE", [POP_JUMP_FORWARD_IF_TRUE] = "POP_JUMP_FORWARD_IF_TRUE", [LOAD_GLOBAL] = "LOAD_GLOBAL", @@ -540,7 +538,7 @@ static const char *const _PyOpcode_OpName[256] = { [CONTAINS_OP] = "CONTAINS_OP", [RERAISE] = "RERAISE", [COPY] = "COPY", - [LOAD_GLOBAL_BUILTIN] = "LOAD_GLOBAL_BUILTIN", + [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", [BINARY_OP] = "BINARY_OP", [SEND] = "SEND", [LOAD_FAST] = "LOAD_FAST", @@ -560,9 +558,9 @@ static const char *const _PyOpcode_OpName[256] = { [STORE_DEREF] = "STORE_DEREF", [DELETE_DEREF] = "DELETE_DEREF", [JUMP_BACKWARD] = "JUMP_BACKWARD", - [LOAD_GLOBAL_MODULE] = "LOAD_GLOBAL_MODULE", - [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", [RESUME_QUICK] = "RESUME_QUICK", + [CALL_FUNCTION_EX] = "CALL_FUNCTION_EX", + [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", [EXTENDED_ARG] = "EXTENDED_ARG", [LIST_APPEND] = "LIST_APPEND", [SET_ADD] = "SET_ADD", @@ -572,32 +570,32 @@ static const char *const _PyOpcode_OpName[256] = { [YIELD_VALUE] = "YIELD_VALUE", [RESUME] = "RESUME", [MATCH_CLASS] = "MATCH_CLASS", - [STORE_ATTR_ADAPTIVE] = "STORE_ATTR_ADAPTIVE", [STORE_ATTR_INSTANCE_VALUE] = "STORE_ATTR_INSTANCE_VALUE", + [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [FORMAT_VALUE] = "FORMAT_VALUE", [BUILD_CONST_KEY_MAP] = "BUILD_CONST_KEY_MAP", [BUILD_STRING] = "BUILD_STRING", - [STORE_ATTR_SLOT] = "STORE_ATTR_SLOT", [STORE_ATTR_WITH_HINT] = "STORE_ATTR_WITH_HINT", [STORE_FAST__LOAD_FAST] = "STORE_FAST__LOAD_FAST", [STORE_FAST__STORE_FAST] = "STORE_FAST__STORE_FAST", + [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", [LIST_EXTEND] = "LIST_EXTEND", [SET_UPDATE] = "SET_UPDATE", [DICT_MERGE] = "DICT_MERGE", [DICT_UPDATE] = "DICT_UPDATE", - [STORE_SUBSCR_ADAPTIVE] = "STORE_SUBSCR_ADAPTIVE", [STORE_SUBSCR_DICT] = "STORE_SUBSCR_DICT", [STORE_SUBSCR_LIST_INT] = "STORE_SUBSCR_LIST_INT", [UNPACK_SEQUENCE_ADAPTIVE] = "UNPACK_SEQUENCE_ADAPTIVE", [UNPACK_SEQUENCE_LIST] = "UNPACK_SEQUENCE_LIST", + [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [CALL] = "CALL", [KW_NAMES] = "KW_NAMES", [POP_JUMP_BACKWARD_IF_NOT_NONE] = "POP_JUMP_BACKWARD_IF_NOT_NONE", [POP_JUMP_BACKWARD_IF_NONE] = "POP_JUMP_BACKWARD_IF_NONE", [POP_JUMP_BACKWARD_IF_FALSE] = "POP_JUMP_BACKWARD_IF_FALSE", [POP_JUMP_BACKWARD_IF_TRUE] = "POP_JUMP_BACKWARD_IF_TRUE", - [UNPACK_SEQUENCE_TUPLE] = "UNPACK_SEQUENCE_TUPLE", [UNPACK_SEQUENCE_TWO_TUPLE] = "UNPACK_SEQUENCE_TWO_TUPLE", + [178] = "<178>", [179] = "<179>", [180] = "<180>", [181] = "<181>", @@ -679,6 +677,7 @@ static const char *const _PyOpcode_OpName[256] = { #endif #define EXTRA_CASES \ + case 178: \ case 179: \ case 180: \ case 181: \ diff --git a/Include/opcode.h b/Include/opcode.h index 1aef2762a21efb..b58b498bbcf941 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -158,36 +158,35 @@ extern "C" { #define JUMP_BACKWARD_QUICK 59 #define LOAD_ATTR_ADAPTIVE 62 #define LOAD_ATTR_CLASS 63 -#define LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR 64 -#define LOAD_ATTR_INSTANCE_VALUE 65 -#define LOAD_ATTR_MODULE 66 -#define LOAD_ATTR_PROPERTY 67 -#define LOAD_ATTR_SLOT 72 -#define LOAD_ATTR_WITH_HINT 73 -#define LOAD_ATTR_METHOD_LAZY_DICT 76 -#define LOAD_ATTR_METHOD_NO_DICT 77 -#define LOAD_ATTR_METHOD_WITH_DICT 78 -#define LOAD_ATTR_METHOD_WITH_VALUES 79 -#define LOAD_CONST__LOAD_FAST 80 -#define LOAD_FAST__LOAD_CONST 81 -#define LOAD_FAST__LOAD_FAST 86 -#define LOAD_GLOBAL_ADAPTIVE 113 -#define LOAD_GLOBAL_BUILTIN 121 -#define LOAD_GLOBAL_MODULE 141 -#define RESUME_QUICK 143 -#define STORE_ATTR_ADAPTIVE 153 -#define STORE_ATTR_INSTANCE_VALUE 154 -#define STORE_ATTR_SLOT 158 -#define STORE_ATTR_WITH_HINT 159 -#define STORE_FAST__LOAD_FAST 160 -#define STORE_FAST__STORE_FAST 161 -#define STORE_SUBSCR_ADAPTIVE 166 -#define STORE_SUBSCR_DICT 167 -#define STORE_SUBSCR_LIST_INT 168 -#define UNPACK_SEQUENCE_ADAPTIVE 169 -#define UNPACK_SEQUENCE_LIST 170 -#define UNPACK_SEQUENCE_TUPLE 177 -#define UNPACK_SEQUENCE_TWO_TUPLE 178 +#define LOAD_ATTR_INSTANCE_VALUE 64 +#define LOAD_ATTR_MODULE 65 +#define LOAD_ATTR_PROPERTY 66 +#define LOAD_ATTR_SLOT 67 +#define LOAD_ATTR_WITH_HINT 72 +#define LOAD_ATTR_METHOD_LAZY_DICT 73 +#define LOAD_ATTR_METHOD_NO_DICT 76 +#define LOAD_ATTR_METHOD_WITH_DICT 77 +#define LOAD_ATTR_METHOD_WITH_VALUES 78 +#define LOAD_CONST__LOAD_FAST 79 +#define LOAD_FAST__LOAD_CONST 80 +#define LOAD_FAST__LOAD_FAST 81 +#define LOAD_GLOBAL_ADAPTIVE 86 +#define LOAD_GLOBAL_BUILTIN 113 +#define LOAD_GLOBAL_MODULE 121 +#define RESUME_QUICK 141 +#define STORE_ATTR_ADAPTIVE 143 +#define STORE_ATTR_INSTANCE_VALUE 153 +#define STORE_ATTR_SLOT 154 +#define STORE_ATTR_WITH_HINT 158 +#define STORE_FAST__LOAD_FAST 159 +#define STORE_FAST__STORE_FAST 160 +#define STORE_SUBSCR_ADAPTIVE 161 +#define STORE_SUBSCR_DICT 166 +#define STORE_SUBSCR_LIST_INT 167 +#define UNPACK_SEQUENCE_ADAPTIVE 168 +#define UNPACK_SEQUENCE_LIST 169 +#define UNPACK_SEQUENCE_TUPLE 170 +#define UNPACK_SEQUENCE_TWO_TUPLE 177 #define DO_TRACING 255 #define HAS_CONST(op) (false\ diff --git a/Lib/opcode.py b/Lib/opcode.py index 57c255e077faed..7657a5158d729e 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -285,7 +285,6 @@ def jabs_op(name, op): "LOAD_ATTR_ADAPTIVE", # These potentially push [NULL, bound method] onto the stack. "LOAD_ATTR_CLASS", - "LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR", "LOAD_ATTR_INSTANCE_VALUE", "LOAD_ATTR_MODULE", "LOAD_ATTR_PROPERTY", diff --git a/Python/ceval.c b/Python/ceval.c index d75743f88cdb39..f851505966502e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3649,33 +3649,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int NOTRACE_DISPATCH(); } - TARGET(LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR) { - 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); - PyObject *descr = read_obj(cache->descr); - descrgetfunc get = Py_TYPE(descr)->tp_descr_get; - DEOPT_IF(get == NULL, LOAD_ATTR); - STAT_INC(LOAD_ATTR, hit); - PyObject *res = get(descr, NULL, cls); - if (res == NULL) { - goto error; - } - assert(res != NULL); - SET_TOP(NULL); - STACK_GROW((oparg & 1)); - SET_TOP(res); - Py_DECREF(cls); - JUMPBY(INLINE_CACHE_ENTRIES_LOAD_ATTR); - NOTRACE_DISPATCH(); - } - TARGET(LOAD_ATTR_PROPERTY) { assert(cframe.use_tracing == 0); _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 21421a8bcd4c13..9193dd9c9cc107 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -63,29 +63,29 @@ static void *opcode_targets[256] = { &&TARGET_DELETE_SUBSCR, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_CLASS, - &&TARGET_LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_ATTR_PROPERTY, + &&TARGET_LOAD_ATTR_SLOT, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_LOAD_ATTR_SLOT, &&TARGET_LOAD_ATTR_WITH_HINT, + &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT, &&TARGET_LOAD_ASSERTION_ERROR, &&TARGET_RETURN_GENERATOR, - &&TARGET_LOAD_ATTR_METHOD_LAZY_DICT, &&TARGET_LOAD_ATTR_METHOD_NO_DICT, &&TARGET_LOAD_ATTR_METHOD_WITH_DICT, &&TARGET_LOAD_ATTR_METHOD_WITH_VALUES, &&TARGET_LOAD_CONST__LOAD_FAST, &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, - &&TARGET_LOAD_FAST__LOAD_FAST, + &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_ASYNC_GEN_WRAP, &&TARGET_PREP_RERAISE_STAR, &&TARGET_POP_EXCEPT, @@ -112,7 +112,7 @@ static void *opcode_targets[256] = { &&TARGET_JUMP_FORWARD, &&TARGET_JUMP_IF_FALSE_OR_POP, &&TARGET_JUMP_IF_TRUE_OR_POP, - &&TARGET_LOAD_GLOBAL_ADAPTIVE, + &&TARGET_LOAD_GLOBAL_BUILTIN, &&TARGET_POP_JUMP_FORWARD_IF_FALSE, &&TARGET_POP_JUMP_FORWARD_IF_TRUE, &&TARGET_LOAD_GLOBAL, @@ -120,7 +120,7 @@ static void *opcode_targets[256] = { &&TARGET_CONTAINS_OP, &&TARGET_RERAISE, &&TARGET_COPY, - &&TARGET_LOAD_GLOBAL_BUILTIN, + &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_BINARY_OP, &&TARGET_SEND, &&TARGET_LOAD_FAST, @@ -140,9 +140,9 @@ static void *opcode_targets[256] = { &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, &&TARGET_JUMP_BACKWARD, - &&TARGET_LOAD_GLOBAL_MODULE, - &&TARGET_CALL_FUNCTION_EX, &&TARGET_RESUME_QUICK, + &&TARGET_CALL_FUNCTION_EX, + &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_EXTENDED_ARG, &&TARGET_LIST_APPEND, &&TARGET_SET_ADD, @@ -152,31 +152,30 @@ static void *opcode_targets[256] = { &&TARGET_YIELD_VALUE, &&TARGET_RESUME, &&TARGET_MATCH_CLASS, - &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_STORE_ATTR_INSTANCE_VALUE, + &&TARGET_STORE_ATTR_SLOT, &&TARGET_FORMAT_VALUE, &&TARGET_BUILD_CONST_KEY_MAP, &&TARGET_BUILD_STRING, - &&TARGET_STORE_ATTR_SLOT, &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_LIST_EXTEND, &&TARGET_SET_UPDATE, &&TARGET_DICT_MERGE, &&TARGET_DICT_UPDATE, - &&TARGET_STORE_SUBSCR_ADAPTIVE, &&TARGET_STORE_SUBSCR_DICT, &&TARGET_STORE_SUBSCR_LIST_INT, &&TARGET_UNPACK_SEQUENCE_ADAPTIVE, &&TARGET_UNPACK_SEQUENCE_LIST, + &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_CALL, &&TARGET_KW_NAMES, &&TARGET_POP_JUMP_BACKWARD_IF_NOT_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_NONE, &&TARGET_POP_JUMP_BACKWARD_IF_FALSE, &&TARGET_POP_JUMP_BACKWARD_IF_TRUE, - &&TARGET_UNPACK_SEQUENCE_TUPLE, &&TARGET_UNPACK_SEQUENCE_TWO_TUPLE, &&_unknown_opcode, &&_unknown_opcode, @@ -254,5 +253,6 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_DO_TRACING }; diff --git a/Python/specialize.c b/Python/specialize.c index 9ec5b2c5edbe90..a0a7f4355a4f9a 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -535,8 +535,7 @@ typedef enum { BUILTIN_CLASSMETHOD, /* Builtin methods with METH_CLASS */ PYTHON_CLASSMETHOD, /* Python classmethod(func) object */ NON_DESCRIPTOR, /* Is not a descriptor, and is an instance of an immutable class */ - MUTABLE_DESCRIPTOR, /* Instance of a mutable class; with __set__/__get__ */ - MUTABLE, /* Instance of a mutable class, but the descriptor doesn't match the operation*/ + MUTABLE, /* Instance of a mutable class; might, or might not, be a descriptor */ ABSENT, /* Attribute is not present on the class */ DUNDER_CLASS, /* __class__ attribute */ GETSET_OVERRIDDEN /* __getattribute__ or __setattr__ has been overridden */ @@ -565,12 +564,6 @@ analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int sto } PyTypeObject *desc_cls = Py_TYPE(descriptor); if (!(desc_cls->tp_flags & Py_TPFLAGS_IMMUTABLETYPE)) { - if (!store && desc_cls->tp_descr_get) { - return MUTABLE_DESCRIPTOR; - } - if (store && desc_cls->tp_descr_set) { - return MUTABLE_DESCRIPTOR; - } return MUTABLE; } if (desc_cls->tp_descr_set) { @@ -776,7 +769,6 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT); goto fail; case MUTABLE: - case MUTABLE_DESCRIPTOR: SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS); goto fail; case GETSET_OVERRIDDEN: @@ -858,7 +850,6 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_NON_OBJECT_SLOT); goto fail; case MUTABLE: - case MUTABLE_DESCRIPTOR: SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS); goto fail; case GETSET_OVERRIDDEN: @@ -913,7 +904,6 @@ load_attr_fail_kind(DescriptorClassification kind) case DUNDER_CLASS: return SPEC_FAIL_OTHER; case MUTABLE: - case MUTABLE_DESCRIPTOR: return SPEC_FAIL_ATTR_MUTABLE_CLASS; case GETSET_OVERRIDDEN: return SPEC_FAIL_OVERRIDDEN; @@ -943,16 +933,10 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr, switch (kind) { case METHOD: case NON_DESCRIPTOR: - case MUTABLE: write_u32(cache->type_version, ((PyTypeObject *)owner)->tp_version_tag); write_obj(cache->descr, descr); _Py_SET_OPCODE(*instr, LOAD_ATTR_CLASS); return 0; - case MUTABLE_DESCRIPTOR: - write_u32(cache->type_version, ((PyTypeObject *)owner)->tp_version_tag); - write_obj(cache->descr, descr); - _Py_SET_OPCODE(*instr, LOAD_ATTR_CLASS_MUTABLE_DESCRIPTOR); - return 0; #ifdef Py_STATS case ABSENT: if (_PyType_Lookup(Py_TYPE(owner), name) != NULL) { From 7f45ec1652237067ee36b96f9da9ae92863449bb Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Fri, 17 Jun 2022 00:51:26 +0800 Subject: [PATCH 10/14] Delete 2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst --- .../2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst b/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst deleted file mode 100644 index 2c9747de327c8e..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2022-06-16-08-56-26.gh-issue-93657.AZG2WT.rst +++ /dev/null @@ -1 +0,0 @@ -Specialize ``LOAD_ATTR`` for mutable class attribute descriptors and ``property()`` attributes. From a6c4ab32b204a668c8adc507a963dec316166227 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 16 Jun 2022 16:53:23 +0000 Subject: [PATCH 11/14] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2022-06-16-16-53-22.gh-issue-93911.RDwIiK.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-06-16-16-53-22.gh-issue-93911.RDwIiK.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-06-16-16-53-22.gh-issue-93911.RDwIiK.rst b/Misc/NEWS.d/next/Core and Builtins/2022-06-16-16-53-22.gh-issue-93911.RDwIiK.rst new file mode 100644 index 00000000000000..9efa994c1916dd --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-06-16-16-53-22.gh-issue-93911.RDwIiK.rst @@ -0,0 +1 @@ +Specialize ``LOAD_ATTR`` for ``property()`` attributes. From 626bfa147bec5b76d4f6d291b4194e6c506b72ae Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Fri, 17 Jun 2022 20:54:49 +0800 Subject: [PATCH 12/14] fix up stats and deopt --- Python/ceval.c | 1 + Python/specialize.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Python/ceval.c b/Python/ceval.c index f851505966502e..7c937c9b39fd72 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3651,6 +3651,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(LOAD_ATTR_PROPERTY) { assert(cframe.use_tracing == 0); + DEOPT_IF(tstate->interp->eval_frame, LOAD_ATTR); _PyLoadMethodCache *cache = (_PyLoadMethodCache *)next_instr; PyObject *owner = TOP(); diff --git a/Python/specialize.c b/Python/specialize.c index a0a7f4355a4f9a..267e9ae56d9125 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -706,10 +706,14 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1); assert(Py_TYPE(descr) == &PyProperty_Type); PyObject *fget = ((_PyPropertyObject *)descr)->prop_get; - if (fget == NULL || Py_TYPE(fget) != &PyFunction_Type) { + if (fget == NULL) { SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR); goto fail; } + if (Py_TYPE(fget) != &PyFunction_Type) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY); + goto fail; + } PyFunctionObject *func = (PyFunctionObject *)fget; PyCodeObject *fcode = (PyCodeObject *)func->func_code; int kind = function_kind(fcode); From 4786bacc4ba7ecf60345b08d7c5527bd71c56f1e Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Fri, 17 Jun 2022 22:06:04 +0800 Subject: [PATCH 13/14] Use 32 bit func_version --- Python/ceval.c | 4 +++- Python/specialize.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Python/ceval.c b/Python/ceval.c index 7c937c9b39fd72..9cd36bf0cebae3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3661,7 +3661,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int assert(type_version != 0); PyObject *fget = read_obj(cache->descr); PyFunctionObject *f = (PyFunctionObject *)fget; - DEOPT_IF(f->func_version != cache->keys_version[0], LOAD_ATTR); + 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; assert(code->co_argcount == 1); STAT_INC(LOAD_ATTR, hit); diff --git a/Python/specialize.c b/Python/specialize.c index 267e9ae56d9125..4b8530840c2559 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -732,7 +732,7 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) SPEC_FAIL_OUT_OF_VERSIONS : SPEC_FAIL_OUT_OF_RANGE); goto fail; } - lm_cache->keys_version[0] = version; + write_u32(lm_cache->keys_version, version); assert(type->tp_version_tag != 0); write_u32(lm_cache->type_version, type->tp_version_tag); /* borrowed */ From 9f32d037ee99f37979f5baa527076757e7962964 Mon Sep 17 00:00:00 2001 From: Ken Jin Date: Fri, 17 Jun 2022 22:14:55 +0800 Subject: [PATCH 14/14] remove the version check --- Python/specialize.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Python/specialize.c b/Python/specialize.c index 4b8530840c2559..2783c0da360ee1 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -726,10 +726,8 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) goto fail; } int version = _PyFunction_GetVersionForCurrentState(func); - if (version == 0 || version != (uint16_t)version) { - SPECIALIZATION_FAIL(LOAD_ATTR, - version == 0 ? - SPEC_FAIL_OUT_OF_VERSIONS : SPEC_FAIL_OUT_OF_RANGE); + if (version == 0) { + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS); goto fail; } write_u32(lm_cache->keys_version, version); 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