diff options
Diffstat (limited to 'Python/specialize.c')
-rw-r--r-- | Python/specialize.c | 67 |
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) |