📄 ceval.c
字号:
SPy_Python_globals *PYTHON_GLOBALS_localcopy=PYTHON_GLOBALS;
#undef PYTHON_GLOBALS
#define PYTHON_GLOBALS PYTHON_GLOBALS_localcopy
#ifdef DXPAIRS
int lastopcode = 0;
#endif
PyObject **stack_pointer; /* Next free slot in value stack */
register unsigned char *next_instr;
register int opcode=0; /* Current opcode */
register int oparg=0; /* 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;
unsigned char *first_instr;
#ifdef LLTRACE
int lltrace;
#endif
#if defined(Py_DEBUG) || defined(LLTRACE)
/* Make it easier to find out where we are with a debugger */
char *filename;
#endif
/* Code access macros */
#define GETCONST(i) Getconst(f, i)
#define GETNAME(i) Getname(f, i)
#define GETNAMEV(i) Getnamev(f, i)
#define INSTR_OFFSET() (next_instr - first_instr)
#define NEXTOP() (*next_instr++)
#define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
#define JUMPTO(x) (next_instr = first_instr + (x))
#define JUMPBY(x) (next_instr += (x))
/* Stack manipulation macros */
#define STACK_LEVEL() (stack_pointer - f->f_valuestack)
#define STACK_EMPTY() (STACK_LEVEL() == 0)
#define TOP() (stack_pointer[-1])
#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() <= f->f_stacksize); }
#define POP() ((void)(lltrace && prtrace(TOP(), "pop")), BASIC_POP())
#else
#define PUSH(v) BASIC_PUSH(v)
#define POP() BASIC_POP()
#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;
#ifdef USE_STACKCHECK
if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "Stack overflow");
return NULL;
}
#endif
/* push frame */
if (++tstate->recursion_depth > Py_GetRecursionLimit()) {
--tstate->recursion_depth;
PyErr_SetString(PyExc_RuntimeError,
"maximum recursion depth exceeded");
tstate->frame = f->f_back;
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 */
--tstate->recursion_depth;
tstate->frame = f->f_back;
return NULL;
}
}
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 */
--tstate->recursion_depth;
tstate->frame = f->f_back;
return NULL;
}
}
}
co = f->f_code;
fastlocals = f->f_localsplus;
freevars = f->f_localsplus + f->f_nlocals;
_PyCode_GETCODEPTR(co, &first_instr);
next_instr = first_instr + f->f_lasti;
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;
for (;;) {
assert(stack_pointer >= f->f_valuestack); /* else underflow */
assert(STACK_LEVEL() <= f->f_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 (things_to_do || --tstate->ticker < 0) {
tstate->ticker = tstate->interp->checkinterval;
tstate->tick_counter++;
if (things_to_do) {
if (Py_MakePendingCalls() < 0) {
why = WHY_EXCEPTION;
goto on_error;
}
}
#if !defined(HAVE_SIGNAL_H) || defined(macintosh)
/* If we have true signals, the signal handler
will call Py_AddPendingCall() so we don't
have to call sigcheck(). On the Mac and
DOS, alas, we have to call it. */
if (PyErr_CheckSignals()) {
why = WHY_EXCEPTION;
goto on_error;
}
#endif
#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");
}
#endif
}
/* Extract opcode and argument */
#if defined(Py_DEBUG) || defined(LLTRACE)
f->f_lasti = INSTR_OFFSET();
#endif
opcode = NEXTOP();
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",
(int) (INSTR_OFFSET() - 3),
opcode, oparg);
}
else {
printf("%d: %d\n",
(int) (INSTR_OFFSET() - 1), opcode);
}
}
#endif
/* Main switch on opcode */
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 POP_TOP:
v = POP();
Py_DECREF(v);
continue;
case ROT_TWO:
v = POP();
w = POP();
PUSH(v);
PUSH(w);
continue;
case ROT_THREE:
v = POP();
w = POP();
x = POP();
PUSH(v);
PUSH(x);
PUSH(w);
continue;
case ROT_FOUR:
u = POP();
v = POP();
w = POP();
x = POP();
PUSH(u);
PUSH(x);
PUSH(w);
PUSH(v);
continue;
case DUP_TOP:
v = TOP();
Py_INCREF(v);
PUSH(v);
continue;
case DUP_TOPX:
switch (oparg) {
case 1:
x = TOP();
Py_INCREF(x);
PUSH(x);
continue;
case 2:
x = POP();
Py_INCREF(x);
w = TOP();
Py_INCREF(w);
PUSH(x);
PUSH(w);
PUSH(x);
continue;
case 3:
x = POP();
Py_INCREF(x);
w = POP();
Py_INCREF(w);
v = TOP();
Py_INCREF(v);
PUSH(w);
PUSH(x);
PUSH(v);
PUSH(w);
PUSH(x);
continue;
case 4:
x = POP();
Py_INCREF(x);
w = POP();
Py_INCREF(w);
v = POP();
Py_INCREF(v);
u = TOP();
Py_INCREF(u);
PUSH(v);
PUSH(w);
PUSH(x);
PUSH(u);
PUSH(v);
PUSH(w);
PUSH(x);
continue;
case 5:
x = POP();
Py_INCREF(x);
w = POP();
Py_INCREF(w);
v = POP();
Py_INCREF(v);
u = POP();
Py_INCREF(u);
t = TOP();
Py_INCREF(t);
PUSH(u);
PUSH(v);
PUSH(w);
PUSH(x);
PUSH(t);
PUSH(u);
PUSH(v);
PUSH(w);
PUSH(x);
continue;
default:
Py_FatalError("invalid argument to DUP_TOPX"
" (bytecode corruption?)");
}
break;
case UNARY_POSITIVE:
v = POP();
x = PyNumber_Positive(v);
Py_DECREF(v);
PUSH(x);
if (x != NULL) continue;
break;
case UNARY_NEGATIVE:
v = POP();
x = PyNumber_Negative(v);
Py_DECREF(v);
PUSH(x);
if (x != NULL) continue;
break;
case UNARY_NOT:
v = POP();
err = PyObject_IsTrue(v);
Py_DECREF(v);
if (err == 0) {
Py_INCREF(Py_True);
PUSH(Py_True);
continue;
}
else if (err > 0) {
Py_INCREF(Py_False);
PUSH(Py_False);
err = 0;
continue;
}
break;
case UNARY_CONVERT:
v = POP();
x = PyObject_Repr(v);
Py_DECREF(v);
PUSH(x);
if (x != NULL) continue;
break;
case UNARY_INVERT:
v = POP();
x = PyNumber_Invert(v);
Py_DECREF(v);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_POWER:
w = POP();
v = POP();
x = PyNumber_Power(v, w, Py_None);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_MULTIPLY:
w = POP();
v = POP();
x = PyNumber_Multiply(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_DIVIDE:
if (!_Py_QnewFlag) {
w = POP();
v = POP();
x = PyNumber_Divide(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
}
/* -Qnew is in effect: fall through to
BINARY_TRUE_DIVIDE */
case BINARY_TRUE_DIVIDE:
w = POP();
v = POP();
x = PyNumber_TrueDivide(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_FLOOR_DIVIDE:
w = POP();
v = POP();
x = PyNumber_FloorDivide(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_MODULO:
w = POP();
v = POP();
x = PyNumber_Remainder(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_ADD:
w = POP();
v = POP();
if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
i = a + b;
if ((i^a) < 0 && (i^b) < 0)
goto slow_add;
x = PyInt_FromLong(i);
}
else {
slow_add:
x = PyNumber_Add(v, w);
}
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_SUBTRACT:
w = POP();
v = POP();
if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: int - int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
i = a - b;
if ((i^a) < 0 && (i^~b) < 0)
goto slow_sub;
x = PyInt_FromLong(i);
}
else {
slow_sub:
x = PyNumber_Subtract(v, w);
}
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_SUBSCR:
w = POP();
v = POP();
if (PyList_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: list[int] */
long i = PyInt_AsLong(w);
if (i < 0)
i += PyList_GET_SIZE(v);
if (i < 0 ||
i >= PyList_GET_SIZE(v)) {
PyErr_SetString(PyExc_IndexError,
"list index out of range");
x = NULL;
}
else {
x = PyList_GET_ITEM(v, i);
Py_INCREF(x);
}
}
else
x = PyObject_GetItem(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
case BINARY_LSHIFT:
w = POP();
v = POP();
x = PyNumber_Lshift(v, w);
Py_DECREF(v);
Py_DECREF(w);
PUSH(x);
if (x != NULL) continue;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -