diff options
author | Mark Shannon <mark@hotpy.org> | 2021-12-15 15:03:42 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-15 15:03:42 (GMT) |
commit | 3a60bfef49b3324660a615a8e6d10710e5f669d9 (patch) | |
tree | c0b4dec8daf9f020a68be673c169d88faded0e6a /Python | |
parent | f025ae63dccf96c4a1d781a6438bd9ed1502f0a1 (diff) | |
download | cpython-3a60bfef49b3324660a615a8e6d10710e5f669d9.zip cpython-3a60bfef49b3324660a615a8e6d10710e5f669d9.tar.gz cpython-3a60bfef49b3324660a615a8e6d10710e5f669d9.tar.bz2 |
bpo-44525: Specialize for calls to type and other builtin classes with 1 argument. (GH-29942)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 35 | ||||
-rw-r--r-- | Python/opcode_targets.h | 28 | ||||
-rw-r--r-- | Python/specialize.c | 27 |
3 files changed, 74 insertions, 16 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 7932433..b9444b2 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4854,6 +4854,41 @@ check_eval_breaker: goto start_frame; } + TARGET(CALL_NO_KW_TYPE_1) { + assert(STACK_ADJUST_IS_RESET); + assert(GET_CACHE()->adaptive.original_oparg == 1); + PyObject *obj = TOP(); + PyObject *callable = SECOND(); + DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL_NO_KW); + PyObject *res = Py_NewRef(Py_TYPE(obj)); + STACK_SHRINK(1); + Py_DECREF(callable); + Py_DECREF(obj); + SET_TOP(res); + DISPATCH(); + } + + TARGET(CALL_NO_KW_BUILTIN_CLASS_1) { + assert(STACK_ADJUST_IS_RESET); + SpecializedCacheEntry *caches = GET_CACHE(); + _PyAdaptiveEntry *cache0 = &caches[0].adaptive; + assert(cache0->original_oparg == 1); + PyObject *callable = SECOND(); + PyObject *arg = TOP(); + DEOPT_IF(!PyType_Check(callable), CALL_NO_KW); + PyTypeObject *tp = (PyTypeObject *)callable; + DEOPT_IF(tp->tp_version_tag != cache0->version, CALL_NO_KW); + STACK_SHRINK(1); + PyObject *res = tp->tp_vectorcall((PyObject *)tp, stack_pointer, 1, NULL); + SET_TOP(res); + Py_DECREF(tp); + Py_DECREF(arg); + if (res == NULL) { + goto error; + } + DISPATCH(); + } + TARGET(CALL_NO_KW_BUILTIN_O) { assert(cframe.use_tracing == 0); assert(STACK_ADJUST_IS_RESET); diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index 3b2e99d..3ee0b9c 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -47,46 +47,46 @@ static void *opcode_targets[256] = { &&TARGET_CALL_NO_KW_PY_SIMPLE, &&TARGET_CALL_NO_KW_LIST_APPEND, &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O, - &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST, + &&TARGET_CALL_NO_KW_TYPE_1, &&TARGET_WITH_EXCEPT_START, &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, &&TARGET_BEFORE_WITH, &&TARGET_END_ASYNC_FOR, + &&TARGET_CALL_NO_KW_BUILTIN_CLASS_1, + &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST, &&TARGET_JUMP_ABSOLUTE_QUICK, &&TARGET_LOAD_ATTR_ADAPTIVE, &&TARGET_LOAD_ATTR_INSTANCE_VALUE, - &&TARGET_LOAD_ATTR_WITH_HINT, - &&TARGET_LOAD_ATTR_SLOT, &&TARGET_STORE_SUBSCR, &&TARGET_DELETE_SUBSCR, + &&TARGET_LOAD_ATTR_WITH_HINT, + &&TARGET_LOAD_ATTR_SLOT, &&TARGET_LOAD_ATTR_MODULE, &&TARGET_LOAD_GLOBAL_ADAPTIVE, &&TARGET_LOAD_GLOBAL_MODULE, &&TARGET_LOAD_GLOBAL_BUILTIN, - &&TARGET_LOAD_METHOD_ADAPTIVE, - &&TARGET_LOAD_METHOD_CACHED, &&TARGET_GET_ITER, &&TARGET_GET_YIELD_FROM_ITER, &&TARGET_PRINT_EXPR, &&TARGET_LOAD_BUILD_CLASS, - &&TARGET_LOAD_METHOD_CLASS, + &&TARGET_LOAD_METHOD_ADAPTIVE, &&TARGET_GET_AWAITABLE, &&TARGET_LOAD_ASSERTION_ERROR, + &&TARGET_LOAD_METHOD_CACHED, + &&TARGET_LOAD_METHOD_CLASS, &&TARGET_LOAD_METHOD_MODULE, &&TARGET_LOAD_METHOD_NO_DICT, &&TARGET_STORE_ATTR_ADAPTIVE, &&TARGET_STORE_ATTR_INSTANCE_VALUE, &&TARGET_STORE_ATTR_SLOT, - &&TARGET_STORE_ATTR_WITH_HINT, - &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_LIST_TO_TUPLE, &&TARGET_RETURN_VALUE, &&TARGET_IMPORT_STAR, &&TARGET_SETUP_ANNOTATIONS, &&TARGET_YIELD_VALUE, - &&TARGET_STORE_FAST__LOAD_FAST, + &&TARGET_STORE_ATTR_WITH_HINT, &&TARGET_PREP_RERAISE_STAR, &&TARGET_POP_EXCEPT, &&TARGET_STORE_NAME, @@ -127,20 +127,20 @@ static void *opcode_targets[256] = { &&TARGET_STORE_FAST, &&TARGET_DELETE_FAST, &&TARGET_JUMP_IF_NOT_EG_MATCH, - &&TARGET_LOAD_FAST__LOAD_CONST, + &&TARGET_LOAD_FAST__LOAD_FAST, &&TARGET_GEN_START, &&TARGET_RAISE_VARARGS, - &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_STORE_FAST__LOAD_FAST, &&TARGET_MAKE_FUNCTION, &&TARGET_BUILD_SLICE, - &&TARGET_STORE_FAST__STORE_FAST, + &&TARGET_LOAD_FAST__LOAD_CONST, &&TARGET_MAKE_CELL, &&TARGET_LOAD_CLOSURE, &&TARGET_LOAD_DEREF, &&TARGET_STORE_DEREF, &&TARGET_DELETE_DEREF, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_LOAD_CONST__LOAD_FAST, + &&TARGET_STORE_FAST__STORE_FAST, &&TARGET_CALL_FUNCTION_EX, &&_unknown_opcode, &&TARGET_EXTENDED_ARG, diff --git a/Python/specialize.c b/Python/specialize.c index bdcba46..5cf327d 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -491,8 +491,10 @@ initial_counter_value(void) { #define SPEC_FAIL_PYCFUNCTION_NOARGS 16 #define SPEC_FAIL_BAD_CALL_FLAGS 17 #define SPEC_FAIL_CLASS 18 -#define SPEC_FAIL_C_METHOD_CALL 19 -#define SPEC_FAIL_METHDESCR_NON_METHOD 20 +#define SPEC_FAIL_PYTHON_CLASS 19 +#define SPEC_FAIL_C_METHOD_CALL 20 +#define SPEC_FAIL_METHDESCR_NON_METHOD 21 +#define SPEC_FAIL_METHOD_CALL_CLASS 22 /* COMPARE_OP */ #define SPEC_FAIL_STRING_COMPARE 13 @@ -1263,6 +1265,27 @@ specialize_class_call( PyObject *callable, _Py_CODEUNIT *instr, int nargs, SpecializedCacheEntry *cache) { + assert(PyType_Check(callable)); + PyTypeObject *tp = (PyTypeObject *)callable; + if (_Py_OPCODE(instr[-1]) == PRECALL_METHOD) { + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_METHOD_CALL_CLASS); + return -1; + } + if (tp->tp_new == PyBaseObject_Type.tp_new) { + SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_PYTHON_CLASS); + return -1; + } + if (nargs == 1) { + if (tp == &PyType_Type) { + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_TYPE_1, _Py_OPARG(*instr)); + return 0; + } + if ((tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) && tp->tp_vectorcall != NULL) { + cache->adaptive.version = tp->tp_version_tag; + *instr = _Py_MAKECODEUNIT(CALL_NO_KW_BUILTIN_CLASS_1, _Py_OPARG(*instr)); + return 0; + } + } SPECIALIZATION_FAIL(CALL_NO_KW, SPEC_FAIL_CLASS); return -1; } |