summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorYury Selivanov <yury@magic.io>2016-12-14 00:03:51 (GMT)
committerYury Selivanov <yury@magic.io>2016-12-14 00:03:51 (GMT)
commitf2392133eba777f05947a8996c507690b95379c3 (patch)
tree3d3e352b04691dabeab1eb8502c2417d2af04826 /Python/compile.c
parente6bb53bf61ac24feca775bdaa651433b8466d2fa (diff)
downloadcpython-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.c37
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,