PyMem_Free(addrmap); if (codestr != NULL) PyMem_Free(codestr); Py_INCREF(code); return code;} /* End: Peephole optimizations ----------------------------------------- */ /* Leave this debugging code for just a little longer. static voidcompiler_display_symbols(PyObject *name, PyObject *symbols){PyObject *key, *value;int flags;Py_ssize_t pos = 0; fprintf(stderr, "block %s\n", PyString_AS_STRING(name));while (PyDict_Next(symbols, &pos, &key, &value)) {flags = PyInt_AsLong(value);fprintf(stderr, "var %s:", PyString_AS_STRING(key));if (flags & DEF_GLOBAL)fprintf(stderr, " declared_global");if (flags & DEF_LOCAL)fprintf(stderr, " local");if (flags & DEF_PARAM)fprintf(stderr, " param");if (flags & DEF_STAR)fprintf(stderr, " stararg");if (flags & DEF_DOUBLESTAR)fprintf(stderr, " starstar");if (flags & DEF_INTUPLE)fprintf(stderr, " tuple");if (flags & DEF_FREE)fprintf(stderr, " free");if (flags & DEF_FREE_GLOBAL)fprintf(stderr, " global");if (flags & DEF_FREE_CLASS)fprintf(stderr, " free/class");if (flags & DEF_IMPORT)fprintf(stderr, " import");fprintf(stderr, "\n");} fprintf(stderr, "\n");}*/ static voidcompiler_unit_check(struct compiler_unit *u){ basicblock *block; for (block = u->u_blocks; block != NULL; block = block->b_list) { assert(block != (void *)0xcbcbcbcb); assert(block != (void *)0xfbfbfbfb); assert(block != (void *)0xdbdbdbdb); if (block->b_instr != NULL) { assert(block->b_ialloc > 0); assert(block->b_iused > 0); assert(block->b_ialloc >= block->b_iused); } else { assert (block->b_iused == 0); assert (block->b_ialloc == 0); } }} static voidcompiler_unit_free(struct compiler_unit *u){ basicblock *b, *next; compiler_unit_check(u); b = u->u_blocks; while (b != NULL) { if (b->b_instr) PyObject_Free((void *)b->b_instr); next = b->b_list; PyObject_Free((void *)b); b = next; } 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);} static intcompiler_enter_scope(struct compiler *c, identifier name, void *key, int lineno){ struct compiler_unit *u; u = (struct compiler_unit *)PyObject_Malloc(sizeof( struct compiler_unit)); if (!u) { PyErr_NoMemory(); return 0; } memset(u, 0, sizeof(struct compiler_unit)); u->u_argcount = 0; u->u_ste = PySymtable_Lookup(c->c_st, key); if (!u->u_ste) { compiler_unit_free(u); return 0; } Py_INCREF(name); 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; u->u_nfblocks = 0; u->u_firstlineno = lineno; u->u_lineno = 0; u->u_lineno_set = false; u->u_consts = PyDict_New(); if (!u->u_consts) { compiler_unit_free(u); return 0; } u->u_names = PyDict_New(); if (!u->u_names) { compiler_unit_free(u); return 0; } u->u_private = NULL; /* Push the old compiler_unit on the stack. */ if (c->u) { PyObject *wrapper = PyCObject_FromVoidPtr(c->u, NULL); if (!wrapper || PyList_Append(c->c_stack, wrapper) < 0) { Py_XDECREF(wrapper); compiler_unit_free(u); return 0; } Py_DECREF(wrapper); u->u_private = c->u->u_private; Py_XINCREF(u->u_private); } c->u = u; c->c_nestlevel++; if (compiler_use_new_block(c) == NULL) return 0; return 1;} static voidcompiler_exit_scope(struct compiler *c){ int n; PyObject *wrapper; c->c_nestlevel--; compiler_unit_free(c->u); /* Restore c->u to the parent unit. */ n = PyList_GET_SIZE(c->c_stack) - 1; if (n >= 0) { wrapper = PyList_GET_ITEM(c->c_stack, n); c->u = (struct compiler_unit *)PyCObject_AsVoidPtr(wrapper); /* we are deleting from a list so this really shouldn't fail */ if (PySequence_DelItem(c->c_stack, n) < 0) Py_FatalError("compiler_exit_scope()"); compiler_unit_check(c->u); } else c->u = NULL; } /* Allocate a new "anonymous" local variable. Used by list comprehensions and with statements.*/ static PyObject *compiler_new_tmpname(struct compiler *c){ char tmpname[256]; PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->u->u_tmpname); return PyString_FromString(tmpname);} /* Allocate a new block and return a pointer to it. Returns NULL on error.*/ static basicblock *compiler_new_block(struct compiler *c){ basicblock *b; struct compiler_unit *u; u = c->u; b = (basicblock *)PyObject_Malloc(sizeof(basicblock)); if (b == NULL) { PyErr_NoMemory(); return NULL; } memset((void *)b, 0, sizeof(basicblock)); /* Extend the singly linked list of blocks with new block. */ b->b_list = u->u_blocks; u->u_blocks = b; return b;} static basicblock *compiler_use_new_block(struct compiler *c){ basicblock *block = compiler_new_block(c); if (block == NULL) return NULL; c->u->u_curblock = block; return block;} static basicblock *compiler_next_block(struct compiler *c){ basicblock *block = compiler_new_block(c); if (block == NULL) return NULL; c->u->u_curblock->b_next = block; c->u->u_curblock = block; return block;} static basicblock *compiler_use_next_block(struct compiler *c, basicblock *block){ assert(block != NULL); c->u->u_curblock->b_next = block; c->u->u_curblock = block; return block;} /* Returns the offset of the next instruction in the current block's b_instr array. Resizes the b_instr as necessary. Returns -1 on failure. */ static intcompiler_next_instr(struct compiler *c, basicblock *b){ assert(b != NULL); if (b->b_instr == NULL) { b->b_instr = (struct instr *)PyObject_Malloc( sizeof(struct instr) * DEFAULT_BLOCK_SIZE); if (b->b_instr == NULL) { PyErr_NoMemory(); return -1; } b->b_ialloc = DEFAULT_BLOCK_SIZE; memset((char *)b->b_instr, 0, 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; if (newsize == 0) { PyErr_NoMemory(); return -1; } b->b_ialloc <<= 1; tmp = (struct instr *)PyObject_Realloc( (void *)b->b_instr, newsize); if (tmp == NULL) { PyErr_NoMemory(); return -1; } b->b_instr = tmp; memset((char *)b->b_instr + oldsize, 0, newsize - oldsize); } return b->b_iused++;} /* Set the i_lineno member of the instruction at offse off if the line number for the current expression/statement (?) has not already been set. If it has been set, the call has no effect. Every time a new node is b */ static voidcompiler_set_lineno(struct compiler *c, int off){ basicblock *b; if (c->u->u_lineno_set) return; c->u->u_lineno_set = true; b = c->u->u_curblock; b->b_instr[off].i_lineno = c->u->u_lineno;} static intopcode_stack_effect(int opcode, int oparg){ switch (opcode) { case POP_TOP: return -1; case ROT_TWO: case ROT_THREE: return 0; case DUP_TOP: return 1; case ROT_FOUR: return 0; case UNARY_POSITIVE: case UNARY_NEGATIVE: case UNARY_NOT: case UNARY_CONVERT: case UNARY_INVERT: return 0; case LIST_APPEND: return -2; case BINARY_POWER: case BINARY_MULTIPLY: case BINARY_DIVIDE: case BINARY_MODULO: case BINARY_ADD: case BINARY_SUBTRACT: case BINARY_SUBSCR: case BINARY_FLOOR_DIVIDE: case BINARY_TRUE_DIVIDE: return -1; case INPLACE_FLOOR_DIVIDE: case INPLACE_TRUE_DIVIDE: return -1; case SLICE+0: return 1; case SLICE+1: return 0; case SLICE+2: return 0; case SLICE+3: return -1; case STORE_SLICE+0: return -2; case STORE_SLICE+1: return -3; case STORE_SLICE+2: return -3; case STORE_SLICE+3: return -4; case DELETE_SLICE+0: return -1; case DELETE_SLICE+1: return -2; case DELETE_SLICE+2: return -2; case DELETE_SLICE+3: return -3; case INPLACE_ADD: case INPLACE_SUBTRACT: case INPLACE_MULTIPLY: case INPLACE_DIVIDE: case INPLACE_MODULO: return -1; case STORE_SUBSCR: return -3; case DELETE_SUBSCR: return -2; case BINARY_LSHIFT: case BINARY_RSHIFT: case BINARY_AND: case BINARY_XOR: case BINARY_OR: return -1; case INPLACE_POWER: return -1; case GET_ITER: return 0; case PRINT_EXPR: return -1; case PRINT_ITEM: return -1; case PRINT_NEWLINE: return 0; case PRINT_ITEM_TO: return -2; case PRINT_NEWLINE_TO: return -1; case INPLACE_LSHIFT: case INPLACE_RSHIFT: case INPLACE_AND: case INPLACE_XOR: case INPLACE_OR: return -1; case BREAK_LOOP: return 0; case WITH_CLEANUP: return -1; /* XXX Sometimes more */ case LOAD_LOCALS: return 1; case RETURN_VALUE: return -1; case IMPORT_STAR: return -1; case EXEC_STMT: return -3; case YIELD_VALUE: return 0; case POP_BLOCK: return 0; case END_FINALLY: return -1; /* or -2 or -3 if exception occurred */ case BUILD_CLASS: return -2; case STORE_NAME: return -1; case DELETE_NAME: return 0; case UNPACK_SEQUENCE: return oparg-1; case FOR_ITER: return 1; case STORE_ATTR: return -2; case DELETE_ATTR: return -1; case STORE_GLOBAL: return -1; case DELETE_GLOBAL: return 0; case DUP_TOPX: return oparg; case LOAD_CONST: return 1; case LOAD_NAME: return 1; case BUILD_TUPLE: case BUILD_LIST: return 1-oparg; case BUILD_MAP: return 1; case LOAD_ATTR: return 0; case COMPARE_OP: return -1; case IMPORT_NAME: return 0; case IMPORT_FROM: return 1; case JUMP_FORWARD: case JUMP_IF_FALSE: case JUMP_IF_TRUE: case JUMP_ABSOLUTE: return 0; case LOAD_GLOBAL: return 1; case CONTINUE_LOOP: return 0; case SETUP_LOOP: return 0; case SETUP_EXCEPT: case SETUP_FINALLY: return 3; /* actually pushed by an exception */ case LOAD_FAST: return 1; case STORE_FAST:Lines 1001–1500 of 4570. Previous lines Load more
PyMem_Free(addrmap); if (codestr != NULL) PyMem_Free(codestr); Py_INCREF(code); return code; } /* End: Peephole optimizations ----------------------------------------- */ /* Leave this debugging code for just a little longer. static void compiler_display_symbols(PyObject *name, PyObject *symbols) { PyObject *key, *value; int flags; Py_ssize_t pos = 0; fprintf(stderr, "block %s\n", PyString_AS_STRING(name)); while (PyDict_Next(symbols, &pos, &key, &value)) { flags = PyInt_AsLong(value); fprintf(stderr, "var %s:", PyString_AS_STRING(key)); if (flags & DEF_GLOBAL) fprintf(stderr, " declared_global"); if (flags & DEF_LOCAL) fprintf(stderr, " local"); if (flags & DEF_PARAM) fprintf(stderr, " param"); if (flags & DEF_STAR) fprintf(stderr, " stararg"); if (flags & DEF_DOUBLESTAR) fprintf(stderr, " starstar"); if (flags & DEF_INTUPLE) fprintf(stderr, " tuple"); if (flags & DEF_FREE) fprintf(stderr, " free"); if (flags & DEF_FREE_GLOBAL) fprintf(stderr, " global"); if (flags & DEF_FREE_CLASS) fprintf(stderr, " free/class"); if (flags & DEF_IMPORT) fprintf(stderr, " import"); fprintf(stderr, "\n"); } fprintf(stderr, "\n"); } */ static void compiler_unit_check(struct compiler_unit *u) { basicblock *block; for (block = u->u_blocks; block != NULL; block = block->b_list) { assert(block != (void *)0xcbcbcbcb); assert(block != (void *)0xfbfbfbfb); assert(block != (void *)0xdbdbdbdb); if (block->b_instr != NULL) { assert(block->b_ialloc > 0); assert(block->b_iused > 0); assert(block->b_ialloc >= block->b_iused); } else { assert (block->b_iused == 0); assert (block->b_ialloc == 0); } } } static void compiler_unit_free(struct compiler_unit *u) { basicblock *b, *next; compiler_unit_check(u); b = u->u_blocks; while (b != NULL) { if (b->b_instr) PyObject_Free((void *)b->b_instr); next = b->b_list; PyObject_Free((void *)b); b = next; } 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); } static int compiler_enter_scope(struct compiler *c, identifier name, void *key, int lineno) { struct compiler_unit *u; u = (struct compiler_unit *)PyObject_Malloc(sizeof( struct compiler_unit)); if (!u) { PyErr_NoMemory(); return 0; } memset(u, 0, sizeof(struct compiler_unit)); u->u_argcount = 0; u->u_ste = PySymtable_Lookup(c->c_st, key); if (!u->u_ste) { compiler_unit_free(u); return 0; } Py_INCREF(name); 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; u->u_nfblocks = 0; u->u_firstlineno = lineno; u->u_lineno = 0; u->u_lineno_set = false; u->u_consts = PyDict_New(); if (!u->u_consts) { compiler_unit_free(u); return 0; } u->u_names = PyDict_New(); if (!u->u_names) { compiler_unit_free(u); return 0; } u->u_private = NULL; /* Push the old compiler_unit on the stack. */ if (c->u) { PyObject *wrapper = PyCObject_FromVoidPtr(c->u, NULL); if (!wrapper || PyList_Append(c->c_stack, wrapper) < 0) { Py_XDECREF(wrapper); compiler_unit_free(u); return 0; } Py_DECREF(wrapper); u->u_private = c->u->u_private; Py_XINCREF(u->u_private); } c->u = u; c->c_nestlevel++; if (compiler_use_new_block(c) == NULL) return 0; return 1; } static void compiler_exit_scope(struct compiler *c) { int n; PyObject *wrapper; c->c_nestlevel--; compiler_unit_free(c->u); /* Restore c->u to the parent unit. */ n = PyList_GET_SIZE(c->c_stack) - 1; if (n >= 0) { wrapper = PyList_GET_ITEM(c->c_stack, n); c->u = (struct compiler_unit *)PyCObject_AsVoidPtr(wrapper); /* we are deleting from a list so this really shouldn't fail */ if (PySequence_DelItem(c->c_stack, n) < 0) Py_FatalError("compiler_exit_scope()"); compiler_unit_check(c->u); } else c->u = NULL; } /* Allocate a new "anonymous" local variable. Used by list comprehensions and with statements. */ static PyObject * compiler_new_tmpname(struct compiler *c) { char tmpname[256]; PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->u->u_tmpname); return PyString_FromString(tmpname); } /* Allocate a new block and return a pointer to it. Returns NULL on error. */ static basicblock * compiler_new_block(struct compiler *c) { basicblock *b; struct compiler_unit *u; u = c->u; b = (basicblock *)PyObject_Malloc(sizeof(basicblock)); if (b == NULL) { PyErr_NoMemory(); return NULL; } memset((void *)b, 0, sizeof(basicblock)); /* Extend the singly linked list of blocks with new block. */ b->b_list = u->u_blocks; u->u_blocks = b; return b; } static basicblock * compiler_use_new_block(struct compiler *c) { basicblock *block = compiler_new_block(c); if (block == NULL) return NULL; c->u->u_curblock = block; return block; } static basicblock * compiler_next_block(struct compiler *c) { basicblock *block = compiler_new_block(c); if (block == NULL) return NULL; c->u->u_curblock->b_next = block; c->u->u_curblock = block; return block; } static basicblock * compiler_use_next_block(struct compiler *c, basicblock *block) { assert(block != NULL); c->u->u_curblock->b_next = block; c->u->u_curblock = block; return block; } /* Returns the offset of the next instruction in the current block's b_instr array. Resizes the b_instr as necessary. Returns -1 on failure. */ static int compiler_next_instr(struct compiler *c, basicblock *b) { assert(b != NULL); if (b->b_instr == NULL) { b->b_instr = (struct instr *)PyObject_Malloc( sizeof(struct instr) * DEFAULT_BLOCK_SIZE); if (b->b_instr == NULL) { PyErr_NoMemory(); return -1; } b->b_ialloc = DEFAULT_BLOCK_SIZE; memset((char *)b->b_instr, 0, 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; if (newsize == 0) { PyErr_NoMemory(); return -1; } b->b_ialloc <<= 1; tmp = (struct instr *)PyObject_Realloc( (void *)b->b_instr, newsize); if (tmp == NULL) { PyErr_NoMemory(); return -1; } b->b_instr = tmp; memset((char *)b->b_instr + oldsize, 0, newsize - oldsize); } return b->b_iused++; } /* Set the i_lineno member of the instruction at offse off if the line number for the current expression/statement (?) has not already been set. If it has been set, the call has no effect. Every time a new node is b */ static void compiler_set_lineno(struct compiler *c, int off) { basicblock *b; if (c->u->u_lineno_set) return; c->u->u_lineno_set = true; b = c->u->u_curblock; b->b_instr[off].i_lineno = c->u->u_lineno; } static int opcode_stack_effect(int opcode, int oparg) { switch (opcode) { case POP_TOP: return -1; case ROT_TWO: case ROT_THREE: return 0; case DUP_TOP: return 1; case ROT_FOUR: return 0; case UNARY_POSITIVE: case UNARY_NEGATIVE: case UNARY_NOT: case UNARY_CONVERT: case UNARY_INVERT: return 0; case LIST_APPEND: return -2; case BINARY_POWER: case BINARY_MULTIPLY: case BINARY_DIVIDE: case BINARY_MODULO: case BINARY_ADD: case BINARY_SUBTRACT: case BINARY_SUBSCR: case BINARY_FLOOR_DIVIDE: case BINARY_TRUE_DIVIDE: return -1; case INPLACE_FLOOR_DIVIDE: case INPLACE_TRUE_DIVIDE: return -1; case SLICE+0: return 1; case SLICE+1: return 0; case SLICE+2: return 0; case SLICE+3: return -1; case STORE_SLICE+0: return -2; case STORE_SLICE+1: return -3; case STORE_SLICE+2: return -3; case STORE_SLICE+3: return -4; case DELETE_SLICE+0: return -1; case DELETE_SLICE+1: return -2; case DELETE_SLICE+2: return -2; case DELETE_SLICE+3: return -3; case INPLACE_ADD: case INPLACE_SUBTRACT: case INPLACE_MULTIPLY: case INPLACE_DIVIDE: case INPLACE_MODULO: return -1; case STORE_SUBSCR: return -3; case DELETE_SUBSCR: return -2; case BINARY_LSHIFT: case BINARY_RSHIFT: case BINARY_AND: case BINARY_XOR: case BINARY_OR: return -1; case INPLACE_POWER: return -1; case GET_ITER: return 0; case PRINT_EXPR: return -1; case PRINT_ITEM: return -1; case PRINT_NEWLINE: return 0; case PRINT_ITEM_TO: return -2; case PRINT_NEWLINE_TO: return -1; case INPLACE_LSHIFT: case INPLACE_RSHIFT: case INPLACE_AND: case INPLACE_XOR: case INPLACE_OR: return -1; case BREAK_LOOP: return 0; case WITH_CLEANUP: return -1; /* XXX Sometimes more */ case LOAD_LOCALS: return 1; case RETURN_VALUE: return -1; case IMPORT_STAR: return -1; case EXEC_STMT: return -3; case YIELD_VALUE: return 0; case POP_BLOCK: return 0; case END_FINALLY: return -1; /* or -2 or -3 if exception occurred */ case BUILD_CLASS: return -2; case STORE_NAME: return -1; case DELETE_NAME: return 0; case UNPACK_SEQUENCE: return oparg-1; case FOR_ITER: return 1; case STORE_ATTR: return -2; case DELETE_ATTR: return -1; case STORE_GLOBAL: return -1; case DELETE_GLOBAL: return 0; case DUP_TOPX: return oparg; case LOAD_CONST: return 1; case LOAD_NAME: return 1; case BUILD_TUPLE: case BUILD_LIST: return 1-oparg; case BUILD_MAP: return 1; case LOAD_ATTR: return 0; case COMPARE_OP: return -1; case IMPORT_NAME: return 0; case IMPORT_FROM: return 1; case JUMP_FORWARD: case JUMP_IF_FALSE: case JUMP_IF_TRUE: case JUMP_ABSOLUTE: return 0; case LOAD_GLOBAL: return 1; case CONTINUE_LOOP: return 0; case SETUP_LOOP: return 0; case SETUP_EXCEPT: case SETUP_FINALLY: return 3; /* actually pushed by an exception */ case LOAD_FAST: return 1; case STORE_FAST: