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); | 
