diff options
author | INADA Naoki <songofacandy@gmail.com> | 2017-01-16 08:23:30 (GMT) |
---|---|---|
committer | INADA Naoki <songofacandy@gmail.com> | 2017-01-16 08:23:30 (GMT) |
commit | 015bce64b35fb9de199f41eb5a3e5b7d9d20e3c1 (patch) | |
tree | 374e77e17b8325e6db020a4ed21ceeae1bb6de71 /Python | |
parent | 510df6f2721bd6ed69716938c45cea03b2b84c99 (diff) | |
download | cpython-015bce64b35fb9de199f41eb5a3e5b7d9d20e3c1.zip cpython-015bce64b35fb9de199f41eb5a3e5b7d9d20e3c1.tar.gz cpython-015bce64b35fb9de199f41eb5a3e5b7d9d20e3c1.tar.bz2 |
Issue #26110: Add document for LOAD_METHOD and CALL_METHOD opcode.
Changed stack layout bit for "easy to explain."
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 72 |
1 files changed, 32 insertions, 40 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index b970ece..1b8cdfc 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3236,81 +3236,73 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) int meth_found = _PyObject_GetMethod(obj, name, &meth); - SET_TOP(meth); /* Replace `obj` on top; OK if NULL. */ if (meth == NULL) { /* Most likely attribute wasn't found. */ - Py_DECREF(obj); goto error; } if (meth_found) { - /* The method object is now on top of the stack. - Push `obj` back to the stack, so that the stack - layout would be: - - method | obj | arg1 | ... | argN - */ - PUSH(obj); + /* We can bypass temporary bound method object. + meth is unbound method and obj is self. + + meth | self | arg1 | ... | argN + */ + SET_TOP(meth); + PUSH(obj); // self } else { - /* Not a method (but a regular attr, or something - was returned by a descriptor protocol). Push - NULL to the top of the stack, to signal + /* meth is not an unbound method (but a regular attr, or + something was returned by a descriptor protocol). Set + the second element of the stack to NULL, to signal CALL_METHOD that it's not a method call. + + NULL | meth | arg1 | ... | argN */ + SET_TOP(NULL); Py_DECREF(obj); - PUSH(NULL); + PUSH(meth); } DISPATCH(); } TARGET(CALL_METHOD) { /* Designed to work in tamdem with LOAD_METHOD. */ - PyObject **sp, *res, *obj; + PyObject **sp, *res, *meth; sp = stack_pointer; - obj = PEEK(oparg + 1); - if (obj == NULL) { - /* `obj` is NULL when LOAD_METHOD thinks that it's not - a method call. Swap the NULL and callable. + meth = PEEK(oparg + 2); + if (meth == NULL) { + /* `meth` is NULL when LOAD_METHOD thinks that it's not + a method call. Stack layout: - ... | callable | NULL | arg1 | ... | argN - ^- TOP() - ^- (-oparg) - ^- (-oparg-1) - ^- (-oparg-2) - - after the next line it will be: - - ... | callable | callable | arg1 | ... | argN - ^- TOP() - ^- (-oparg) - ^- (-oparg-1) - ^- (-oparg-2) + ... | NULL | callable | arg1 | ... | argN + ^- TOP() + ^- (-oparg) + ^- (-oparg-1) + ^- (-oparg-2) - Right side `callable` will be POPed by call_funtion. - Left side `callable` will be POPed manually later - (one of "callbale" refs on the stack is borrowed.) + `callable` will be POPed by call_funtion. + NULL will will be POPed manually later. */ - SET_VALUE(oparg + 1, PEEK(oparg + 2)); res = call_function(&sp, oparg, NULL); stack_pointer = sp; - (void)POP(); /* POP the left side callable. */ + (void)POP(); /* POP the NULL. */ } else { /* This is a method call. Stack layout: - ... | method | obj | arg1 | ... | argN + ... | method | self | arg1 | ... | argN ^- TOP() ^- (-oparg) - ^- (-oparg-1) + ^- (-oparg-1) + ^- (-oparg-2) - `obj` and `method` will be POPed by call_function. + `self` and `method` will be POPed by call_function. We'll be passing `oparg + 1` to call_function, to - make it accept the `obj` as a first argument. + make it accept the `self` as a first argument. */ res = call_function(&sp, oparg + 1, NULL); stack_pointer = sp; |