mirror of
https://github.com/python/cpython.git
synced 2025-10-21 14:12:27 +00:00
bpo-26110: Add `CALL_METHOD_KW
` opcode to speedup method calls with keywords (GH-26014)
* Add CALL_METHOD_KW * Make CALL_METHOD branchless too since it shares the same code * Place parentheses in STACK_SHRINK
This commit is contained in:
parent
e4e931a67e
commit
f24afda591
10 changed files with 247 additions and 180 deletions
|
@ -1421,7 +1421,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
|||
#define STACK_SHRINK(n) do { \
|
||||
assert(n >= 0); \
|
||||
(void)(lltrace && prtrace(tstate, TOP(), "stackadj")); \
|
||||
(void)(BASIC_STACKADJ(-n)); \
|
||||
(void)(BASIC_STACKADJ(-(n))); \
|
||||
assert(STACK_LEVEL() <= co->co_stacksize); \
|
||||
} while (0)
|
||||
#define EXT_POP(STACK_POINTER) ((void)(lltrace && \
|
||||
|
@ -1431,7 +1431,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
|
|||
#define PUSH(v) BASIC_PUSH(v)
|
||||
#define POP() BASIC_POP()
|
||||
#define STACK_GROW(n) BASIC_STACKADJ(n)
|
||||
#define STACK_SHRINK(n) BASIC_STACKADJ(-n)
|
||||
#define STACK_SHRINK(n) BASIC_STACKADJ(-(n))
|
||||
#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER))
|
||||
#endif
|
||||
|
||||
|
@ -4164,16 +4164,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
|
|||
|
||||
case TARGET(CALL_METHOD): {
|
||||
/* Designed to work in tamdem with LOAD_METHOD. */
|
||||
PyObject **sp, *res, *meth;
|
||||
PyObject **sp, *res;
|
||||
int meth_found;
|
||||
|
||||
sp = stack_pointer;
|
||||
/* `meth` is NULL when LOAD_METHOD thinks that it's not
|
||||
a method call.
|
||||
|
||||
meth = PEEK(oparg + 2);
|
||||
if (meth == NULL) {
|
||||
/* `meth` is NULL when LOAD_METHOD thinks that it's not
|
||||
a method call.
|
||||
|
||||
Stack layout:
|
||||
Stack layout:
|
||||
|
||||
... | NULL | callable | arg1 | ... | argN
|
||||
^- TOP()
|
||||
|
@ -4181,15 +4179,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
|
|||
^- (-oparg-1)
|
||||
^- (-oparg-2)
|
||||
|
||||
`callable` will be POPed by call_function.
|
||||
NULL will will be POPed manually later.
|
||||
*/
|
||||
res = call_function(tstate, &trace_info, &sp, oparg, NULL);
|
||||
stack_pointer = sp;
|
||||
(void)POP(); /* POP the NULL. */
|
||||
}
|
||||
else {
|
||||
/* This is a method call. Stack layout:
|
||||
`callable` will be POPed by call_function.
|
||||
NULL will will be POPed manually later.
|
||||
If `meth` isn't NULL, it's a method call. Stack layout:
|
||||
|
||||
... | method | self | arg1 | ... | argN
|
||||
^- TOP()
|
||||
|
@ -4197,21 +4189,45 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
|
|||
^- (-oparg-1)
|
||||
^- (-oparg-2)
|
||||
|
||||
`self` and `method` will be POPed by call_function.
|
||||
We'll be passing `oparg + 1` to call_function, to
|
||||
make it accept the `self` as a first argument.
|
||||
*/
|
||||
res = call_function(tstate, &trace_info, &sp, oparg + 1, NULL);
|
||||
stack_pointer = sp;
|
||||
}
|
||||
`self` and `method` will be POPed by call_function.
|
||||
We'll be passing `oparg + 1` to call_function, to
|
||||
make it accept the `self` as a first argument.
|
||||
*/
|
||||
meth_found = (PEEK(oparg + 2) != NULL);
|
||||
res = call_function(tstate, &trace_info, &sp, oparg + meth_found, NULL);
|
||||
stack_pointer = sp;
|
||||
|
||||
STACK_SHRINK(1 - meth_found);
|
||||
PUSH(res);
|
||||
if (res == NULL)
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
}
|
||||
CHECK_EVAL_BREAKER();
|
||||
DISPATCH();
|
||||
}
|
||||
case TARGET(CALL_METHOD_KW): {
|
||||
/* Designed to work in tandem with LOAD_METHOD. Same as CALL_METHOD
|
||||
but pops TOS to get a tuple of keyword names. */
|
||||
PyObject **sp, *res;
|
||||
PyObject *names = NULL;
|
||||
int meth_found;
|
||||
|
||||
names = POP();
|
||||
|
||||
sp = stack_pointer;
|
||||
meth_found = (PEEK(oparg + 2) != NULL);
|
||||
res = call_function(tstate, &trace_info, &sp, oparg + meth_found, names);
|
||||
stack_pointer = sp;
|
||||
|
||||
STACK_SHRINK(1 - meth_found);
|
||||
PUSH(res);
|
||||
Py_DECREF(names);
|
||||
if (res == NULL) {
|
||||
goto error;
|
||||
}
|
||||
CHECK_EVAL_BREAKER();
|
||||
DISPATCH();
|
||||
}
|
||||
case TARGET(CALL_FUNCTION): {
|
||||
PREDICTED(CALL_FUNCTION);
|
||||
PyObject **sp, *res;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue