summaryrefslogtreecommitdiff
path: root/Python/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c72
1 files changed, 49 insertions, 23 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 0e16075852..17fef31482 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);