diff options
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 72 |
1 files changed, 49 insertions, 23 deletions
diff --git a/Python/compile.c b/Python/compile.c index 0e16075..17fef31 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -564,7 +564,7 @@ compiler_enter_scope(struct compiler *c, identifier name, PyObject *tuple, *name, *zero; int res; assert(u->u_scope_type == COMPILER_SCOPE_CLASS); - assert(PyDict_Size(u->u_cellvars) == 0); + assert(PyDict_GET_SIZE(u->u_cellvars) == 0); name = _PyUnicode_FromId(&PyId___class__); if (!name) { compiler_unit_free(u); @@ -591,7 +591,7 @@ compiler_enter_scope(struct compiler *c, identifier name, } u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, - PyDict_Size(u->u_cellvars)); + PyDict_GET_SIZE(u->u_cellvars)); if (!u->u_freevars) { compiler_unit_free(u); return 0; @@ -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; } @@ -1124,7 +1128,7 @@ compiler_add_o(struct compiler *c, PyObject *dict, PyObject *o) Py_DECREF(t); return -1; } - arg = PyDict_Size(dict); + arg = PyDict_GET_SIZE(dict); v = PyLong_FromSsize_t(arg); if (!v) { Py_DECREF(t); @@ -1995,7 +1999,7 @@ compiler_class(struct compiler *c, stmt_ty s) } else { /* No methods referenced __class__, so just return None */ - assert(PyDict_Size(c->u->u_cellvars) == 0); + assert(PyDict_GET_SIZE(c->u->u_cellvars) == 0); ADDOP_O(c, LOAD_CONST, Py_None, consts); } ADDOP_IN_SCOPE(c, RETURN_VALUE); @@ -3348,11 +3352,8 @@ compiler_dict(struct compiler *c, expr_ty e) /* If there is more than one dict, they need to be merged into a new * dict. If there is one dict and it's an unpacking, then it needs * to be copied into a new dict." */ - while (containers > 1 || is_unpacking) { - int oparg = containers < 255 ? containers : 255; - ADDOP_I(c, BUILD_MAP_UNPACK, oparg); - containers -= (oparg - 1); - is_unpacking = 0; + if (containers > 1 || is_unpacking) { + ADDOP_I(c, BUILD_MAP_UNPACK, containers); } return 1; } @@ -3403,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, @@ -4044,7 +4078,7 @@ compiler_visit_keyword(struct compiler *c, keyword_ty k) static int expr_constant(struct compiler *c, expr_ty e) { - char *id; + const char *id; switch (e->kind) { case Ellipsis_kind: return 1; @@ -5145,7 +5179,7 @@ static PyObject * dict_keys_inorder(PyObject *dict, Py_ssize_t offset) { PyObject *tuple, *k, *v; - Py_ssize_t i, pos = 0, size = PyDict_Size(dict); + Py_ssize_t i, pos = 0, size = PyDict_GET_SIZE(dict); tuple = PyTuple_New(size); if (tuple == NULL) @@ -5169,7 +5203,6 @@ compute_code_flags(struct compiler *c) { PySTEntryObject *ste = c->u->u_ste; int flags = 0; - Py_ssize_t n; if (ste->ste_type == FunctionBlock) { flags |= CO_NEWLOCALS | CO_OPTIMIZED; if (ste->ste_nested) @@ -5189,16 +5222,9 @@ compute_code_flags(struct compiler *c) /* (Only) inherit compilerflags in PyCF_MASK */ flags |= (c->c_flags->cf_flags & PyCF_MASK); - n = PyDict_Size(c->u->u_freevars); - if (n < 0) - return -1; - if (n == 0) { - n = PyDict_Size(c->u->u_cellvars); - if (n < 0) - return -1; - if (n == 0) { - flags |= CO_NOFREE; - } + if (!PyDict_GET_SIZE(c->u->u_freevars) && + !PyDict_GET_SIZE(c->u->u_cellvars)) { + flags |= CO_NOFREE; } return flags; @@ -5239,7 +5265,7 @@ makecode(struct compiler *c, struct assembler *a) if (!freevars) goto error; - nlocals = PyDict_Size(c->u->u_varnames); + nlocals = PyDict_GET_SIZE(c->u->u_varnames); assert(nlocals < INT_MAX); nlocals_int = Py_SAFE_DOWNCAST(nlocals, Py_ssize_t, int); |