cinap_lenrekadd hg and python4bb9e2215 years agoHistory
4570 lines · 109.1 KB · C
RawDownload
		dfs(c, b->b_next, a);	for (i = 0; i < b->b_iused; i++) {		instr = &b->b_instr[i];		if (instr->i_jrel || instr->i_jabs)			dfs(c, instr->i_target, a);	}	a->a_postorder[a->a_nblocks++] = b;} static intstackdepth_walk(struct compiler *c, basicblock *b, int depth, int maxdepth){	int i;	struct instr *instr;	if (b->b_seen || b->b_startdepth >= depth)		return maxdepth;	b->b_seen = 1;	b->b_startdepth = depth;	for (i = 0; i < b->b_iused; i++) {		instr = &b->b_instr[i];		depth += opcode_stack_effect(instr->i_opcode, instr->i_oparg);		if (depth > maxdepth)			maxdepth = depth;		assert(depth >= 0); /* invalid code or bug in stackdepth() */		if (instr->i_jrel || instr->i_jabs) {			maxdepth = stackdepth_walk(c, instr->i_target,						   depth, maxdepth);			if (instr->i_opcode == JUMP_ABSOLUTE ||			    instr->i_opcode == JUMP_FORWARD) {				goto out; /* remaining code is dead */			}		}	}	if (b->b_next)		maxdepth = stackdepth_walk(c, b->b_next, depth, maxdepth);out:	b->b_seen = 0;	return maxdepth;} /* Find the flow path that needs the largest stack.  We assume that * cycles in the flow graph have no net effect on the stack depth. */static intstackdepth(struct compiler *c){	basicblock *b, *entryblock;	entryblock = NULL;	for (b = c->u->u_blocks; b != NULL; b = b->b_list) {		b->b_seen = 0;		b->b_startdepth = INT_MIN;		entryblock = b;	}	if (!entryblock)		return 0;	return stackdepth_walk(c, entryblock, 0, 0);} static intassemble_init(struct assembler *a, int nblocks, int firstlineno){	memset(a, 0, sizeof(struct assembler));	a->a_lineno = firstlineno;	a->a_bytecode = PyString_FromStringAndSize(NULL, DEFAULT_CODE_SIZE);	if (!a->a_bytecode)		return 0;	a->a_lnotab = PyString_FromStringAndSize(NULL, DEFAULT_LNOTAB_SIZE);	if (!a->a_lnotab)		return 0;	a->a_postorder = (basicblock **)PyObject_Malloc(					    sizeof(basicblock *) * nblocks);	if (!a->a_postorder) {		PyErr_NoMemory();		return 0;	}	return 1;} static voidassemble_free(struct assembler *a){	Py_XDECREF(a->a_bytecode);	Py_XDECREF(a->a_lnotab);	if (a->a_postorder)		PyObject_Free(a->a_postorder);} /* Return the size of a basic block in bytes. */ static intinstrsize(struct instr *instr){	if (!instr->i_hasarg)		return 1;	if (instr->i_oparg > 0xffff)		return 6;	return 3;} static intblocksize(basicblock *b){	int i;	int size = 0; 	for (i = 0; i < b->b_iused; i++)		size += instrsize(&b->b_instr[i]);	return size;} /* All about a_lnotab. c_lnotab is an array of unsigned bytes disguised as a Python string.It is used to map bytecode offsets to source code line #s (when neededfor tracebacks). The array is conceptually a list of    (bytecode offset increment, line number increment)pairs.	The details are important and delicate, best illustrated by example:     byte code offset	source code line number	0		    1	6		    2       50		    7      350		  307      361		  308 The first trick is that these numbers aren't stored, only the incrementsfrom one row to the next (this doesn't really work, but it's a start):     0, 1,  6, 1,  44, 5,  300, 300,  11, 1 The second trick is that an unsigned byte can't hold negative values, orvalues larger than 255, so (a) there's a deep assumption that byte codeoffsets and their corresponding line #s both increase monotonically, and (b)if at least one column jumps by more than 255 from one row to the next, morethan one pair is written to the table. In case #b, there's no way to knowfrom looking at the table later how many were written.	That's the delicatepart.  A user of c_lnotab desiring to find the source line numbercorresponding to a bytecode address A should do something like this     lineno = addr = 0    for addr_incr, line_incr in c_lnotab:	addr += addr_incr	if addr > A:	    return lineno	lineno += line_incr 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 addrincrement is < 256.  So, in the example above, assemble_lnotab (it usedto 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 intassemble_lnotab(struct assembler *a, struct instr *i){	int d_bytecode, d_lineno;	int len;	unsigned char *lnotab; 	d_bytecode = a->a_offset - a->a_lineno_off;	d_lineno = i->i_lineno - a->a_lineno; 	assert(d_bytecode >= 0);	assert(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) {		int j, nbytes, ncodes = d_bytecode / 255;		nbytes = a->a_lnotab_off + 2 * ncodes;		len = PyString_GET_SIZE(a->a_lnotab);		if (nbytes >= len) {			if (len * 2 < nbytes)				len = nbytes;			else				len *= 2;			if (_PyString_Resize(&a->a_lnotab, len) < 0)				return 0;		}		lnotab = (unsigned char *)			   PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off;		for (j = 0; j < ncodes; j++) {			*lnotab++ = 255;			*lnotab++ = 0;		}		d_bytecode -= ncodes * 255;		a->a_lnotab_off += ncodes * 2;	}	assert(d_bytecode <= 255);	if (d_lineno > 255) {		int j, nbytes, ncodes = d_lineno / 255;		nbytes = a->a_lnotab_off + 2 * ncodes;		len = PyString_GET_SIZE(a->a_lnotab);		if (nbytes >= len) {			if (len * 2 < nbytes)				len = nbytes;			else				len *= 2;			if (_PyString_Resize(&a->a_lnotab, len) < 0)				return 0;		}		lnotab = (unsigned char *)			   PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off;		*lnotab++ = d_bytecode;		*lnotab++ = 255;		d_bytecode = 0;		for (j = 1; j < ncodes; j++) {			*lnotab++ = 0;			*lnotab++ = 255;		}		d_lineno -= ncodes * 255;		a->a_lnotab_off += ncodes * 2;	} 	len = PyString_GET_SIZE(a->a_lnotab);	if (a->a_lnotab_off + 2 >= len) {		if (_PyString_Resize(&a->a_lnotab, len * 2) < 0)			return 0;	}	lnotab = (unsigned char *)			PyString_AS_STRING(a->a_lnotab) + a->a_lnotab_off; 	a->a_lnotab_off += 2;	if (d_bytecode) {		*lnotab++ = d_bytecode;		*lnotab++ = d_lineno;	}	else {	/* First line of a block; def stmt, etc. */		*lnotab++ = 0;		*lnotab++ = d_lineno;	}	a->a_lineno = i->i_lineno;	a->a_lineno_off = a->a_offset;	return 1;} /* assemble_emit()   Extend the bytecode with a new instruction.   Update lnotab if necessary.*/ static intassemble_emit(struct assembler *a, struct instr *i){	int size, arg = 0, ext = 0;	Py_ssize_t len = PyString_GET_SIZE(a->a_bytecode);	char *code; 	size = instrsize(i);	if (i->i_hasarg) {		arg = i->i_oparg;		ext = arg >> 16;	}	if (i->i_lineno && !assemble_lnotab(a, i))		return 0;	if (a->a_offset + size >= len) {		if (_PyString_Resize(&a->a_bytecode, len * 2) < 0)		    return 0;	}	code = PyString_AS_STRING(a->a_bytecode) + a->a_offset;	a->a_offset += size;	if (size == 6) {		assert(i->i_hasarg);		*code++ = (char)EXTENDED_ARG;		*code++ = ext & 0xff;		*code++ = ext >> 8;		arg &= 0xffff;	}	*code++ = i->i_opcode;	if (i->i_hasarg) {		assert(size == 3 || size == 6);		*code++ = arg & 0xff;		*code++ = arg >> 8;	}	return 1;} static voidassemble_jump_offsets(struct assembler *a, struct compiler *c){	basicblock *b;	int bsize, totsize, extended_arg_count, last_extended_arg_count = 0;	int i; 	/* Compute the size of each block and fixup jump args.	   Replace block pointer with position in bytecode. */start:	totsize = 0;	for (i = a->a_nblocks - 1; i >= 0; i--) {		b = a->a_postorder[i];		bsize = blocksize(b);		b->b_offset = totsize;		totsize += bsize;	}	extended_arg_count = 0;	for (b = c->u->u_blocks; b != NULL; b = b->b_list) {		bsize = b->b_offset;		for (i = 0; i < b->b_iused; i++) {			struct instr *instr = &b->b_instr[i];			/* Relative jumps are computed relative to			   the instruction pointer after fetching			   the jump instruction.			*/			bsize += instrsize(instr);			if (instr->i_jabs)				instr->i_oparg = instr->i_target->b_offset;			else if (instr->i_jrel) {				int delta = instr->i_target->b_offset - bsize;				instr->i_oparg = delta;			}			else				continue;			if (instr->i_oparg > 0xffff)				extended_arg_count++;		}	} 	/* XXX: This is an awful hack that could hurt performance, but		on the bright side it should work until we come up		with a better solution. 		In the meantime, should the goto be dropped in favor		of a loop? 		The issue is that in the first loop blocksize() is called		which calls instrsize() which requires i_oparg be set		appropriately.	There is a bootstrap problem because		i_oparg is calculated in the second loop above. 		So we loop until we stop seeing new EXTENDED_ARGs.		The only EXTENDED_ARGs that could be popping up are		ones in jump instructions.  So this should converge		fairly quickly.	*/	if (last_extended_arg_count != extended_arg_count) {		last_extended_arg_count = extended_arg_count;		goto start;	}} static PyObject *dict_keys_inorder(PyObject *dict, int offset){	PyObject *tuple, *k, *v;	Py_ssize_t i, pos = 0, size = PyDict_Size(dict); 	tuple = PyTuple_New(size);	if (tuple == NULL)		return NULL;	while (PyDict_Next(dict, &pos, &k, &v)) {		i = PyInt_AS_LONG(v);		k = PyTuple_GET_ITEM(k, 0);		Py_INCREF(k);		assert((i - offset) < size);		assert((i - offset) >= 0);		PyTuple_SET_ITEM(tuple, i - offset, k);	}	return tuple;} static intcompute_code_flags(struct compiler *c){	PySTEntryObject *ste = c->u->u_ste;	int flags = 0, n;	if (ste->ste_type != ModuleBlock)		flags |= CO_NEWLOCALS;	if (ste->ste_type == FunctionBlock) {		if (!ste->ste_unoptimized)			flags |= CO_OPTIMIZED;		if (ste->ste_nested)			flags |= CO_NESTED;		if (ste->ste_generator)			flags |= CO_GENERATOR;	}	if (ste->ste_varargs)		flags |= CO_VARARGS;	if (ste->ste_varkeywords)		flags |= CO_VARKEYWORDS;	if (ste->ste_generator)		flags |= CO_GENERATOR; 	/* (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;	    }	} 	return flags;} static PyCodeObject *makecode(struct compiler *c, struct assembler *a){	PyObject *tmp;	PyCodeObject *co = NULL;	PyObject *consts = NULL;	PyObject *names = NULL;	PyObject *varnames = NULL;	PyObject *filename = NULL;	PyObject *name = NULL;	PyObject *freevars = NULL;	PyObject *cellvars = NULL;	PyObject *bytecode = NULL;	int nlocals, flags; 	tmp = dict_keys_inorder(c->u->u_consts, 0);	if (!tmp)		goto error;	consts = PySequence_List(tmp); /* optimize_code requires a list */	Py_DECREF(tmp); 	names = dict_keys_inorder(c->u->u_names, 0);	varnames = dict_keys_inorder(c->u->u_varnames, 0);	if (!consts || !names || !varnames)		goto error;      	cellvars = dict_keys_inorder(c->u->u_cellvars, 0);	if (!cellvars)	    goto error;	freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars));	if (!freevars)	    goto error;	filename = PyString_FromString(c->c_filename);	if (!filename)		goto error; 	nlocals = PyDict_Size(c->u->u_varnames);	flags = compute_code_flags(c);	if (flags < 0)		goto error; 	bytecode = optimize_code(a->a_bytecode, consts, names, a->a_lnotab);	if (!bytecode)		goto error; 	tmp = PyList_AsTuple(consts); /* PyCode_New requires a tuple */	if (!tmp)		goto error;	Py_DECREF(consts);	consts = tmp; 	co = PyCode_New(c->u->u_argcount, nlocals, stackdepth(c), flags,			bytecode, consts, names, varnames,			freevars, cellvars,			filename, c->u->u_name,			c->u->u_firstlineno,			a->a_lnotab); error:	Py_XDECREF(consts);	Py_XDECREF(names);	Py_XDECREF(varnames);	Py_XDECREF(filename);	Py_XDECREF(name);	Py_XDECREF(freevars);	Py_XDECREF(cellvars);	Py_XDECREF(bytecode);	return co;}  /* For debugging purposes only */#if 0static voiddump_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 voiddump_basicblock(const basicblock *b){	const char *seen = b->b_seen ? "seen " : "";	const char *b_return = b->b_return ? "return " : "";

Lines 4001–4500 of 4570. Previous lines