diff options
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, |