cinap_lenrekadd hg and python4bb9e2215 years agoHistory
4351 lines · 104.0 KB · C
RawDownload
  /* Interpreter main loop */ PyObject *PyEval_EvalFrame(PyFrameObject *f) {	/* This is for backward compatibility with extension modules that           used this API; core interpreter code should call PyEval_EvalFrameEx() */	return PyEval_EvalFrameEx(f, 0);} PyObject *PyEval_EvalFrameEx(PyFrameObject *f, int throwflag){#ifdef DXPAIRS	int lastopcode = 0;#endif	register PyObject **stack_pointer;   /* Next free slot in value stack */	register unsigned char *next_instr;	register int opcode;	/* Current opcode */	register int oparg;	/* Current opcode argument, if any */	register enum why_code why; /* Reason for block stack unwind */	register int err;	/* Error status -- nonzero if error */	register PyObject *x;	/* Result object -- NULL if error */	register PyObject *v;	/* Temporary objects popped off stack */	register PyObject *w;	register PyObject *u;	register PyObject *t;	register PyObject *stream = NULL;    /* for PRINT opcodes */	register PyObject **fastlocals, **freevars;	PyObject *retval = NULL;	/* Return value */	PyThreadState *tstate = PyThreadState_GET();	PyCodeObject *co; 	/* when tracing we set things up so that                not (instr_lb <= current_bytecode_offset < instr_ub) 	   is true when the line being executed has changed.  The           initial values are such as to make this false the first           time it is tested. */	int instr_ub = -1, instr_lb = 0, instr_prev = -1; 	unsigned char *first_instr;	PyObject *names;	PyObject *consts;#if defined(Py_DEBUG) || defined(LLTRACE)	/* Make it easier to find out where we are with a debugger */	char *filename;#endif /* Tuple access macros */ #ifndef Py_DEBUG#define GETITEM(v, i) PyTuple_GET_ITEM((PyTupleObject *)(v), (i))#else#define GETITEM(v, i) PyTuple_GetItem((v), (i))#endif #ifdef WITH_TSC/* Use Pentium timestamp counter to mark certain events:   inst0 -- beginning of switch statement for opcode dispatch   inst1 -- end of switch statement (may be skipped)   loop0 -- the top of the mainloop   loop1 -- place where control returns again to top of mainloop            (may be skipped)   intr1 -- beginning of long interruption   intr2 -- end of long interruption    Many opcodes call out to helper C functions.  In some cases, the   time in those functions should be counted towards the time for the   opcode, but not in all cases.  For example, a CALL_FUNCTION opcode   calls another Python function; there's no point in charge all the   bytecode executed by the called function to the caller.    It's hard to make a useful judgement statically.  In the presence   of operator overloading, it's impossible to tell if a call will   execute new Python code or not.    It's a case-by-case judgement.  I'll use intr1 for the following   cases:    EXEC_STMT   IMPORT_STAR   IMPORT_FROM   CALL_FUNCTION (and friends)  */	uint64 inst0, inst1, loop0, loop1, intr0 = 0, intr1 = 0;	int ticked = 0; 	READ_TIMESTAMP(inst0);	READ_TIMESTAMP(inst1);	READ_TIMESTAMP(loop0);	READ_TIMESTAMP(loop1); 	/* shut up the compiler */	opcode = 0;#endif /* Code access macros */ #define INSTR_OFFSET()	((int)(next_instr - first_instr))#define NEXTOP()	(*next_instr++)#define NEXTARG()	(next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])#define PEEKARG()	((next_instr[2]<<8) + next_instr[1])#define JUMPTO(x)	(next_instr = first_instr + (x))#define JUMPBY(x)	(next_instr += (x)) /* OpCode prediction macros	Some opcodes tend to come in pairs thus making it possible to predict	the second code when the first is run.  For example, COMPARE_OP is often	followed by JUMP_IF_FALSE or JUMP_IF_TRUE.  And, those opcodes are often	followed by a POP_TOP. 	Verifying the prediction costs a single high-speed test of register	variable against a constant.  If the pairing was good, then the	processor has a high likelihood of making its own successful branch	prediction which results in a nearly zero overhead transition to the	next opcode. 	A successful prediction saves a trip through the eval-loop including	its two unpredictable branches, the HASARG test and the switch-case.         If collecting opcode statistics, turn off prediction so that	statistics are accurately maintained (the predictions bypass	the opcode frequency counter updates).*/ #ifdef DYNAMIC_EXECUTION_PROFILE#define PREDICT(op)		if (0) goto PRED_##op#else#define PREDICT(op)		if (*next_instr == op) goto PRED_##op#endif #define PREDICTED(op)		PRED_##op: next_instr++#define PREDICTED_WITH_ARG(op)	PRED_##op: oparg = PEEKARG(); next_instr += 3 /* Stack manipulation macros */ /* The stack can grow at most MAXINT deep, as co_nlocals and   co_stacksize are ints. */#define STACK_LEVEL()	((int)(stack_pointer - f->f_valuestack))#define EMPTY()		(STACK_LEVEL() == 0)#define TOP()		(stack_pointer[-1])#define SECOND()	(stack_pointer[-2])#define THIRD() 	(stack_pointer[-3])#define FOURTH()	(stack_pointer[-4])#define SET_TOP(v)	(stack_pointer[-1] = (v))#define SET_SECOND(v)	(stack_pointer[-2] = (v))#define SET_THIRD(v)	(stack_pointer[-3] = (v))#define SET_FOURTH(v)	(stack_pointer[-4] = (v))#define BASIC_STACKADJ(n)	(stack_pointer += n)#define BASIC_PUSH(v)	(*stack_pointer++ = (v))#define BASIC_POP()	(*--stack_pointer) #ifdef LLTRACE#define PUSH(v)		{ (void)(BASIC_PUSH(v), \                               lltrace && prtrace(TOP(), "push")); \                               assert(STACK_LEVEL() <= co->co_stacksize); }#define POP()		((void)(lltrace && prtrace(TOP(), "pop")), BASIC_POP())#define STACKADJ(n)	{ (void)(BASIC_STACKADJ(n), \                               lltrace && prtrace(TOP(), "stackadj")); \                               assert(STACK_LEVEL() <= co->co_stacksize); }#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER))#else#define PUSH(v)		BASIC_PUSH(v)#define POP()		BASIC_POP()#define STACKADJ(n)	BASIC_STACKADJ(n)#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER))#endif /* Local variable macros */ #define GETLOCAL(i)	(fastlocals[i]) /* The SETLOCAL() macro must not DECREF the local variable in-place and   then store the new value; it must copy the old value to a temporary   value, then store the new value, and then DECREF the temporary value.   This is because it is possible that during the DECREF the frame is   accessed by other code (e.g. a __del__ method or gc.collect()) and the   variable would be pointing to already-freed memory. */#define SETLOCAL(i, value)	do { PyObject *tmp = GETLOCAL(i); \				     GETLOCAL(i) = value; \                                     Py_XDECREF(tmp); } while (0) /* Start of code */ 	if (f == NULL)		return NULL; 	/* push frame */	if (Py_EnterRecursiveCall(""))		return NULL; 	tstate->frame = f; 	if (tstate->use_tracing) {		if (tstate->c_tracefunc != NULL) {			/* tstate->c_tracefunc, if defined, is a			   function that will be called on *every* entry			   to a code block.  Its return value, if not			   None, is a function that will be called at			   the start of each executed line of code.			   (Actually, the function must return itself			   in order to continue tracing.)  The trace			   functions are called with three arguments:			   a pointer to the current frame, a string			   indicating why the function is called, and			   an argument which depends on the situation.			   The global trace function is also called			   whenever an exception is detected. */			if (call_trace(tstate->c_tracefunc, tstate->c_traceobj,				       f, PyTrace_CALL, Py_None)) {				/* Trace function raised an error */				goto exit_eval_frame;			}		}		if (tstate->c_profilefunc != NULL) {			/* Similar for c_profilefunc, except it needn't			   return itself and isn't called for "line" events */			if (call_trace(tstate->c_profilefunc,				       tstate->c_profileobj,				       f, PyTrace_CALL, Py_None)) {				/* Profile function raised an error */				goto exit_eval_frame;			}		}	} 	co = f->f_code;	names = co->co_names;	consts = co->co_consts;	fastlocals = f->f_localsplus;	freevars = f->f_localsplus + co->co_nlocals;	first_instr = (unsigned char*) PyString_AS_STRING(co->co_code);	/* An explanation is in order for the next line. 	   f->f_lasti now refers to the index of the last instruction	   executed.  You might think this was obvious from the name, but	   this wasn't always true before 2.3!  PyFrame_New now sets	   f->f_lasti to -1 (i.e. the index *before* the first instruction)	   and YIELD_VALUE doesn't fiddle with f_lasti any more.  So this	   does work.  Promise. */	next_instr = first_instr + f->f_lasti + 1;	stack_pointer = f->f_stacktop;	assert(stack_pointer != NULL);	f->f_stacktop = NULL;	/* remains NULL unless yield suspends frame */ #ifdef LLTRACE	lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL;#endif#if defined(Py_DEBUG) || defined(LLTRACE)	filename = PyString_AsString(co->co_filename);#endif 	why = WHY_NOT;	err = 0;	x = Py_None;	/* Not a reference, just anything non-NULL */	w = NULL; 	if (throwflag) { /* support for generator.throw() */		why = WHY_EXCEPTION;		goto on_error;	} 	for (;;) {#ifdef WITH_TSC		if (inst1 == 0) {			/* Almost surely, the opcode executed a break			   or a continue, preventing inst1 from being set			   on the way out of the loop.			*/			READ_TIMESTAMP(inst1);			loop1 = inst1;		}		dump_tsc(opcode, ticked, inst0, inst1, loop0, loop1,			 intr0, intr1);		ticked = 0;		inst1 = 0;		intr0 = 0;		intr1 = 0;		READ_TIMESTAMP(loop0);#endif		assert(stack_pointer >= f->f_valuestack); /* else underflow */		assert(STACK_LEVEL() <= co->co_stacksize);  /* else overflow */ 		/* Do periodic things.  Doing this every time through		   the loop would add too much overhead, so we do it		   only every Nth instruction.  We also do it if		   ``things_to_do'' is set, i.e. when an asynchronous		   event needs attention (e.g. a signal handler or		   async I/O handler); see Py_AddPendingCall() and		   Py_MakePendingCalls() above. */ 		if (--_Py_Ticker < 0) {                        if (*next_instr == SETUP_FINALLY) {                                /* Make the last opcode before                                   a try: finally: block uninterruptable. */                                goto fast_next_opcode;                        }			_Py_Ticker = _Py_CheckInterval;			tstate->tick_counter++;#ifdef WITH_TSC			ticked = 1;#endif			if (things_to_do) {				if (Py_MakePendingCalls() < 0) {					why = WHY_EXCEPTION;					goto on_error;				}				if (things_to_do)					/* MakePendingCalls() didn't succeed.					   Force early re-execution of this					   "periodic" code, possibly after					   a thread switch */					_Py_Ticker = 0;			}#ifdef WITH_THREAD			if (interpreter_lock) {				/* Give another thread a chance */ 				if (PyThreadState_Swap(NULL) != tstate)					Py_FatalError("ceval: tstate mix-up");				PyThread_release_lock(interpreter_lock); 				/* Other threads may run now */ 				PyThread_acquire_lock(interpreter_lock, 1);				if (PyThreadState_Swap(tstate) != NULL)					Py_FatalError("ceval: orphan tstate"); 				/* Check for thread interrupts */ 				if (tstate->async_exc != NULL) {					x = tstate->async_exc;					tstate->async_exc = NULL;					PyErr_SetNone(x);					Py_DECREF(x);					why = WHY_EXCEPTION;					goto on_error;				}			}#endif		} 	fast_next_opcode:		f->f_lasti = INSTR_OFFSET(); 		/* line-by-line tracing support */ 		if (tstate->c_tracefunc != NULL && !tstate->tracing) {			/* see maybe_call_line_trace			   for expository comments */			f->f_stacktop = stack_pointer; 			err = maybe_call_line_trace(tstate->c_tracefunc,						    tstate->c_traceobj,						    f, &instr_lb, &instr_ub,						    &instr_prev);			/* Reload possibly changed frame fields */			JUMPTO(f->f_lasti);			if (f->f_stacktop != NULL) {				stack_pointer = f->f_stacktop;				f->f_stacktop = NULL;			}			if (err) {				/* trace function raised an exception */				goto on_error;			}		} 		/* Extract opcode and argument */ 		opcode = NEXTOP();		oparg = 0;   /* allows oparg to be stored in a register because			it doesn't have to be remembered across a full loop */		if (HAS_ARG(opcode))			oparg = NEXTARG();	  dispatch_opcode:#ifdef DYNAMIC_EXECUTION_PROFILE#ifdef DXPAIRS		dxpairs[lastopcode][opcode]++;		lastopcode = opcode;#endif		dxp[opcode]++;#endif #ifdef LLTRACE		/* Instruction tracing */ 		if (lltrace) {			if (HAS_ARG(opcode)) {				printf("%d: %d, %d\n",				       f->f_lasti, opcode, oparg);			}			else {				printf("%d: %d\n",				       f->f_lasti, opcode);			}		}#endif 		/* Main switch on opcode */		READ_TIMESTAMP(inst0); 		switch (opcode) { 		/* BEWARE!		   It is essential that any operation that fails sets either		   x to NULL, err to nonzero, or why to anything but WHY_NOT,		   and that no operation that succeeds does this! */ 		/* case STOP_CODE: this is an error! */ 		case NOP:			goto fast_next_opcode; 		case LOAD_FAST:			x = GETLOCAL(oparg);			if (x != NULL) {				Py_INCREF(x);				PUSH(x);				goto fast_next_opcode;			}			format_exc_check_arg(PyExc_UnboundLocalError,				UNBOUNDLOCAL_ERROR_MSG,				PyTuple_GetItem(co->co_varnames, oparg));			break; 		case LOAD_CONST:			x = GETITEM(consts, oparg);			Py_INCREF(x);			PUSH(x);			goto fast_next_opcode; 		PREDICTED_WITH_ARG(STORE_FAST);		case STORE_FAST:			v = POP();			SETLOCAL(oparg, v);			goto fast_next_opcode; 		PREDICTED(POP_TOP);		case POP_TOP:			v = POP();			Py_DECREF(v);			goto fast_next_opcode; 		case ROT_TWO:			v = TOP();			w = SECOND();			SET_TOP(w);			SET_SECOND(v);			goto fast_next_opcode; 		case ROT_THREE:			v = TOP();			w = SECOND();			x = THIRD();			SET_TOP(w);			SET_SECOND(x);			SET_THIRD(v);			goto fast_next_opcode; 		case ROT_FOUR:			u = TOP();			v = SECOND();			w = THIRD();			x = FOURTH();			SET_TOP(v);			SET_SECOND(w);			SET_THIRD(x);			SET_FOURTH(u);			goto fast_next_opcode; 		case DUP_TOP:			v = TOP();			Py_INCREF(v);			PUSH(v);			goto fast_next_opcode; 		case DUP_TOPX:			if (oparg == 2) {				x = TOP();				Py_INCREF(x);				w = SECOND();				Py_INCREF(w);				STACKADJ(2);				SET_TOP(x);				SET_SECOND(w);				goto fast_next_opcode;			} else if (oparg == 3) {				x = TOP();				Py_INCREF(x);				w = SECOND();				Py_INCREF(w);				v = THIRD();				Py_INCREF(v);				STACKADJ(3);				SET_TOP(x);

Lines 501–1000 of 4351. Previous lines