diff options
author | Yury Selivanov <yury@magic.io> | 2016-12-14 00:03:51 (GMT) |
---|---|---|
committer | Yury Selivanov <yury@magic.io> | 2016-12-14 00:03:51 (GMT) |
commit | f2392133eba777f05947a8996c507690b95379c3 (patch) | |
tree | 3d3e352b04691dabeab1eb8502c2417d2af04826 /Python/compile.c | |
parent | e6bb53bf61ac24feca775bdaa651433b8466d2fa (diff) | |
download | cpython-f2392133eba777f05947a8996c507690b95379c3.zip cpython-f2392133eba777f05947a8996c507690b95379c3.tar.gz cpython-f2392133eba777f05947a8996c507690b95379c3.tar.bz2 |
Issue #26110: Add LOAD_METHOD/CALL_METHOD opcodes.
Special thanks to INADA Naoki for pushing the patch through
the last mile, Serhiy Storchaka for reviewing the code, and to
Victor Stinner for suggesting the idea (originally implemented
in the PyPy project).
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/Python/compile.c b/Python/compile.c index f4edf8f..25179fa 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1040,6 +1040,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return -oparg; case CALL_FUNCTION: return -oparg; + case CALL_METHOD: + return -oparg-1; case CALL_FUNCTION_KW: return -oparg-1; case CALL_FUNCTION_EX: @@ -1078,6 +1080,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) /* If there's a fmt_spec on the stack, we go from 2->1, else 1->1. */ return (oparg & FVS_MASK) == FVS_HAVE_SPEC ? -1 : 0; + case LOAD_METHOD: + return 1; default: return PY_INVALID_STACK_EFFECT; } @@ -3400,8 +3404,41 @@ compiler_compare(struct compiler *c, expr_ty e) } static int +maybe_optimize_method_call(struct compiler *c, expr_ty e) +{ + Py_ssize_t argsl, i; + expr_ty meth = e->v.Call.func; + asdl_seq *args = e->v.Call.args; + + /* Check that the call node is an attribute access, and that + the call doesn't have keyword parameters. */ + if (meth->kind != Attribute_kind || meth->v.Attribute.ctx != Load || + asdl_seq_LEN(e->v.Call.keywords)) + return -1; + + /* Check that there are no *varargs types of arguments. */ + argsl = asdl_seq_LEN(args); + for (i = 0; i < argsl; i++) { + expr_ty elt = asdl_seq_GET(args, i); + if (elt->kind == Starred_kind) { + return -1; + } + } + + /* Alright, we can optimize the code. */ + VISIT(c, expr, meth->v.Attribute.value); + ADDOP_NAME(c, LOAD_METHOD, meth->v.Attribute.attr, names); + VISIT_SEQ(c, expr, e->v.Call.args); + ADDOP_I(c, CALL_METHOD, asdl_seq_LEN(e->v.Call.args)); + return 1; +} + +static int compiler_call(struct compiler *c, expr_ty e) { + if (maybe_optimize_method_call(c, e) > 0) + return 1; + VISIT(c, expr, e->v.Call.func); return compiler_call_helper(c, 0, e->v.Call.args, |