diff options
Diffstat (limited to 'Python/compile.c')
-rw-r--r-- | Python/compile.c | 135 |
1 files changed, 104 insertions, 31 deletions
diff --git a/Python/compile.c b/Python/compile.c index 6d96006..4464882 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -143,7 +143,7 @@ struct compiler { PyFutureFeatures *c_future; /* pointer to module's __future__ */ PyCompilerFlags *c_flags; - int c_interactive; + int c_interactive; /* true if in interactive mode */ int c_nestlevel; struct compiler_unit *u; /* compiler state for current block */ @@ -300,8 +300,11 @@ PyCodeObject * PyNode_Compile(struct _node *n, const char *filename) { PyCodeObject *co = NULL; + mod_ty mod; PyArena *arena = PyArena_New(); - mod_ty mod = PyAST_FromNode(n, NULL, filename, arena); + if (!arena) + return NULL; + mod = PyAST_FromNode(n, NULL, filename, arena); if (mod) co = PyAST_Compile(mod, filename, NULL, arena); PyArena_Free(arena); @@ -610,8 +613,10 @@ markblocks(unsigned char *code, int len) unsigned int *blocks = (unsigned int *)PyMem_Malloc(len*sizeof(int)); int i,j, opcode, blockcnt = 0; - if (blocks == NULL) + if (blocks == NULL) { + PyErr_NoMemory(); return NULL; + } memset(blocks, 0, len*sizeof(int)); /* Mark labels in the first pass */ @@ -1066,14 +1071,14 @@ compiler_unit_free(struct compiler_unit *u) PyObject_Free((void *)b); b = next; } - Py_XDECREF(u->u_ste); - Py_XDECREF(u->u_name); - Py_XDECREF(u->u_consts); - Py_XDECREF(u->u_names); - Py_XDECREF(u->u_varnames); - Py_XDECREF(u->u_freevars); - Py_XDECREF(u->u_cellvars); - Py_XDECREF(u->u_private); + Py_CLEAR(u->u_ste); + Py_CLEAR(u->u_name); + Py_CLEAR(u->u_consts); + Py_CLEAR(u->u_names); + Py_CLEAR(u->u_varnames); + Py_CLEAR(u->u_freevars); + Py_CLEAR(u->u_cellvars); + Py_CLEAR(u->u_private); PyObject_Free(u); } @@ -1100,8 +1105,17 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key, u->u_name = name; u->u_varnames = list2dict(u->u_ste->ste_varnames); u->u_cellvars = dictbytype(u->u_ste->ste_symbols, CELL, 0, 0); + if (!u->u_varnames || !u->u_cellvars) { + compiler_unit_free(u); + return 0; + } + u->u_freevars = dictbytype(u->u_ste->ste_symbols, FREE, DEF_FREE_CLASS, PyDict_Size(u->u_cellvars)); + if (!u->u_freevars) { + compiler_unit_free(u); + return 0; + } u->u_blocks = NULL; u->u_tmpname = 0; @@ -1125,7 +1139,8 @@ compiler_enter_scope(struct compiler *c, identifier name, void *key, /* Push the old compiler_unit on the stack. */ if (c->u) { PyObject *wrapper = PyCObject_FromVoidPtr(c->u, NULL); - if (PyList_Append(c->c_stack, wrapper) < 0) { + if (!wrapper || PyList_Append(c->c_stack, wrapper) < 0) { + Py_XDECREF(wrapper); compiler_unit_free(u); return 0; } @@ -1251,6 +1266,7 @@ compiler_next_instr(struct compiler *c, basicblock *b) sizeof(struct instr) * DEFAULT_BLOCK_SIZE); } else if (b->b_iused == b->b_ialloc) { + struct instr *tmp; size_t oldsize, newsize; oldsize = b->b_ialloc * sizeof(struct instr); newsize = oldsize << 1; @@ -1259,10 +1275,13 @@ compiler_next_instr(struct compiler *c, basicblock *b) return -1; } b->b_ialloc <<= 1; - b->b_instr = (struct instr *)PyObject_Realloc( + tmp = (struct instr *)PyObject_Realloc( (void *)b->b_instr, newsize); - if (b->b_instr == NULL) + if (tmp == NULL) { + PyErr_NoMemory(); return -1; + } + b->b_instr = tmp; memset((char *)b->b_instr + oldsize, 0, newsize - oldsize); } return b->b_iused++; @@ -1769,7 +1788,8 @@ compiler_mod(struct compiler *c, mod_ty mod) if (!module) return NULL; } - if (!compiler_enter_scope(c, module, mod, 1)) + /* Use 0 for firstlineno initially, will fixup in assemble(). */ + if (!compiler_enter_scope(c, module, mod, 0)) return NULL; switch (mod->kind) { case Module_kind: @@ -1963,11 +1983,8 @@ compiler_function(struct compiler *c, stmt_ty s) n = asdl_seq_LEN(s->v.FunctionDef.body); /* if there was a docstring, we need to skip the first statement */ for (i = docstring; i < n; i++) { - stmt_ty s2 = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, i); - if (i == 0 && s2->kind == Expr_kind && - s2->v.Expr.value->kind == Str_kind) - continue; - VISIT_IN_SCOPE(c, stmt, s2); + st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, i); + VISIT_IN_SCOPE(c, stmt, st); } co = assemble(c, 1); compiler_exit_scope(c); @@ -2190,6 +2207,10 @@ compiler_for(struct compiler *c, stmt_ty s) VISIT(c, expr, s->v.For.iter); ADDOP(c, GET_ITER); compiler_use_next_block(c, start); + /* XXX(nnorwitz): is there a better way to handle this? + for loops are special, we want to be able to trace them + each time around, so we need to set an extra line number. */ + c->u->u_lineno_set = false; ADDOP_JREL(c, FOR_ITER, cleanup); VISIT(c, expr, s->v.For.target); VISIT_SEQ(c, stmt, s->v.For.body); @@ -2708,11 +2729,13 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) case Global_kind: break; case Expr_kind: - VISIT(c, expr, s->v.Expr.value); if (c->c_interactive && c->c_nestlevel <= 1) { + VISIT(c, expr, s->v.Expr.value); ADDOP(c, PRINT_EXPR); } - else { + else if (s->v.Expr.value->kind != Str_kind && + s->v.Expr.value->kind != Num_kind) { + VISIT(c, expr, s->v.Expr.value); ADDOP(c, POP_TOP); } break; @@ -2989,6 +3012,7 @@ compiler_boolop(struct compiler *c, expr_ty e) return 0; s = e->v.BoolOp.values; n = asdl_seq_LEN(s) - 1; + assert(n >= 0); for (i = 0; i < n; ++i) { VISIT(c, expr, (expr_ty)asdl_seq_GET(s, i)); ADDOP_JREL(c, jumpi, end); @@ -3643,7 +3667,7 @@ compiler_augassign(struct compiler *c, stmt_ty s) assert(s->kind == AugAssign_kind); switch (e->kind) { - case Attribute_kind: + case Attribute_kind: auge = Attribute(e->v.Attribute.value, e->v.Attribute.attr, AugLoad, e->lineno, e->col_offset, c->c_arena); if (auge == NULL) @@ -3666,7 +3690,8 @@ compiler_augassign(struct compiler *c, stmt_ty s) VISIT(c, expr, auge); break; case Name_kind: - VISIT(c, expr, s->v.AugAssign.target); + if (!compiler_nameop(c, e->v.Name.id, Load)) + return 0; VISIT(c, expr, s->v.AugAssign.value); ADDOP(c, inplace_binop(c, s->v.AugAssign.op)); return compiler_nameop(c, e->v.Name.id, Store); @@ -3979,6 +4004,8 @@ stackdepth(struct compiler *c) b->b_startdepth = INT_MIN; entryblock = b; } + if (!entryblock) + return 0; return stackdepth_walk(c, entryblock, 0, 0); } @@ -4074,9 +4101,10 @@ corresponding to a bytecode address A should do something like this In order for this to work, when the addr field increments by more than 255, the line # increment in each pair generated must be 0 until the remaining addr -increment is < 256. So, in the example above, com_set_lineno should not (as -was actually done until 2.2) expand 300, 300 to 255, 255, 45, 45, but to -255, 0, 45, 255, 0, 45. +increment is < 256. So, in the example above, assemble_lnotab (it used +to be called com_set_lineno) should not (as was actually done until 2.2) +expand 300, 300 to 255, 255, 45, 45, + but to 255, 0, 45, 255, 0, 45. */ static int @@ -4092,7 +4120,10 @@ assemble_lnotab(struct assembler *a, struct instr *i) assert(d_bytecode >= 0); assert(d_lineno >= 0); - if (d_lineno == 0) + /* XXX(nnorwitz): is there a better way to handle this? + for loops are special, we want to be able to trace them + each time around, so we need to set an extra line number. */ + if (d_lineno == 0 && i->i_opcode != FOR_ITER) return 1; if (d_bytecode > 255) { @@ -4131,12 +4162,12 @@ assemble_lnotab(struct assembler *a, struct instr *i) } lnotab = (unsigned char *) PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; - *lnotab++ = 255; *lnotab++ = d_bytecode; + *lnotab++ = 255; d_bytecode = 0; for (j = 1; j < ncodes; j++) { - *lnotab++ = 255; *lnotab++ = 0; + *lnotab++ = 255; } d_lineno -= ncodes * 255; a->a_lnotab_off += ncodes * 2; @@ -4173,7 +4204,7 @@ static int assemble_emit(struct assembler *a, struct instr *i) { int size, arg = 0, ext = 0; - int len = PyString_GET_SIZE(a->a_bytecode); + Py_ssize_t len = PyString_GET_SIZE(a->a_bytecode); char *code; size = instrsize(i); @@ -4397,6 +4428,41 @@ makecode(struct compiler *c, struct assembler *a) return co; } + +/* For debugging purposes only */ +#if 0 +static void +dump_instr(const struct instr *i) +{ + const char *jrel = i->i_jrel ? "jrel " : ""; + const char *jabs = i->i_jabs ? "jabs " : ""; + char arg[128]; + + *arg = '\0'; + if (i->i_hasarg) + sprintf(arg, "arg: %d ", i->i_oparg); + + fprintf(stderr, "line: %d, opcode: %d %s%s%s\n", + i->i_lineno, i->i_opcode, arg, jabs, jrel); +} + +static void +dump_basicblock(const basicblock *b) +{ + const char *seen = b->b_seen ? "seen " : ""; + const char *b_return = b->b_return ? "return " : ""; + fprintf(stderr, "used: %d, depth: %d, offset: %d %s%s\n", + b->b_iused, b->b_startdepth, b->b_offset, seen, b_return); + if (b->b_instr) { + int i; + for (i = 0; i < b->b_iused; i++) { + fprintf(stderr, " [%02d] ", i); + dump_instr(b->b_instr + i); + } + } +} +#endif + static PyCodeObject * assemble(struct compiler *c, int addNone) { @@ -4423,6 +4489,13 @@ assemble(struct compiler *c, int addNone) entryblock = b; } + /* Set firstlineno if it wasn't explicitly set. */ + if (!c->u->u_firstlineno) { + if (entryblock && entryblock->b_instr) + c->u->u_firstlineno = entryblock->b_instr->i_lineno; + else + c->u->u_firstlineno = 1; + } if (!assemble_init(&a, nblocks, c->u->u_firstlineno)) goto error; dfs(c, entryblock, &a); |