aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/specialize.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/specialize.c')
-rw-r--r--Python/specialize.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/Python/specialize.c b/Python/specialize.c
index 4a227381a8b..4fec5a36fc9 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -1904,6 +1904,33 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
return 0;
}
+
+static int
+specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
+ bool bound_method)
+{
+ _PyCallCache *cache = (_PyCallCache *)(instr + 1);
+ PyCodeObject *code = (PyCodeObject *)func->func_code;
+ int kind = function_kind(code);
+ /* Don't specialize if PEP 523 is active */
+ if (_PyInterpreterState_GET()->eval_frame) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
+ return -1;
+ }
+ if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
+ return -1;
+ }
+ int version = _PyFunction_GetVersionForCurrentState(func);
+ if (version == 0) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
+ return -1;
+ }
+ write_u32(cache->func_version, version);
+ instr->op.code = bound_method ? CALL_KW_BOUND_METHOD : CALL_KW_PY;
+ return 0;
+}
+
static int
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
{
@@ -1999,6 +2026,46 @@ _Py_Specialize_Call(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
}
}
+void
+_Py_Specialize_CallKw(_PyStackRef callable_st, _Py_CODEUNIT *instr, int nargs)
+{
+ PyObject *callable = PyStackRef_AsPyObjectBorrow(callable_st);
+
+ assert(ENABLE_SPECIALIZATION);
+ assert(_PyOpcode_Caches[CALL_KW] == INLINE_CACHE_ENTRIES_CALL_KW);
+ assert(_Py_OPCODE(*instr) != INSTRUMENTED_CALL_KW);
+ _PyCallCache *cache = (_PyCallCache *)(instr + 1);
+ int fail;
+ if (PyFunction_Check(callable)) {
+ fail = specialize_py_call_kw((PyFunctionObject *)callable, instr, nargs, false);
+ }
+ else if (PyMethod_Check(callable)) {
+ PyObject *func = ((PyMethodObject *)callable)->im_func;
+ if (PyFunction_Check(func)) {
+ fail = specialize_py_call_kw((PyFunctionObject *)func, instr, nargs, true);
+ }
+ else {
+ SPECIALIZATION_FAIL(CALL_KW, SPEC_FAIL_CALL_BOUND_METHOD);
+ fail = -1;
+ }
+ }
+ else {
+ instr->op.code = CALL_KW_NON_PY;
+ fail = 0;
+ }
+ if (fail) {
+ STAT_INC(CALL, failure);
+ assert(!PyErr_Occurred());
+ instr->op.code = CALL_KW;
+ cache->counter = adaptive_counter_backoff(cache->counter);
+ }
+ else {
+ STAT_INC(CALL, success);
+ assert(!PyErr_Occurred());
+ cache->counter = adaptive_counter_cooldown();
+ }
+}
+
#ifdef Py_STATS
static int
binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)