summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/abstract_interp_cases.c.h41
-rw-r--r--Python/bytecodes.c190
-rw-r--r--Python/ceval.c2
-rw-r--r--Python/ceval_macros.h5
-rw-r--r--Python/compile.c22
-rw-r--r--Python/executor_cases.c.h140
-rw-r--r--Python/flowgraph.c2
-rw-r--r--Python/generated_cases.c.h173
-rw-r--r--Python/instrumentation.c5
-rw-r--r--Python/opcode_targets.h28
-rw-r--r--Python/specialize.c82
11 files changed, 444 insertions, 246 deletions
diff --git a/Python/abstract_interp_cases.c.h b/Python/abstract_interp_cases.c.h
index 1b96ca1..5a3848c 100644
--- a/Python/abstract_interp_cases.c.h
+++ b/Python/abstract_interp_cases.c.h
@@ -661,21 +661,21 @@
break;
}
- case CALL_NO_KW_TYPE_1: {
+ case CALL_TYPE_1: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
break;
}
- case CALL_NO_KW_STR_1: {
+ case CALL_STR_1: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
break;
}
- case CALL_NO_KW_TUPLE_1: {
+ case CALL_TUPLE_1: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
@@ -687,49 +687,70 @@
break;
}
- case CALL_NO_KW_BUILTIN_O: {
+ case CALL_BUILTIN_CLASS: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
break;
}
- case CALL_NO_KW_BUILTIN_FAST: {
+ case CALL_BUILTIN_O: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
break;
}
- case CALL_NO_KW_LEN: {
+ case CALL_BUILTIN_FAST: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
break;
}
- case CALL_NO_KW_ISINSTANCE: {
+ case CALL_BUILTIN_FAST_WITH_KEYWORDS: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
break;
}
- case CALL_NO_KW_METHOD_DESCRIPTOR_O: {
+ case CALL_LEN: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
break;
}
- case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS: {
+ case CALL_ISINSTANCE: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
break;
}
- case CALL_NO_KW_METHOD_DESCRIPTOR_FAST: {
+ case CALL_METHOD_DESCRIPTOR_O: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_METHOD_DESCRIPTOR_NOARGS: {
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
+ break;
+ }
+
+ case CALL_METHOD_DESCRIPTOR_FAST: {
STACK_SHRINK(oparg);
STACK_SHRINK(1);
PARTITIONNODE_OVERWRITE((_Py_PARTITIONNODE_t *)PARTITIONNODE_NULLROOT, PEEK(-(-1)), true);
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 08d91b5..e5be62c 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -74,7 +74,6 @@ dummy_func(
unsigned int oparg,
_Py_CODEUNIT *next_instr,
PyObject **stack_pointer,
- PyObject *kwnames,
int throwflag,
PyObject *args[]
)
@@ -2854,12 +2853,6 @@ dummy_func(
self = owner;
}
- inst(KW_NAMES, (--)) {
- ASSERT_KWNAMES_IS_NULL();
- assert(oparg < PyTuple_GET_SIZE(FRAME_CO_CONSTS));
- kwnames = GETITEM(FRAME_CO_CONSTS, oparg);
- }
-
inst(INSTRUMENTED_CALL, ( -- )) {
int is_meth = PEEK(oparg + 1) != NULL;
int total_args = oparg + is_meth;
@@ -2876,36 +2869,31 @@ dummy_func(
}
// Cache layout: counter/1, func_version/2
- // Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members!
+ // CALL_INTRINSIC_1/2, CALL_KW, and CALL_FUNCTION_EX aren't members!
family(CALL, INLINE_CACHE_ENTRIES_CALL) = {
CALL_BOUND_METHOD_EXACT_ARGS,
CALL_PY_EXACT_ARGS,
CALL_PY_WITH_DEFAULTS,
- CALL_NO_KW_TYPE_1,
- CALL_NO_KW_STR_1,
- CALL_NO_KW_TUPLE_1,
+ CALL_TYPE_1,
+ CALL_STR_1,
+ CALL_TUPLE_1,
CALL_BUILTIN_CLASS,
- CALL_NO_KW_BUILTIN_O,
- CALL_NO_KW_BUILTIN_FAST,
+ CALL_BUILTIN_O,
+ CALL_BUILTIN_FAST,
CALL_BUILTIN_FAST_WITH_KEYWORDS,
- CALL_NO_KW_LEN,
- CALL_NO_KW_ISINSTANCE,
- CALL_NO_KW_LIST_APPEND,
- CALL_NO_KW_METHOD_DESCRIPTOR_O,
+ CALL_LEN,
+ CALL_ISINSTANCE,
+ CALL_LIST_APPEND,
+ CALL_METHOD_DESCRIPTOR_O,
CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
- CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
- CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
- CALL_NO_KW_ALLOC_AND_ENTER_INIT,
+ CALL_METHOD_DESCRIPTOR_NOARGS,
+ CALL_METHOD_DESCRIPTOR_FAST,
+ CALL_ALLOC_AND_ENTER_INIT,
};
- // On entry, the stack is either
- // [NULL, callable, arg1, arg2, ...]
- // or
- // [method, self, arg1, arg2, ...]
- // (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.)
- // On exit, the stack is [result].
// When calling Python, inline the call using DISPATCH_INLINED().
inst(CALL, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
+ // oparg counts all of the args, but *not* self:
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -2915,7 +2903,7 @@ dummy_func(
_PyCallCache *cache = (_PyCallCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
next_instr--;
- _Py_Specialize_Call(callable, next_instr, total_args, kwnames);
+ _Py_Specialize_Call(callable, next_instr, total_args);
DISPATCH_SAME_OPARG();
}
STAT_INC(CALL, deferred);
@@ -2931,7 +2919,6 @@ dummy_func(
Py_DECREF(callable);
callable = method;
}
- int positional_args = total_args - KWNAMES_LEN();
// Check if the call can be inlined or not
if (Py_TYPE(callable) == &PyFunction_Type &&
tstate->interp->eval_frame == NULL &&
@@ -2941,9 +2928,8 @@ dummy_func(
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, (PyFunctionObject *)callable, locals,
- args, positional_args, kwnames
+ args, total_args, NULL
);
- kwnames = NULL;
// Manipulate stack directly since we leave using DISPATCH_INLINED().
STACK_SHRINK(oparg + 2);
// The frame has stolen all the arguments from the stack,
@@ -2958,8 +2944,8 @@ dummy_func(
/* Callable is not a normal Python function */
res = PyObject_Vectorcall(
callable, args,
- positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
- kwnames);
+ total_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ NULL);
if (opcode == INSTRUMENTED_CALL) {
PyObject *arg = total_args == 0 ?
&_PyInstrumentation_MISSING : args[0];
@@ -2977,7 +2963,6 @@ dummy_func(
}
}
}
- kwnames = NULL;
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
Py_DECREF(callable);
for (int i = 0; i < total_args; i++) {
@@ -3006,7 +2991,6 @@ dummy_func(
}
op(_CHECK_FUNCTION_EXACT_ARGS, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
- ASSERT_KWNAMES_IS_NULL();
DEOPT_IF(!PyFunction_Check(callable), CALL);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != func_version, CALL);
@@ -3081,7 +3065,6 @@ dummy_func(
_PUSH_FRAME;
inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, callable, self_or_null, args[oparg] -- unused)) {
- ASSERT_KWNAMES_IS_NULL();
DEOPT_IF(tstate->interp->eval_frame, CALL);
int argcount = oparg;
if (self_or_null != NULL) {
@@ -3116,8 +3099,7 @@ dummy_func(
DISPATCH_INLINED(new_frame);
}
- inst(CALL_NO_KW_TYPE_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_TYPE_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) {
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
PyObject *obj = args[0];
@@ -3128,8 +3110,7 @@ dummy_func(
Py_DECREF(&PyType_Type); // I.e., callable
}
- inst(CALL_NO_KW_STR_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_STR_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) {
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL);
@@ -3142,8 +3123,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- inst(CALL_NO_KW_TUPLE_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_TUPLE_1, (unused/1, unused/2, callable, null, args[oparg] -- res)) {
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL);
@@ -3156,13 +3136,12 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- inst(CALL_NO_KW_ALLOC_AND_ENTER_INIT, (unused/1, unused/2, callable, null, args[oparg] -- unused)) {
+ inst(CALL_ALLOC_AND_ENTER_INIT, (unused/1, unused/2, callable, null, args[oparg] -- unused)) {
/* This instruction does the following:
* 1. Creates the object (by calling ``object.__new__``)
* 2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``)
* 3. Pushes the frame for ``__init__`` to the frame stack
* */
- ASSERT_KWNAMES_IS_NULL();
_PyCallCache *cache = (_PyCallCache *)next_instr;
DEOPT_IF(null != NULL, CALL);
DEOPT_IF(!PyType_Check(callable), CALL);
@@ -3225,14 +3204,11 @@ dummy_func(
args--;
total_args++;
}
- int kwnames_len = KWNAMES_LEN();
DEOPT_IF(!PyType_Check(callable), CALL);
PyTypeObject *tp = (PyTypeObject *)callable;
DEOPT_IF(tp->tp_vectorcall == NULL, CALL);
STAT_INC(CALL, hit);
- res = tp->tp_vectorcall((PyObject *)tp, args,
- total_args - kwnames_len, kwnames);
- kwnames = NULL;
+ res = tp->tp_vectorcall((PyObject *)tp, args, total_args, NULL);
/* Free the arguments. */
for (int i = 0; i < total_args; i++) {
Py_DECREF(args[i]);
@@ -3242,9 +3218,8 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- inst(CALL_NO_KW_BUILTIN_O, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
+ inst(CALL_BUILTIN_O, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
/* Builtin METH_O functions */
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -3271,9 +3246,8 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- inst(CALL_NO_KW_BUILTIN_FAST, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
+ inst(CALL_BUILTIN_FAST, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
/* Builtin METH_FASTCALL functions, without keywords */
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -3319,14 +3293,8 @@ dummy_func(
_PyCFunctionFastWithKeywords cfunc =
(_PyCFunctionFastWithKeywords)(void(*)(void))
PyCFunction_GET_FUNCTION(callable);
- res = cfunc(
- PyCFunction_GET_SELF(callable),
- args,
- total_args - KWNAMES_LEN(),
- kwnames
- );
+ res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
- kwnames = NULL;
/* Free the arguments. */
for (int i = 0; i < total_args; i++) {
@@ -3337,8 +3305,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- inst(CALL_NO_KW_LEN, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_LEN, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
/* len(o) */
int total_args = oparg;
if (self_or_null != NULL) {
@@ -3362,8 +3329,7 @@ dummy_func(
ERROR_IF(res == NULL, error);
}
- inst(CALL_NO_KW_ISINSTANCE, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_ISINSTANCE, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
/* isinstance(o, o2) */
int total_args = oparg;
if (self_or_null != NULL) {
@@ -3390,8 +3356,7 @@ dummy_func(
}
// This is secretly a super-instruction
- inst(CALL_NO_KW_LIST_APPEND, (unused/1, unused/2, callable, self, args[oparg] -- unused)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_LIST_APPEND, (unused/1, unused/2, callable, self, args[oparg] -- unused)) {
assert(oparg == 1);
PyInterpreterState *interp = tstate->interp;
DEOPT_IF(callable != interp->callable_cache.list_append, CALL);
@@ -3410,8 +3375,7 @@ dummy_func(
DISPATCH();
}
- inst(CALL_NO_KW_METHOD_DESCRIPTOR_O, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_METHOD_DESCRIPTOR_O, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -3459,9 +3423,8 @@ dummy_func(
int nargs = total_args - 1;
_PyCFunctionFastWithKeywords cfunc =
(_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
- res = cfunc(self, args + 1, nargs - KWNAMES_LEN(), kwnames);
+ res = cfunc(self, args + 1, nargs, NULL);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
- kwnames = NULL;
/* Free the arguments. */
for (int i = 0; i < total_args; i++) {
@@ -3472,8 +3435,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- inst(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_METHOD_DESCRIPTOR_NOARGS, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
assert(oparg == 0 || oparg == 1);
int total_args = oparg;
if (self_or_null != NULL) {
@@ -3503,8 +3465,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
- inst(CALL_NO_KW_METHOD_DESCRIPTOR_FAST, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
- ASSERT_KWNAMES_IS_NULL();
+ inst(CALL_METHOD_DESCRIPTOR_FAST, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -3532,6 +3493,91 @@ dummy_func(
CHECK_EVAL_BREAKER();
}
+ inst(INSTRUMENTED_CALL_KW, ( -- )) {
+ int is_meth = PEEK(oparg + 2) != NULL;
+ int total_args = oparg + is_meth;
+ PyObject *function = PEEK(oparg + 3);
+ PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING
+ : PEEK(total_args + 1);
+ int err = _Py_call_instrumentation_2args(
+ tstate, PY_MONITORING_EVENT_CALL,
+ frame, next_instr - 1, function, arg);
+ ERROR_IF(err, error);
+ GO_TO_INSTRUCTION(CALL_KW);
+ }
+
+ inst(CALL_KW, (callable, self_or_null, args[oparg], kwnames -- res)) {
+ // oparg counts all of the args, but *not* self:
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ if (self_or_null == NULL && Py_TYPE(callable) == &PyMethod_Type) {
+ args--;
+ total_args++;
+ PyObject *self = ((PyMethodObject *)callable)->im_self;
+ args[0] = Py_NewRef(self);
+ PyObject *method = ((PyMethodObject *)callable)->im_func;
+ args[-1] = Py_NewRef(method);
+ Py_DECREF(callable);
+ callable = method;
+ }
+ int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames);
+ // Check if the call can be inlined or not
+ if (Py_TYPE(callable) == &PyFunction_Type &&
+ tstate->interp->eval_frame == NULL &&
+ ((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall)
+ {
+ int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
+ PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
+ tstate, (PyFunctionObject *)callable, locals,
+ args, positional_args, kwnames
+ );
+ Py_DECREF(kwnames);
+ // Manipulate stack directly since we leave using DISPATCH_INLINED().
+ STACK_SHRINK(oparg + 3);
+ // The frame has stolen all the arguments from the stack,
+ // so there is no need to clean them up.
+ if (new_frame == NULL) {
+ goto error;
+ }
+ frame->return_offset = 0;
+ DISPATCH_INLINED(new_frame);
+ }
+ /* Callable is not a normal Python function */
+ res = PyObject_Vectorcall(
+ callable, args,
+ positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ kwnames);
+ if (opcode == INSTRUMENTED_CALL_KW) {
+ PyObject *arg = total_args == 0 ?
+ &_PyInstrumentation_MISSING : args[0];
+ if (res == NULL) {
+ _Py_call_instrumentation_exc2(
+ tstate, PY_MONITORING_EVENT_C_RAISE,
+ frame, next_instr-1, callable, arg);
+ }
+ else {
+ int err = _Py_call_instrumentation_2args(
+ tstate, PY_MONITORING_EVENT_C_RETURN,
+ frame, next_instr-1, callable, arg);
+ if (err < 0) {
+ Py_CLEAR(res);
+ }
+ }
+ }
+ Py_DECREF(kwnames);
+ assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+ Py_DECREF(callable);
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ ERROR_IF(res == NULL, error);
+ CHECK_EVAL_BREAKER();
+ }
+
inst(INSTRUMENTED_CALL_FUNCTION_EX, ( -- )) {
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
}
diff --git a/Python/ceval.c b/Python/ceval.c
index b02bf60..cae29e0 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -678,7 +678,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
#endif
_PyInterpreterFrame entry_frame;
- PyObject *kwnames = NULL; // Borrowed reference. Reset by CALL instructions.
@@ -840,7 +839,6 @@ pop_2_error:
pop_1_error:
STACK_SHRINK(1);
error:
- kwnames = NULL;
/* Double-check exception status. */
#ifdef NDEBUG
if (!_PyErr_Occurred(tstate)) {
diff --git a/Python/ceval_macros.h b/Python/ceval_macros.h
index f5d9155..012750d 100644
--- a/Python/ceval_macros.h
+++ b/Python/ceval_macros.h
@@ -311,9 +311,6 @@ GETITEM(PyObject *v, Py_ssize_t i) {
" in enclosing scope"
#define NAME_ERROR_MSG "name '%.200s' is not defined"
-#define KWNAMES_LEN() \
- (kwnames == NULL ? 0 : ((int)PyTuple_GET_SIZE(kwnames)))
-
#define DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dval, result) \
do { \
if (Py_REFCNT(left) == 1) { \
@@ -356,8 +353,6 @@ static const convertion_func_ptr CONVERSION_FUNCTIONS[4] = {
[FVC_ASCII] = PyObject_ASCII
};
-#define ASSERT_KWNAMES_IS_NULL() assert(kwnames == NULL)
-
// GH-89279: Force inlining by using a macro.
#if defined(_MSC_VER) && SIZEOF_INT == 4
#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) (assert(sizeof((ATOMIC_VAL)->_value) == 4), *((volatile int*)&((ATOMIC_VAL)->_value)))
diff --git a/Python/compile.c b/Python/compile.c
index 1f08e46..b05c1ad 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -4982,9 +4982,13 @@ maybe_optimize_method_call(struct compiler *c, expr_ty e)
VISIT_SEQ(c, keyword, kwds);
RETURN_IF_ERROR(
compiler_call_simple_kw_helper(c, loc, kwds, kwdsl));
+ loc = update_start_location_to_match_attr(c, LOC(e), meth);
+ ADDOP_I(c, loc, CALL_KW, argsl + kwdsl);
+ }
+ else {
+ loc = update_start_location_to_match_attr(c, LOC(e), meth);
+ ADDOP_I(c, loc, CALL, argsl);
}
- loc = update_start_location_to_match_attr(c, LOC(e), meth);
- ADDOP_I(c, loc, CALL, argsl + kwdsl);
return 1;
}
@@ -5150,7 +5154,7 @@ compiler_subkwargs(struct compiler *c, location loc,
}
/* Used by compiler_call_helper and maybe_optimize_method_call to emit
- * KW_NAMES before CALL.
+ * a tuple of keyword names before CALL.
*/
static int
compiler_call_simple_kw_helper(struct compiler *c, location loc,
@@ -5165,12 +5169,7 @@ compiler_call_simple_kw_helper(struct compiler *c, location loc,
keyword_ty kw = asdl_seq_GET(keywords, i);
PyTuple_SET_ITEM(names, i, Py_NewRef(kw->arg));
}
- Py_ssize_t arg = compiler_add_const(c->c_const_cache, c->u, names);
- if (arg < 0) {
- return ERROR;
- }
- Py_DECREF(names);
- ADDOP_I(c, loc, KW_NAMES, arg);
+ ADDOP_LOAD_CONST_NEW(c, loc, names);
return SUCCESS;
}
@@ -5215,8 +5214,11 @@ compiler_call_helper(struct compiler *c, location loc,
VISIT_SEQ(c, keyword, keywords);
RETURN_IF_ERROR(
compiler_call_simple_kw_helper(c, loc, keywords, nkwelts));
+ ADDOP_I(c, loc, CALL_KW, n + nelts + nkwelts);
+ }
+ else {
+ ADDOP_I(c, loc, CALL, n + nelts);
}
- ADDOP_I(c, loc, CALL, n + nelts + nkwelts);
return SUCCESS;
ex_call:
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 8f3febe..befb972 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -2256,7 +2256,6 @@
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
uint32_t func_version = (uint32_t)operand;
- ASSERT_KWNAMES_IS_NULL();
DEOPT_IF(!PyFunction_Check(callable), CALL);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != func_version, CALL);
@@ -2324,7 +2323,7 @@
break;
}
- case CALL_NO_KW_TYPE_1: {
+ case CALL_TYPE_1: {
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -2332,7 +2331,6 @@
args = stack_pointer - oparg;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
PyObject *obj = args[0];
@@ -2347,7 +2345,7 @@
break;
}
- case CALL_NO_KW_STR_1: {
+ case CALL_STR_1: {
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -2355,7 +2353,6 @@
args = stack_pointer - oparg;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL);
@@ -2372,7 +2369,7 @@
break;
}
- case CALL_NO_KW_TUPLE_1: {
+ case CALL_TUPLE_1: {
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -2380,7 +2377,6 @@
args = stack_pointer - oparg;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL);
@@ -2411,7 +2407,38 @@
break;
}
- case CALL_NO_KW_BUILTIN_O: {
+ case CALL_BUILTIN_CLASS: {
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *callable;
+ PyObject *res;
+ args = stack_pointer - oparg;
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ DEOPT_IF(!PyType_Check(callable), CALL);
+ PyTypeObject *tp = (PyTypeObject *)callable;
+ DEOPT_IF(tp->tp_vectorcall == NULL, CALL);
+ STAT_INC(CALL, hit);
+ res = tp->tp_vectorcall((PyObject *)tp, args, total_args, NULL);
+ /* Free the arguments. */
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ Py_DECREF(tp);
+ if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ CHECK_EVAL_BREAKER();
+ break;
+ }
+
+ case CALL_BUILTIN_O: {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2420,7 +2447,6 @@
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
/* Builtin METH_O functions */
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -2451,7 +2477,7 @@
break;
}
- case CALL_NO_KW_BUILTIN_FAST: {
+ case CALL_BUILTIN_FAST: {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2460,7 +2486,6 @@
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
/* Builtin METH_FASTCALL functions, without keywords */
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -2495,7 +2520,45 @@
break;
}
- case CALL_NO_KW_LEN: {
+ case CALL_BUILTIN_FAST_WITH_KEYWORDS: {
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *callable;
+ PyObject *res;
+ args = stack_pointer - oparg;
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ /* Builtin METH_FASTCALL | METH_KEYWORDS functions */
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
+ DEOPT_IF(PyCFunction_GET_FLAGS(callable) !=
+ (METH_FASTCALL | METH_KEYWORDS), CALL);
+ STAT_INC(CALL, hit);
+ /* res = func(self, args, nargs, kwnames) */
+ _PyCFunctionFastWithKeywords cfunc =
+ (_PyCFunctionFastWithKeywords)(void(*)(void))
+ PyCFunction_GET_FUNCTION(callable);
+ res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL);
+ assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+
+ /* Free the arguments. */
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ Py_DECREF(callable);
+ if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ CHECK_EVAL_BREAKER();
+ break;
+ }
+
+ case CALL_LEN: {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2503,7 +2566,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
/* len(o) */
int total_args = oparg;
if (self_or_null != NULL) {
@@ -2531,7 +2593,7 @@
break;
}
- case CALL_NO_KW_ISINSTANCE: {
+ case CALL_ISINSTANCE: {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2539,7 +2601,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
/* isinstance(o, o2) */
int total_args = oparg;
if (self_or_null != NULL) {
@@ -2569,7 +2630,7 @@
break;
}
- case CALL_NO_KW_METHOD_DESCRIPTOR_O: {
+ case CALL_METHOD_DESCRIPTOR_O: {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2577,7 +2638,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -2612,7 +2672,47 @@
break;
}
- case CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS: {
+ case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: {
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *callable;
+ PyObject *res;
+ args = stack_pointer - oparg;
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ PyMethodDescrObject *method = (PyMethodDescrObject *)callable;
+ DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL);
+ PyMethodDef *meth = method->d_method;
+ DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), CALL);
+ PyTypeObject *d_type = method->d_common.d_type;
+ PyObject *self = args[0];
+ DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL);
+ STAT_INC(CALL, hit);
+ int nargs = total_args - 1;
+ _PyCFunctionFastWithKeywords cfunc =
+ (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
+ res = cfunc(self, args + 1, nargs, NULL);
+ assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+
+ /* Free the arguments. */
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ Py_DECREF(callable);
+ if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error; }
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(1);
+ stack_pointer[-1] = res;
+ CHECK_EVAL_BREAKER();
+ break;
+ }
+
+ case CALL_METHOD_DESCRIPTOR_NOARGS: {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2620,7 +2720,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 0 || oparg == 1);
int total_args = oparg;
if (self_or_null != NULL) {
@@ -2654,7 +2753,7 @@
break;
}
- case CALL_NO_KW_METHOD_DESCRIPTOR_FAST: {
+ case CALL_METHOD_DESCRIPTOR_FAST: {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -2662,7 +2761,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
diff --git a/Python/flowgraph.c b/Python/flowgraph.c
index 55b871d..44858b9 100644
--- a/Python/flowgraph.c
+++ b/Python/flowgraph.c
@@ -1624,8 +1624,6 @@ optimize_basic_block(PyObject *const_cache, basicblock *bb, PyObject *consts)
INSTR_SET_OP0(inst, NOP);
}
break;
- case KW_NAMES:
- break;
case LOAD_GLOBAL:
if (nextop == PUSH_NULL && (oparg & 1) == 0) {
INSTR_SET_OP1(inst, LOAD_GLOBAL, oparg | 1);
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 9742c95..fff47a1 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -3688,13 +3688,6 @@
DISPATCH();
}
- TARGET(KW_NAMES) {
- ASSERT_KWNAMES_IS_NULL();
- assert(oparg < PyTuple_GET_SIZE(FRAME_CO_CONSTS));
- kwnames = GETITEM(FRAME_CO_CONSTS, oparg);
- DISPATCH();
- }
-
TARGET(INSTRUMENTED_CALL) {
int is_meth = PEEK(oparg + 1) != NULL;
int total_args = oparg + is_meth;
@@ -3720,6 +3713,7 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
+ // oparg counts all of the args, but *not* self:
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -3729,7 +3723,7 @@
_PyCallCache *cache = (_PyCallCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
next_instr--;
- _Py_Specialize_Call(callable, next_instr, total_args, kwnames);
+ _Py_Specialize_Call(callable, next_instr, total_args);
DISPATCH_SAME_OPARG();
}
STAT_INC(CALL, deferred);
@@ -3745,7 +3739,6 @@
Py_DECREF(callable);
callable = method;
}
- int positional_args = total_args - KWNAMES_LEN();
// Check if the call can be inlined or not
if (Py_TYPE(callable) == &PyFunction_Type &&
tstate->interp->eval_frame == NULL &&
@@ -3755,9 +3748,8 @@
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, (PyFunctionObject *)callable, locals,
- args, positional_args, kwnames
+ args, total_args, NULL
);
- kwnames = NULL;
// Manipulate stack directly since we leave using DISPATCH_INLINED().
STACK_SHRINK(oparg + 2);
// The frame has stolen all the arguments from the stack,
@@ -3772,8 +3764,8 @@
/* Callable is not a normal Python function */
res = PyObject_Vectorcall(
callable, args,
- positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
- kwnames);
+ total_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ NULL);
if (opcode == INSTRUMENTED_CALL) {
PyObject *arg = total_args == 0 ?
&_PyInstrumentation_MISSING : args[0];
@@ -3791,7 +3783,6 @@
}
}
}
- kwnames = NULL;
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
Py_DECREF(callable);
for (int i = 0; i < total_args; i++) {
@@ -3839,7 +3830,6 @@
callable = func;
{
uint32_t func_version = read_u32(&next_instr[1].cache);
- ASSERT_KWNAMES_IS_NULL();
DEOPT_IF(!PyFunction_Check(callable), CALL);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != func_version, CALL);
@@ -3918,7 +3908,6 @@
callable = stack_pointer[-2 - oparg];
{
uint32_t func_version = read_u32(&next_instr[1].cache);
- ASSERT_KWNAMES_IS_NULL();
DEOPT_IF(!PyFunction_Check(callable), CALL);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != func_version, CALL);
@@ -3991,7 +3980,6 @@
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
uint32_t func_version = read_u32(&next_instr[1].cache);
- ASSERT_KWNAMES_IS_NULL();
DEOPT_IF(tstate->interp->eval_frame, CALL);
int argcount = oparg;
if (self_or_null != NULL) {
@@ -4026,7 +4014,7 @@
DISPATCH_INLINED(new_frame);
}
- TARGET(CALL_NO_KW_TYPE_1) {
+ TARGET(CALL_TYPE_1) {
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -4034,7 +4022,6 @@
args = stack_pointer - oparg;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
PyObject *obj = args[0];
@@ -4050,7 +4037,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_STR_1) {
+ TARGET(CALL_STR_1) {
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -4058,7 +4045,6 @@
args = stack_pointer - oparg;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL);
@@ -4076,7 +4062,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_TUPLE_1) {
+ TARGET(CALL_TUPLE_1) {
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -4084,7 +4070,6 @@
args = stack_pointer - oparg;
null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL);
@@ -4102,7 +4087,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_ALLOC_AND_ENTER_INIT) {
+ TARGET(CALL_ALLOC_AND_ENTER_INIT) {
PyObject **args;
PyObject *null;
PyObject *callable;
@@ -4114,7 +4099,6 @@
* 2. Pushes a shim frame to the frame stack (to cleanup after ``__init__``)
* 3. Pushes the frame for ``__init__`` to the frame stack
* */
- ASSERT_KWNAMES_IS_NULL();
_PyCallCache *cache = (_PyCallCache *)next_instr;
DEOPT_IF(null != NULL, CALL);
DEOPT_IF(!PyType_Check(callable), CALL);
@@ -4188,14 +4172,11 @@
args--;
total_args++;
}
- int kwnames_len = KWNAMES_LEN();
DEOPT_IF(!PyType_Check(callable), CALL);
PyTypeObject *tp = (PyTypeObject *)callable;
DEOPT_IF(tp->tp_vectorcall == NULL, CALL);
STAT_INC(CALL, hit);
- res = tp->tp_vectorcall((PyObject *)tp, args,
- total_args - kwnames_len, kwnames);
- kwnames = NULL;
+ res = tp->tp_vectorcall((PyObject *)tp, args, total_args, NULL);
/* Free the arguments. */
for (int i = 0; i < total_args; i++) {
Py_DECREF(args[i]);
@@ -4210,7 +4191,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_BUILTIN_O) {
+ TARGET(CALL_BUILTIN_O) {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -4219,7 +4200,6 @@
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
/* Builtin METH_O functions */
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -4251,7 +4231,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_BUILTIN_FAST) {
+ TARGET(CALL_BUILTIN_FAST) {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -4260,7 +4240,6 @@
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
/* Builtin METH_FASTCALL functions, without keywords */
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -4318,14 +4297,8 @@
_PyCFunctionFastWithKeywords cfunc =
(_PyCFunctionFastWithKeywords)(void(*)(void))
PyCFunction_GET_FUNCTION(callable);
- res = cfunc(
- PyCFunction_GET_SELF(callable),
- args,
- total_args - KWNAMES_LEN(),
- kwnames
- );
+ res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
- kwnames = NULL;
/* Free the arguments. */
for (int i = 0; i < total_args; i++) {
@@ -4341,7 +4314,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_LEN) {
+ TARGET(CALL_LEN) {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -4349,7 +4322,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
/* len(o) */
int total_args = oparg;
if (self_or_null != NULL) {
@@ -4378,7 +4350,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_ISINSTANCE) {
+ TARGET(CALL_ISINSTANCE) {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -4386,7 +4358,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
/* isinstance(o, o2) */
int total_args = oparg;
if (self_or_null != NULL) {
@@ -4417,14 +4388,13 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_LIST_APPEND) {
+ TARGET(CALL_LIST_APPEND) {
PyObject **args;
PyObject *self;
PyObject *callable;
args = stack_pointer - oparg;
self = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 1);
PyInterpreterState *interp = tstate->interp;
DEOPT_IF(callable != interp->callable_cache.list_append, CALL);
@@ -4443,7 +4413,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_O) {
+ TARGET(CALL_METHOD_DESCRIPTOR_O) {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -4451,7 +4421,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -4511,9 +4480,8 @@
int nargs = total_args - 1;
_PyCFunctionFastWithKeywords cfunc =
(_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
- res = cfunc(self, args + 1, nargs - KWNAMES_LEN(), kwnames);
+ res = cfunc(self, args + 1, nargs, NULL);
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
- kwnames = NULL;
/* Free the arguments. */
for (int i = 0; i < total_args; i++) {
@@ -4529,7 +4497,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS) {
+ TARGET(CALL_METHOD_DESCRIPTOR_NOARGS) {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -4537,7 +4505,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
assert(oparg == 0 || oparg == 1);
int total_args = oparg;
if (self_or_null != NULL) {
@@ -4572,7 +4539,7 @@
DISPATCH();
}
- TARGET(CALL_NO_KW_METHOD_DESCRIPTOR_FAST) {
+ TARGET(CALL_METHOD_DESCRIPTOR_FAST) {
PyObject **args;
PyObject *self_or_null;
PyObject *callable;
@@ -4580,7 +4547,6 @@
args = stack_pointer - oparg;
self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg];
- ASSERT_KWNAMES_IS_NULL();
int total_args = oparg;
if (self_or_null != NULL) {
args--;
@@ -4613,6 +4579,105 @@
DISPATCH();
}
+ TARGET(INSTRUMENTED_CALL_KW) {
+ int is_meth = PEEK(oparg + 2) != NULL;
+ int total_args = oparg + is_meth;
+ PyObject *function = PEEK(oparg + 3);
+ PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING
+ : PEEK(total_args + 1);
+ int err = _Py_call_instrumentation_2args(
+ tstate, PY_MONITORING_EVENT_CALL,
+ frame, next_instr - 1, function, arg);
+ if (err) goto error;
+ GO_TO_INSTRUCTION(CALL_KW);
+ }
+
+ TARGET(CALL_KW) {
+ PREDICTED(CALL_KW);
+ PyObject *kwnames;
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *callable;
+ PyObject *res;
+ kwnames = stack_pointer[-1];
+ args = stack_pointer - 1 - oparg;
+ self_or_null = stack_pointer[-2 - oparg];
+ callable = stack_pointer[-3 - oparg];
+ // oparg counts all of the args, but *not* self:
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ if (self_or_null == NULL && Py_TYPE(callable) == &PyMethod_Type) {
+ args--;
+ total_args++;
+ PyObject *self = ((PyMethodObject *)callable)->im_self;
+ args[0] = Py_NewRef(self);
+ PyObject *method = ((PyMethodObject *)callable)->im_func;
+ args[-1] = Py_NewRef(method);
+ Py_DECREF(callable);
+ callable = method;
+ }
+ int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames);
+ // Check if the call can be inlined or not
+ if (Py_TYPE(callable) == &PyFunction_Type &&
+ tstate->interp->eval_frame == NULL &&
+ ((PyFunctionObject *)callable)->vectorcall == _PyFunction_Vectorcall)
+ {
+ int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
+ PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
+ tstate, (PyFunctionObject *)callable, locals,
+ args, positional_args, kwnames
+ );
+ Py_DECREF(kwnames);
+ // Manipulate stack directly since we leave using DISPATCH_INLINED().
+ STACK_SHRINK(oparg + 3);
+ // The frame has stolen all the arguments from the stack,
+ // so there is no need to clean them up.
+ if (new_frame == NULL) {
+ goto error;
+ }
+ frame->return_offset = 0;
+ DISPATCH_INLINED(new_frame);
+ }
+ /* Callable is not a normal Python function */
+ res = PyObject_Vectorcall(
+ callable, args,
+ positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ kwnames);
+ if (opcode == INSTRUMENTED_CALL_KW) {
+ PyObject *arg = total_args == 0 ?
+ &_PyInstrumentation_MISSING : args[0];
+ if (res == NULL) {
+ _Py_call_instrumentation_exc2(
+ tstate, PY_MONITORING_EVENT_C_RAISE,
+ frame, next_instr-1, callable, arg);
+ }
+ else {
+ int err = _Py_call_instrumentation_2args(
+ tstate, PY_MONITORING_EVENT_C_RETURN,
+ frame, next_instr-1, callable, arg);
+ if (err < 0) {
+ Py_CLEAR(res);
+ }
+ }
+ }
+ Py_DECREF(kwnames);
+ assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+ Py_DECREF(callable);
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ if (res == NULL) { STACK_SHRINK(oparg); goto pop_3_error; }
+ STACK_SHRINK(oparg);
+ STACK_SHRINK(2);
+ stack_pointer[-1] = res;
+ CHECK_EVAL_BREAKER();
+ DISPATCH();
+ }
+
TARGET(INSTRUMENTED_CALL_FUNCTION_EX) {
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
}
diff --git a/Python/instrumentation.c b/Python/instrumentation.c
index fee6eae..0768c82 100644
--- a/Python/instrumentation.c
+++ b/Python/instrumentation.c
@@ -37,6 +37,8 @@ static const int8_t EVENT_FOR_OPCODE[256] = {
[INSTRUMENTED_RETURN_VALUE] = PY_MONITORING_EVENT_PY_RETURN,
[CALL] = PY_MONITORING_EVENT_CALL,
[INSTRUMENTED_CALL] = PY_MONITORING_EVENT_CALL,
+ [CALL_KW] = PY_MONITORING_EVENT_CALL,
+ [INSTRUMENTED_CALL_KW] = PY_MONITORING_EVENT_CALL,
[CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL,
[INSTRUMENTED_CALL_FUNCTION_EX] = PY_MONITORING_EVENT_CALL,
[LOAD_SUPER_ATTR] = PY_MONITORING_EVENT_CALL,
@@ -69,6 +71,7 @@ static const uint8_t DE_INSTRUMENT[256] = {
[INSTRUMENTED_RETURN_VALUE] = RETURN_VALUE,
[INSTRUMENTED_RETURN_CONST] = RETURN_CONST,
[INSTRUMENTED_CALL] = CALL,
+ [INSTRUMENTED_CALL_KW] = CALL_KW,
[INSTRUMENTED_CALL_FUNCTION_EX] = CALL_FUNCTION_EX,
[INSTRUMENTED_YIELD_VALUE] = YIELD_VALUE,
[INSTRUMENTED_JUMP_FORWARD] = JUMP_FORWARD,
@@ -90,6 +93,8 @@ static const uint8_t INSTRUMENTED_OPCODES[256] = {
[INSTRUMENTED_RETURN_VALUE] = INSTRUMENTED_RETURN_VALUE,
[CALL] = INSTRUMENTED_CALL,
[INSTRUMENTED_CALL] = INSTRUMENTED_CALL,
+ [CALL_KW] = INSTRUMENTED_CALL_KW,
+ [INSTRUMENTED_CALL_KW] = INSTRUMENTED_CALL_KW,
[CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX,
[INSTRUMENTED_CALL_FUNCTION_EX] = INSTRUMENTED_CALL_FUNCTION_EX,
[YIELD_VALUE] = INSTRUMENTED_YIELD_VALUE,
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index f00eb31..bcd6ea7 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -56,6 +56,7 @@ static void *opcode_targets[256] = {
&&TARGET_CALL_FUNCTION_EX,
&&TARGET_CALL_INTRINSIC_1,
&&TARGET_CALL_INTRINSIC_2,
+ &&TARGET_CALL_KW,
&&TARGET_COMPARE_OP,
&&TARGET_CONTAINS_OP,
&&TARGET_CONVERT_VALUE,
@@ -78,7 +79,6 @@ static void *opcode_targets[256] = {
&&TARGET_JUMP_BACKWARD,
&&TARGET_JUMP_BACKWARD_NO_INTERRUPT,
&&TARGET_JUMP_FORWARD,
- &&TARGET_KW_NAMES,
&&TARGET_LIST_APPEND,
&&TARGET_LIST_EXTEND,
&&TARGET_LOAD_ATTR,
@@ -161,24 +161,24 @@ static void *opcode_targets[256] = {
&&TARGET_BINARY_SUBSCR_LIST_INT,
&&TARGET_BINARY_SUBSCR_STR_INT,
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
+ &&TARGET_CALL_ALLOC_AND_ENTER_INIT,
&&TARGET_CALL_BOUND_METHOD_EXACT_ARGS,
&&TARGET_CALL_BUILTIN_CLASS,
+ &&TARGET_CALL_BUILTIN_FAST,
&&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS,
+ &&TARGET_CALL_BUILTIN_O,
+ &&TARGET_CALL_ISINSTANCE,
+ &&TARGET_CALL_LEN,
+ &&TARGET_CALL_LIST_APPEND,
+ &&TARGET_CALL_METHOD_DESCRIPTOR_FAST,
&&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
- &&TARGET_CALL_NO_KW_ALLOC_AND_ENTER_INIT,
- &&TARGET_CALL_NO_KW_BUILTIN_FAST,
- &&TARGET_CALL_NO_KW_BUILTIN_O,
- &&TARGET_CALL_NO_KW_ISINSTANCE,
- &&TARGET_CALL_NO_KW_LEN,
- &&TARGET_CALL_NO_KW_LIST_APPEND,
- &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_FAST,
- &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS,
- &&TARGET_CALL_NO_KW_METHOD_DESCRIPTOR_O,
- &&TARGET_CALL_NO_KW_STR_1,
- &&TARGET_CALL_NO_KW_TUPLE_1,
- &&TARGET_CALL_NO_KW_TYPE_1,
+ &&TARGET_CALL_METHOD_DESCRIPTOR_NOARGS,
+ &&TARGET_CALL_METHOD_DESCRIPTOR_O,
&&TARGET_CALL_PY_EXACT_ARGS,
&&TARGET_CALL_PY_WITH_DEFAULTS,
+ &&TARGET_CALL_STR_1,
+ &&TARGET_CALL_TUPLE_1,
+ &&TARGET_CALL_TYPE_1,
&&TARGET_COMPARE_OP_FLOAT,
&&TARGET_COMPARE_OP_INT,
&&TARGET_COMPARE_OP_STR,
@@ -235,7 +235,6 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
- &&_unknown_opcode,
&&TARGET_INSTRUMENTED_RESUME,
&&TARGET_INSTRUMENTED_END_FOR,
&&TARGET_INSTRUMENTED_END_SEND,
@@ -245,6 +244,7 @@ static void *opcode_targets[256] = {
&&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR,
&&TARGET_INSTRUMENTED_FOR_ITER,
&&TARGET_INSTRUMENTED_CALL,
+ &&TARGET_INSTRUMENTED_CALL_KW,
&&TARGET_INSTRUMENTED_CALL_FUNCTION_EX,
&&TARGET_INSTRUMENTED_INSTRUCTION,
&&TARGET_INSTRUMENTED_JUMP_FORWARD,
diff --git a/Python/specialize.c b/Python/specialize.c
index 47e0bd7..d9b748c 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -473,7 +473,6 @@ _PyCode_Quicken(PyCodeObject *code)
#define SPEC_FAIL_CALL_STR 24
#define SPEC_FAIL_CALL_CLASS_NO_VECTORCALL 25
#define SPEC_FAIL_CALL_CLASS_MUTABLE 26
-#define SPEC_FAIL_CALL_KWNAMES 27
#define SPEC_FAIL_CALL_METHOD_WRAPPER 28
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
#define SPEC_FAIL_CALL_INIT_NOT_SIMPLE 30
@@ -1644,24 +1643,23 @@ get_init_for_simple_managed_python_class(PyTypeObject *tp)
}
static int
-specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
- PyObject *kwnames)
+specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
{
assert(PyType_Check(callable));
PyTypeObject *tp = _PyType_CAST(callable);
if (tp->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
int oparg = instr->op.arg;
- if (nargs == 1 && kwnames == NULL && oparg == 1) {
+ if (nargs == 1 && oparg == 1) {
if (tp == &PyUnicode_Type) {
- instr->op.code = CALL_NO_KW_STR_1;
+ instr->op.code = CALL_STR_1;
return 0;
}
else if (tp == &PyType_Type) {
- instr->op.code = CALL_NO_KW_TYPE_1;
+ instr->op.code = CALL_TYPE_1;
return 0;
}
else if (tp == &PyTuple_Type) {
- instr->op.code = CALL_NO_KW_TUPLE_1;
+ instr->op.code = CALL_TUPLE_1;
return 0;
}
}
@@ -1680,13 +1678,9 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
return -1;
}
- if (kwnames) {
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
- return -1;
- }
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
write_u32(cache->func_version, tp->tp_version_tag);
- _Py_SET_OPCODE(*instr, CALL_NO_KW_ALLOC_AND_ENTER_INIT);
+ _Py_SET_OPCODE(*instr, CALL_ALLOC_AND_ENTER_INIT);
return 0;
}
return -1;
@@ -1744,13 +1738,8 @@ meth_descr_call_fail_kind(int ml_flags)
static int
specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
- int nargs, PyObject *kwnames)
+ int nargs)
{
- if (kwnames) {
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
- return -1;
- }
-
switch (descr->d_method->ml_flags &
(METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
METH_KEYWORDS | METH_METHOD)) {
@@ -1759,7 +1748,7 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
return -1;
}
- instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS;
+ instr->op.code = CALL_METHOD_DESCRIPTOR_NOARGS;
return 0;
}
case METH_O: {
@@ -1773,14 +1762,14 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
bool pop = (next.op.code == POP_TOP);
int oparg = instr->op.arg;
if ((PyObject *)descr == list_append && oparg == 1 && pop) {
- instr->op.code = CALL_NO_KW_LIST_APPEND;
+ instr->op.code = CALL_LIST_APPEND;
return 0;
}
- instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_O;
+ instr->op.code = CALL_METHOD_DESCRIPTOR_O;
return 0;
}
case METH_FASTCALL: {
- instr->op.code = CALL_NO_KW_METHOD_DESCRIPTOR_FAST;
+ instr->op.code = CALL_METHOD_DESCRIPTOR_FAST;
return 0;
}
case METH_FASTCALL | METH_KEYWORDS: {
@@ -1794,7 +1783,7 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
static int
specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
- PyObject *kwnames, bool bound_method)
+ bool bound_method)
{
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
PyCodeObject *code = (PyCodeObject *)func->func_code;
@@ -1804,10 +1793,6 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
return -1;
}
- if (kwnames) {
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
- return -1;
- }
if (kind != SIMPLE_FUNCTION) {
SPECIALIZATION_FAIL(CALL, kind);
return -1;
@@ -1843,8 +1828,7 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
}
static int
-specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
- PyObject *kwnames)
+specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
{
if (PyCFunction_GET_FUNCTION(callable) == NULL) {
return 1;
@@ -1853,10 +1837,6 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
(METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
METH_KEYWORDS | METH_METHOD)) {
case METH_O: {
- if (kwnames) {
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
- return -1;
- }
if (nargs != 1) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
return 1;
@@ -1864,26 +1844,22 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
/* len(o) */
PyInterpreterState *interp = _PyInterpreterState_GET();
if (callable == interp->callable_cache.len) {
- instr->op.code = CALL_NO_KW_LEN;
+ instr->op.code = CALL_LEN;
return 0;
}
- instr->op.code = CALL_NO_KW_BUILTIN_O;
+ instr->op.code = CALL_BUILTIN_O;
return 0;
}
case METH_FASTCALL: {
- if (kwnames) {
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
- return -1;
- }
if (nargs == 2) {
/* isinstance(o1, o2) */
PyInterpreterState *interp = _PyInterpreterState_GET();
if (callable == interp->callable_cache.isinstance) {
- instr->op.code = CALL_NO_KW_ISINSTANCE;
+ instr->op.code = CALL_ISINSTANCE;
return 0;
}
}
- instr->op.code = CALL_NO_KW_BUILTIN_FAST;
+ instr->op.code = CALL_BUILTIN_FAST;
return 0;
}
case METH_FASTCALL | METH_KEYWORDS: {
@@ -1924,12 +1900,8 @@ call_fail_kind(PyObject *callable)
#endif // Py_STATS
-/* TODO:
- - Specialize calling classes.
-*/
void
-_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
- PyObject *kwnames)
+_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
{
assert(ENABLE_SPECIALIZATION);
assert(_PyOpcode_Caches[CALL] == INLINE_CACHE_ENTRIES_CALL);
@@ -1937,25 +1909,23 @@ _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs,
_PyCallCache *cache = (_PyCallCache *)(instr + 1);
int fail;
if (PyCFunction_CheckExact(callable)) {
- fail = specialize_c_call(callable, instr, nargs, kwnames);
+ fail = specialize_c_call(callable, instr, nargs);
}
else if (PyFunction_Check(callable)) {
- fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs,
- kwnames, false);
+ fail = specialize_py_call((PyFunctionObject *)callable, instr, nargs, false);
}
else if (PyType_Check(callable)) {
- fail = specialize_class_call(callable, instr, nargs, kwnames);
+ fail = specialize_class_call(callable, instr, nargs);
}
else if (Py_IS_TYPE(callable, &PyMethodDescr_Type)) {
- fail = specialize_method_descriptor((PyMethodDescrObject *)callable,
- instr, nargs, kwnames);
+ fail = specialize_method_descriptor((PyMethodDescrObject *)callable, instr, nargs);
}
else if (PyMethod_Check(callable)) {
PyObject *func = ((PyMethodObject *)callable)->im_func;
if (PyFunction_Check(func)) {
- fail = specialize_py_call((PyFunctionObject *)func,
- instr, nargs+1, kwnames, true);
- } else {
+ fail = specialize_py_call((PyFunctionObject *)func, instr, nargs+1, true);
+ }
+ else {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
fail = -1;
}
@@ -2491,7 +2461,7 @@ success:
}
/* Code init cleanup.
- * CALL_NO_KW_ALLOC_AND_ENTER_INIT will set up
+ * CALL_ALLOC_AND_ENTER_INIT will set up
* the frame to execute the EXIT_INIT_CHECK
* instruction.
* Ends with a RESUME so that it is not traced.