diff options
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 2e15eea480..fa7b0b5a05 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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; |