summaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c2376
1 files changed, 1279 insertions, 1097 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 2b1619163b..7a0cb7f04a 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -37,7 +37,7 @@ typedef unsigned long long uint64;
static void
ppc_getcounter(uint64 *v)
{
- register unsigned long tbu, tb, tbu2;
+ unsigned long tbu, tb, tbu2;
loop:
asm volatile ("mftbu %0" : "=r" (tbu) );
@@ -65,9 +65,11 @@ ppc_getcounter(uint64 *v)
even in 64-bit mode, we need to use "a" and "d" for the lower and upper
32-bit pieces of the result. */
-#define READ_TIMESTAMP(val) \
- __asm__ __volatile__("rdtsc" : \
- "=a" (((int*)&(val))[0]), "=d" (((int*)&(val))[1]));
+#define READ_TIMESTAMP(val) do { \
+ unsigned int h, l; \
+ __asm__ __volatile__("rdtsc" : "=a" (l), "=d" (h)); \
+ (val) = ((uint64)l) | (((uint64)h) << 32); \
+ } while(0)
#else
@@ -123,13 +125,16 @@ static PyObject * load_args(PyObject ***, int);
static int lltrace;
static int prtrace(PyObject *, char *);
#endif
-static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
+static int call_trace(Py_tracefunc, PyObject *,
+ PyThreadState *, PyFrameObject *,
int, PyObject *);
static int call_trace_protected(Py_tracefunc, PyObject *,
- PyFrameObject *, int, PyObject *);
-static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
+ PyThreadState *, PyFrameObject *,
+ int, PyObject *);
+static void call_exc_trace(Py_tracefunc, PyObject *,
+ PyThreadState *, PyFrameObject *);
static int maybe_call_line_trace(Py_tracefunc, PyObject *,
- PyFrameObject *, int *, int *, int *);
+ PyThreadState *, PyFrameObject *, int *, int *, int *);
static PyObject * cmp_outcome(int, PyObject *, PyObject *);
static PyObject * import_from(PyObject *, PyObject *);
@@ -142,8 +147,6 @@ static PyObject * special_lookup(PyObject *, _Py_Identifier *);
#define NAME_ERROR_MSG \
"name '%.200s' is not defined"
-#define GLOBAL_NAME_ERROR_MSG \
- "global name '%.200s' is not defined"
#define UNBOUNDLOCAL_ERROR_MSG \
"local variable '%.200s' referenced before assignment"
#define UNBOUNDFREE_ERROR_MSG \
@@ -364,29 +367,28 @@ PyEval_ReleaseThread(PyThreadState *tstate)
drop_gil(tstate);
}
-/* This function is called from PyOS_AfterFork to ensure that newly
- created child processes don't hold locks referring to threads which
- are not running in the child process. (This could also be done using
- pthread_atfork mechanism, at least for the pthreads implementation.) */
+/* This function is called from PyOS_AfterFork to destroy all threads which are
+ * not running in the child process, and clear internal locks which might be
+ * held by those threads. (This could also be done using pthread_atfork
+ * mechanism, at least for the pthreads implementation.) */
void
PyEval_ReInitThreads(void)
{
_Py_IDENTIFIER(_after_fork);
PyObject *threading, *result;
- PyThreadState *tstate = PyThreadState_GET();
+ PyThreadState *current_tstate = PyThreadState_GET();
if (!gil_created())
return;
recreate_gil();
pending_lock = PyThread_allocate_lock();
- take_gil(tstate);
+ take_gil(current_tstate);
main_thread = PyThread_get_thread_ident();
/* Update the threading module with the new state.
*/
- tstate = PyThreadState_GET();
- threading = PyMapping_GetItemString(tstate->interp->modules,
+ threading = PyMapping_GetItemString(current_tstate->interp->modules,
"threading");
if (threading == NULL) {
/* threading not imported */
@@ -399,6 +401,9 @@ PyEval_ReInitThreads(void)
else
Py_DECREF(result);
Py_DECREF(threading);
+
+ /* Destroy all threads except the current one */
+ _PyThreadState_DeleteExcept(current_tstate);
}
#else
@@ -705,7 +710,7 @@ Py_SetRecursionLimit(int new_limit)
to guarantee that _Py_CheckRecursiveCall() is regularly called.
Without USE_STACKCHECK, there is no need for this. */
int
-_Py_CheckRecursiveCall(char *where)
+_Py_CheckRecursiveCall(const char *where)
{
PyThreadState *tstate = PyThreadState_GET();
@@ -742,7 +747,6 @@ _Py_CheckRecursiveCall(char *where)
enum why_code {
WHY_NOT = 0x0001, /* No error */
WHY_EXCEPTION = 0x0002, /* Exception occurred */
- WHY_RERAISE = 0x0004, /* Exception re-raised by 'finally' */
WHY_RETURN = 0x0008, /* 'return' statement */
WHY_BREAK = 0x0010, /* 'break' statement */
WHY_CONTINUE = 0x0020, /* 'continue' statement */
@@ -753,7 +757,7 @@ enum why_code {
static void save_exc_state(PyThreadState *, PyFrameObject *);
static void swap_exc_state(PyThreadState *, PyFrameObject *);
static void restore_and_clear_exc_state(PyThreadState *, PyFrameObject *);
-static enum why_code do_raise(PyObject *, PyObject *);
+static int do_raise(PyObject *, PyObject *);
static int unpack_iterable(PyObject *, int, int, PyObject **);
/* Records whether tracing is on for any thread. Counts the number of
@@ -793,18 +797,12 @@ 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 **fastlocals, **freevars;
+ PyObject **stack_pointer; /* Next free slot in value stack */
+ unsigned char *next_instr;
+ int opcode; /* Current opcode */
+ int oparg; /* Current opcode argument, if any */
+ enum why_code why; /* Reason for block stack unwind */
+ PyObject **fastlocals, **freevars;
PyObject *retval = NULL; /* Return value */
PyThreadState *tstate = PyThreadState_GET();
PyCodeObject *co;
@@ -1143,7 +1141,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
whenever an exception is detected. */
if (call_trace_protected(tstate->c_tracefunc,
tstate->c_traceobj,
- f, PyTrace_CALL, Py_None)) {
+ tstate, f, PyTrace_CALL, Py_None)) {
/* Trace function raised an error */
goto exit_eval_frame;
}
@@ -1153,7 +1151,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
return itself and isn't called for "line" events */
if (call_trace_protected(tstate->c_profilefunc,
tstate->c_profileobj,
- f, PyTrace_CALL, Py_None)) {
+ tstate, f, PyTrace_CALL, Py_None)) {
/* Profile function raised an error */
goto exit_eval_frame;
}
@@ -1189,9 +1187,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
stack_pointer = f->f_stacktop;
assert(stack_pointer != NULL);
f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */
+ f->f_executing = 1;
- if (co->co_flags & CO_GENERATOR && !throwflag) {
- if (f->f_exc_type != NULL && f->f_exc_type != Py_None) {
+ if (co->co_flags & CO_GENERATOR) {
+ if (!throwflag && f->f_exc_type != NULL && f->f_exc_type != Py_None) {
/* We were in an except handler when we left,
restore the exception state which was put aside
(see YIELD_VALUE). */
@@ -1206,14 +1205,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
#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;
- }
+ if (throwflag) /* support for generator.throw() */
+ goto error;
+
+#ifdef Py_DEBUG
+ /* PyEval_EvalFrameEx() must not be called with an exception set,
+ because it may clear it (directly or indirectly) and so the
+ caller loses its exception */
+ assert(!PyErr_Occurred());
+#endif
for (;;) {
#ifdef WITH_TSC
@@ -1235,6 +1236,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
#endif
assert(stack_pointer >= f->f_valuestack); /* else underflow */
assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */
+ assert(!PyErr_Occurred());
/* Do periodic things. Doing this every time through
the loop would add too much overhead, so we do it
@@ -1250,15 +1252,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
a try: finally: block uninterruptible. */
goto fast_next_opcode;
}
- tstate->tick_counter++;
#ifdef WITH_TSC
ticked = 1;
#endif
if (_Py_atomic_load_relaxed(&pendingcalls_to_do)) {
- if (Py_MakePendingCalls() < 0) {
- why = WHY_EXCEPTION;
- goto on_error;
- }
+ if (Py_MakePendingCalls() < 0)
+ goto error;
}
#ifdef WITH_THREAD
if (_Py_atomic_load_relaxed(&gil_drop_request)) {
@@ -1270,19 +1269,25 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* Other threads may run now */
take_gil(tstate);
+
+ /* Check if we should make a quick exit. */
+ if (_Py_Finalizing && _Py_Finalizing != tstate) {
+ drop_gil(tstate);
+ PyThread_exit_thread();
+ }
+
if (PyThreadState_Swap(tstate) != NULL)
Py_FatalError("ceval: orphan tstate");
}
#endif
/* Check for asynchronous exceptions. */
if (tstate->async_exc != NULL) {
- x = tstate->async_exc;
+ PyObject *exc = tstate->async_exc;
tstate->async_exc = NULL;
UNSIGNAL_ASYNC_EXC();
- PyErr_SetNone(x);
- Py_DECREF(x);
- why = WHY_EXCEPTION;
- goto on_error;
+ PyErr_SetNone(exc);
+ Py_DECREF(exc);
+ goto error;
}
}
@@ -1293,24 +1298,24 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
if (_Py_TracingPossible &&
tstate->c_tracefunc != NULL && !tstate->tracing) {
+ int err;
/* 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);
+ tstate, 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) {
+ if (err)
/* trace function raised an exception */
- goto on_error;
- }
+ goto error;
}
/* Extract opcode and argument */
@@ -1357,87 +1362,99 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
TARGET(NOP)
FAST_DISPATCH();
- TARGET(LOAD_FAST)
- x = GETLOCAL(oparg);
- if (x != NULL) {
- Py_INCREF(x);
- PUSH(x);
- FAST_DISPATCH();
+ TARGET(LOAD_FAST) {
+ PyObject *value = GETLOCAL(oparg);
+ if (value == NULL) {
+ format_exc_check_arg(PyExc_UnboundLocalError,
+ UNBOUNDLOCAL_ERROR_MSG,
+ PyTuple_GetItem(co->co_varnames, oparg));
+ goto error;
}
- format_exc_check_arg(PyExc_UnboundLocalError,
- UNBOUNDLOCAL_ERROR_MSG,
- PyTuple_GetItem(co->co_varnames, oparg));
- break;
+ Py_INCREF(value);
+ PUSH(value);
+ FAST_DISPATCH();
+ }
- TARGET(LOAD_CONST)
- x = GETITEM(consts, oparg);
- Py_INCREF(x);
- PUSH(x);
+ TARGET(LOAD_CONST) {
+ PyObject *value = GETITEM(consts, oparg);
+ Py_INCREF(value);
+ PUSH(value);
FAST_DISPATCH();
+ }
PREDICTED_WITH_ARG(STORE_FAST);
- TARGET(STORE_FAST)
- v = POP();
- SETLOCAL(oparg, v);
+ TARGET(STORE_FAST) {
+ PyObject *value = POP();
+ SETLOCAL(oparg, value);
FAST_DISPATCH();
+ }
- TARGET(POP_TOP)
- v = POP();
- Py_DECREF(v);
+ TARGET(POP_TOP) {
+ PyObject *value = POP();
+ Py_DECREF(value);
FAST_DISPATCH();
+ }
- TARGET(ROT_TWO)
- v = TOP();
- w = SECOND();
- SET_TOP(w);
- SET_SECOND(v);
+ TARGET(ROT_TWO) {
+ PyObject *top = TOP();
+ PyObject *second = SECOND();
+ SET_TOP(second);
+ SET_SECOND(top);
FAST_DISPATCH();
+ }
- TARGET(ROT_THREE)
- v = TOP();
- w = SECOND();
- x = THIRD();
- SET_TOP(w);
- SET_SECOND(x);
- SET_THIRD(v);
+ TARGET(ROT_THREE) {
+ PyObject *top = TOP();
+ PyObject *second = SECOND();
+ PyObject *third = THIRD();
+ SET_TOP(second);
+ SET_SECOND(third);
+ SET_THIRD(top);
FAST_DISPATCH();
+ }
- TARGET(DUP_TOP)
- v = TOP();
- Py_INCREF(v);
- PUSH(v);
+ TARGET(DUP_TOP) {
+ PyObject *top = TOP();
+ Py_INCREF(top);
+ PUSH(top);
FAST_DISPATCH();
+ }
- TARGET(DUP_TOP_TWO)
- x = TOP();
- Py_INCREF(x);
- w = SECOND();
- Py_INCREF(w);
+ TARGET(DUP_TOP_TWO) {
+ PyObject *top = TOP();
+ PyObject *second = SECOND();
+ Py_INCREF(top);
+ Py_INCREF(second);
STACKADJ(2);
- SET_TOP(x);
- SET_SECOND(w);
+ SET_TOP(top);
+ SET_SECOND(second);
FAST_DISPATCH();
+ }
- TARGET(UNARY_POSITIVE)
- v = TOP();
- x = PyNumber_Positive(v);
- Py_DECREF(v);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(UNARY_POSITIVE) {
+ PyObject *value = TOP();
+ PyObject *res = PyNumber_Positive(value);
+ Py_DECREF(value);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(UNARY_NEGATIVE)
- v = TOP();
- x = PyNumber_Negative(v);
- Py_DECREF(v);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(UNARY_NEGATIVE) {
+ PyObject *value = TOP();
+ PyObject *res = PyNumber_Negative(value);
+ Py_DECREF(value);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(UNARY_NOT)
- v = TOP();
- err = PyObject_IsTrue(v);
- Py_DECREF(v);
+ TARGET(UNARY_NOT) {
+ PyObject *value = TOP();
+ int err = PyObject_IsTrue(value);
+ Py_DECREF(value);
if (err == 0) {
Py_INCREF(Py_True);
SET_TOP(Py_True);
@@ -1450,416 +1467,464 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH();
}
STACKADJ(-1);
- break;
+ goto error;
+ }
- TARGET(UNARY_INVERT)
- v = TOP();
- x = PyNumber_Invert(v);
- Py_DECREF(v);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(UNARY_INVERT) {
+ PyObject *value = TOP();
+ PyObject *res = PyNumber_Invert(value);
+ Py_DECREF(value);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_POWER)
- w = POP();
- v = TOP();
- x = PyNumber_Power(v, w, Py_None);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_POWER) {
+ PyObject *exp = POP();
+ PyObject *base = TOP();
+ PyObject *res = PyNumber_Power(base, exp, Py_None);
+ Py_DECREF(base);
+ Py_DECREF(exp);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_MULTIPLY)
- w = POP();
- v = TOP();
- x = PyNumber_Multiply(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_MULTIPLY) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_Multiply(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_TRUE_DIVIDE)
- w = POP();
- v = TOP();
- x = PyNumber_TrueDivide(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_TRUE_DIVIDE) {
+ PyObject *divisor = POP();
+ PyObject *dividend = TOP();
+ PyObject *quotient = PyNumber_TrueDivide(dividend, divisor);
+ Py_DECREF(dividend);
+ Py_DECREF(divisor);
+ SET_TOP(quotient);
+ if (quotient == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_FLOOR_DIVIDE)
- w = POP();
- v = TOP();
- x = PyNumber_FloorDivide(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_FLOOR_DIVIDE) {
+ PyObject *divisor = POP();
+ PyObject *dividend = TOP();
+ PyObject *quotient = PyNumber_FloorDivide(dividend, divisor);
+ Py_DECREF(dividend);
+ Py_DECREF(divisor);
+ SET_TOP(quotient);
+ if (quotient == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_MODULO)
- w = POP();
- v = TOP();
- if (PyUnicode_CheckExact(v))
- x = PyUnicode_Format(v, w);
- else
- x = PyNumber_Remainder(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_MODULO) {
+ PyObject *divisor = POP();
+ PyObject *dividend = TOP();
+ PyObject *res = PyUnicode_CheckExact(dividend) ?
+ PyUnicode_Format(dividend, divisor) :
+ PyNumber_Remainder(dividend, divisor);
+ Py_DECREF(divisor);
+ Py_DECREF(dividend);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_ADD)
- w = POP();
- v = TOP();
- if (PyUnicode_CheckExact(v) &&
- PyUnicode_CheckExact(w)) {
- x = unicode_concatenate(v, w, f, next_instr);
+ TARGET(BINARY_ADD) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *sum;
+ if (PyUnicode_CheckExact(left) &&
+ PyUnicode_CheckExact(right)) {
+ sum = unicode_concatenate(left, right, f, next_instr);
/* unicode_concatenate consumed the ref to v */
- goto skip_decref_vx;
}
else {
- x = PyNumber_Add(v, w);
+ sum = PyNumber_Add(left, right);
+ Py_DECREF(left);
}
- Py_DECREF(v);
- skip_decref_vx:
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
-
- TARGET(BINARY_SUBTRACT)
- w = POP();
- v = TOP();
- x = PyNumber_Subtract(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
-
- TARGET(BINARY_SUBSCR)
- w = POP();
- v = TOP();
- x = PyObject_GetItem(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ Py_DECREF(right);
+ SET_TOP(sum);
+ if (sum == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_LSHIFT)
- w = POP();
- v = TOP();
- x = PyNumber_Lshift(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_SUBTRACT) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *diff = PyNumber_Subtract(left, right);
+ Py_DECREF(right);
+ Py_DECREF(left);
+ SET_TOP(diff);
+ if (diff == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_RSHIFT)
- w = POP();
- v = TOP();
- x = PyNumber_Rshift(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_SUBSCR) {
+ PyObject *sub = POP();
+ PyObject *container = TOP();
+ PyObject *res = PyObject_GetItem(container, sub);
+ Py_DECREF(container);
+ Py_DECREF(sub);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_AND)
- w = POP();
- v = TOP();
- x = PyNumber_And(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_LSHIFT) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_Lshift(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_XOR)
- w = POP();
- v = TOP();
- x = PyNumber_Xor(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_RSHIFT) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_Rshift(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(BINARY_OR)
- w = POP();
- v = TOP();
- x = PyNumber_Or(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BINARY_AND) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_And(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(LIST_APPEND)
- w = POP();
- v = PEEK(oparg);
- err = PyList_Append(v, w);
- Py_DECREF(w);
- if (err == 0) {
- PREDICT(JUMP_ABSOLUTE);
- DISPATCH();
- }
- break;
+ TARGET(BINARY_XOR) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_Xor(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(SET_ADD)
- w = POP();
- v = stack_pointer[-oparg];
- err = PySet_Add(v, w);
- Py_DECREF(w);
- if (err == 0) {
- PREDICT(JUMP_ABSOLUTE);
- DISPATCH();
- }
- break;
+ TARGET(BINARY_OR) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_Or(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_POWER)
- w = POP();
- v = TOP();
- x = PyNumber_InPlacePower(v, w, Py_None);
+ TARGET(LIST_APPEND) {
+ PyObject *v = POP();
+ PyObject *list = PEEK(oparg);
+ int err;
+ err = PyList_Append(list, v);
Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ if (err != 0)
+ goto error;
+ PREDICT(JUMP_ABSOLUTE);
+ DISPATCH();
+ }
- TARGET(INPLACE_MULTIPLY)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceMultiply(v, w);
+ TARGET(SET_ADD) {
+ PyObject *v = POP();
+ PyObject *set = stack_pointer[-oparg];
+ int err;
+ err = PySet_Add(set, v);
Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ if (err != 0)
+ goto error;
+ PREDICT(JUMP_ABSOLUTE);
+ DISPATCH();
+ }
- TARGET(INPLACE_TRUE_DIVIDE)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceTrueDivide(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_POWER) {
+ PyObject *exp = POP();
+ PyObject *base = TOP();
+ PyObject *res = PyNumber_InPlacePower(base, exp, Py_None);
+ Py_DECREF(base);
+ Py_DECREF(exp);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_FLOOR_DIVIDE)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceFloorDivide(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_MULTIPLY) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_InPlaceMultiply(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_MODULO)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceRemainder(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_TRUE_DIVIDE) {
+ PyObject *divisor = POP();
+ PyObject *dividend = TOP();
+ PyObject *quotient = PyNumber_InPlaceTrueDivide(dividend, divisor);
+ Py_DECREF(dividend);
+ Py_DECREF(divisor);
+ SET_TOP(quotient);
+ if (quotient == NULL)
+ goto error;
+ DISPATCH();
+ }
+
+ TARGET(INPLACE_FLOOR_DIVIDE) {
+ PyObject *divisor = POP();
+ PyObject *dividend = TOP();
+ PyObject *quotient = PyNumber_InPlaceFloorDivide(dividend, divisor);
+ Py_DECREF(dividend);
+ Py_DECREF(divisor);
+ SET_TOP(quotient);
+ if (quotient == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_ADD)
- w = POP();
- v = TOP();
- if (PyUnicode_CheckExact(v) &&
- PyUnicode_CheckExact(w)) {
- x = unicode_concatenate(v, w, f, next_instr);
+ TARGET(INPLACE_MODULO) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *mod = PyNumber_InPlaceRemainder(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(mod);
+ if (mod == NULL)
+ goto error;
+ DISPATCH();
+ }
+
+ TARGET(INPLACE_ADD) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *sum;
+ if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) {
+ sum = unicode_concatenate(left, right, f, next_instr);
/* unicode_concatenate consumed the ref to v */
- goto skip_decref_v;
}
else {
- x = PyNumber_InPlaceAdd(v, w);
+ sum = PyNumber_InPlaceAdd(left, right);
+ Py_DECREF(left);
}
- Py_DECREF(v);
- skip_decref_v:
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ Py_DECREF(right);
+ SET_TOP(sum);
+ if (sum == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_SUBTRACT)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceSubtract(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_SUBTRACT) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *diff = PyNumber_InPlaceSubtract(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(diff);
+ if (diff == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_LSHIFT)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceLshift(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_LSHIFT) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_InPlaceLshift(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_RSHIFT)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceRshift(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_RSHIFT) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_InPlaceRshift(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_AND)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceAnd(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_AND) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_InPlaceAnd(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_XOR)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceXor(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_XOR) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_InPlaceXor(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(INPLACE_OR)
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceOr(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(INPLACE_OR) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = PyNumber_InPlaceOr(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(STORE_SUBSCR)
- w = TOP();
- v = SECOND();
- u = THIRD();
+ TARGET(STORE_SUBSCR) {
+ PyObject *sub = TOP();
+ PyObject *container = SECOND();
+ PyObject *v = THIRD();
+ int err;
STACKADJ(-3);
/* v[w] = u */
- err = PyObject_SetItem(v, w, u);
- Py_DECREF(u);
+ err = PyObject_SetItem(container, sub, v);
Py_DECREF(v);
- Py_DECREF(w);
- if (err == 0) DISPATCH();
- break;
+ Py_DECREF(container);
+ Py_DECREF(sub);
+ if (err != 0)
+ goto error;
+ DISPATCH();
+ }
- TARGET(DELETE_SUBSCR)
- w = TOP();
- v = SECOND();
+ TARGET(DELETE_SUBSCR) {
+ PyObject *sub = TOP();
+ PyObject *container = SECOND();
+ int err;
STACKADJ(-2);
/* del v[w] */
- err = PyObject_DelItem(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- if (err == 0) DISPATCH();
- break;
+ err = PyObject_DelItem(container, sub);
+ Py_DECREF(container);
+ Py_DECREF(sub);
+ if (err != 0)
+ goto error;
+ DISPATCH();
+ }
- TARGET(PRINT_EXPR)
- v = POP();
- w = PySys_GetObject("displayhook");
- if (w == NULL) {
+ TARGET(PRINT_EXPR) {
+ _Py_IDENTIFIER(displayhook);
+ PyObject *value = POP();
+ PyObject *hook = _PySys_GetObjectId(&PyId_displayhook);
+ PyObject *res;
+ if (hook == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"lost sys.displayhook");
- err = -1;
- x = NULL;
- }
- if (err == 0) {
- x = PyTuple_Pack(1, v);
- if (x == NULL)
- err = -1;
- }
- if (err == 0) {
- w = PyEval_CallObject(w, x);
- Py_XDECREF(w);
- if (w == NULL)
- err = -1;
+ Py_DECREF(value);
+ goto error;
}
- Py_DECREF(v);
- Py_XDECREF(x);
- break;
+ res = PyObject_CallFunctionObjArgs(hook, value, NULL);
+ Py_DECREF(value);
+ if (res == NULL)
+ goto error;
+ Py_DECREF(res);
+ DISPATCH();
+ }
#ifdef CASE_TOO_BIG
default: switch (opcode) {
#endif
- TARGET(RAISE_VARARGS)
- v = w = NULL;
+ TARGET(RAISE_VARARGS) {
+ PyObject *cause = NULL, *exc = NULL;
switch (oparg) {
case 2:
- v = POP(); /* cause */
+ cause = POP(); /* cause */
case 1:
- w = POP(); /* exc */
+ exc = POP(); /* exc */
case 0: /* Fallthrough */
- why = do_raise(w, v);
+ if (do_raise(exc, cause)) {
+ why = WHY_EXCEPTION;
+ goto fast_block_end;
+ }
break;
default:
PyErr_SetString(PyExc_SystemError,
"bad RAISE_VARARGS oparg");
- why = WHY_EXCEPTION;
break;
}
- break;
-
- TARGET(STORE_LOCALS)
- x = POP();
- v = f->f_locals;
- Py_XDECREF(v);
- f->f_locals = x;
- DISPATCH();
+ goto error;
+ }
- TARGET(RETURN_VALUE)
+ TARGET(RETURN_VALUE) {
retval = POP();
why = WHY_RETURN;
goto fast_block_end;
+ }
- TARGET(YIELD_FROM)
- u = POP();
- x = TOP();
- /* send u to x */
- if (PyGen_CheckExact(x)) {
- retval = _PyGen_Send((PyGenObject *)x, u);
+ TARGET(YIELD_FROM) {
+ PyObject *v = POP();
+ PyObject *reciever = TOP();
+ int err;
+ if (PyGen_CheckExact(reciever)) {
+ retval = _PyGen_Send((PyGenObject *)reciever, v);
} else {
_Py_IDENTIFIER(send);
- if (u == Py_None)
- retval = Py_TYPE(x)->tp_iternext(x);
+ if (v == Py_None)
+ retval = Py_TYPE(reciever)->tp_iternext(reciever);
else
- retval = _PyObject_CallMethodId(x, &PyId_send, "O", u);
+ retval = _PyObject_CallMethodIdObjArgs(reciever, &PyId_send, v, NULL);
}
- Py_DECREF(u);
- if (!retval) {
+ Py_DECREF(v);
+ if (retval == NULL) {
PyObject *val;
- x = POP(); /* Remove iter from stack */
- Py_DECREF(x);
+ if (tstate->c_tracefunc != NULL
+ && PyErr_ExceptionMatches(PyExc_StopIteration))
+ call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f);
err = _PyGen_FetchStopIterationValue(&val);
- if (err < 0) {
- x = NULL;
- break;
- }
- x = val;
- PUSH(x);
- continue;
+ if (err < 0)
+ goto error;
+ Py_DECREF(reciever);
+ SET_TOP(val);
+ DISPATCH();
}
/* x remains on stack, retval is value to be yielded */
f->f_stacktop = stack_pointer;
@@ -1867,39 +1932,38 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* and repeat... */
f->f_lasti--;
goto fast_yield;
+ }
- TARGET(YIELD_VALUE)
+ TARGET(YIELD_VALUE) {
retval = POP();
f->f_stacktop = stack_pointer;
why = WHY_YIELD;
goto fast_yield;
+ }
- TARGET(POP_EXCEPT)
- {
- PyTryBlock *b = PyFrame_BlockPop(f);
- if (b->b_type != EXCEPT_HANDLER) {
- PyErr_SetString(PyExc_SystemError,
- "popped block is not an except handler");
- why = WHY_EXCEPTION;
- break;
- }
- UNWIND_EXCEPT_HANDLER(b);
+ TARGET(POP_EXCEPT) {
+ PyTryBlock *b = PyFrame_BlockPop(f);
+ if (b->b_type != EXCEPT_HANDLER) {
+ PyErr_SetString(PyExc_SystemError,
+ "popped block is not an except handler");
+ goto error;
}
+ UNWIND_EXCEPT_HANDLER(b);
DISPATCH();
+ }
- TARGET(POP_BLOCK)
- {
- PyTryBlock *b = PyFrame_BlockPop(f);
- UNWIND_BLOCK(b);
- }
+ TARGET(POP_BLOCK) {
+ PyTryBlock *b = PyFrame_BlockPop(f);
+ UNWIND_BLOCK(b);
DISPATCH();
+ }
PREDICTED(END_FINALLY);
- TARGET(END_FINALLY)
- v = POP();
- if (PyLong_Check(v)) {
- why = (enum why_code) PyLong_AS_LONG(v);
- assert(why != WHY_YIELD);
+ TARGET(END_FINALLY) {
+ PyObject *status = POP();
+ if (PyLong_Check(status)) {
+ why = (enum why_code) PyLong_AS_LONG(status);
+ assert(why != WHY_YIELD && why != WHY_EXCEPTION);
if (why == WHY_RETURN ||
why == WHY_CONTINUE)
retval = POP();
@@ -1912,248 +1976,280 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
assert(b->b_type == EXCEPT_HANDLER);
UNWIND_EXCEPT_HANDLER(b);
why = WHY_NOT;
+ Py_DECREF(status);
+ DISPATCH();
}
+ Py_DECREF(status);
+ goto fast_block_end;
}
- else if (PyExceptionClass_Check(v)) {
- w = POP();
- u = POP();
- PyErr_Restore(v, w, u);
- why = WHY_RERAISE;
- break;
+ else if (PyExceptionClass_Check(status)) {
+ PyObject *exc = POP();
+ PyObject *tb = POP();
+ PyErr_Restore(status, exc, tb);
+ why = WHY_EXCEPTION;
+ goto fast_block_end;
}
- else if (v != Py_None) {
+ else if (status != Py_None) {
PyErr_SetString(PyExc_SystemError,
"'finally' pops bad exception");
- why = WHY_EXCEPTION;
+ Py_DECREF(status);
+ goto error;
}
- Py_DECREF(v);
- break;
+ Py_DECREF(status);
+ DISPATCH();
+ }
- TARGET(LOAD_BUILD_CLASS)
- {
+ TARGET(LOAD_BUILD_CLASS) {
_Py_IDENTIFIER(__build_class__);
+ PyObject *bc;
if (PyDict_CheckExact(f->f_builtins)) {
- x = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__);
- if (x == NULL) {
+ bc = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__);
+ if (bc == NULL) {
PyErr_SetString(PyExc_NameError,
"__build_class__ not found");
- break;
+ goto error;
}
- Py_INCREF(x);
+ Py_INCREF(bc);
}
else {
PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__);
if (build_class_str == NULL)
break;
- x = PyObject_GetItem(f->f_builtins, build_class_str);
- if (x == NULL) {
+ bc = PyObject_GetItem(f->f_builtins, build_class_str);
+ if (bc == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyError))
PyErr_SetString(PyExc_NameError,
"__build_class__ not found");
- break;
+ goto error;
}
}
- PUSH(x);
- break;
+ PUSH(bc);
+ DISPATCH();
}
- TARGET(STORE_NAME)
- w = GETITEM(names, oparg);
- v = POP();
- if ((x = f->f_locals) != NULL) {
- if (PyDict_CheckExact(x))
- err = PyDict_SetItem(x, w, v);
- else
- err = PyObject_SetItem(x, w, v);
+ TARGET(STORE_NAME) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *v = POP();
+ PyObject *ns = f->f_locals;
+ int err;
+ if (ns == NULL) {
+ PyErr_Format(PyExc_SystemError,
+ "no locals found when storing %R", name);
Py_DECREF(v);
- if (err == 0) DISPATCH();
- break;
+ goto error;
}
- PyErr_Format(PyExc_SystemError,
- "no locals found when storing %R", w);
- break;
+ if (PyDict_CheckExact(ns))
+ err = PyDict_SetItem(ns, name, v);
+ else
+ err = PyObject_SetItem(ns, name, v);
+ Py_DECREF(v);
+ if (err != 0)
+ goto error;
+ DISPATCH();
+ }
- TARGET(DELETE_NAME)
- w = GETITEM(names, oparg);
- if ((x = f->f_locals) != NULL) {
- if ((err = PyObject_DelItem(x, w)) != 0)
- format_exc_check_arg(PyExc_NameError,
- NAME_ERROR_MSG,
- w);
- break;
+ TARGET(DELETE_NAME) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *ns = f->f_locals;
+ int err;
+ if (ns == NULL) {
+ PyErr_Format(PyExc_SystemError,
+ "no locals when deleting %R", name);
+ goto error;
}
- PyErr_Format(PyExc_SystemError,
- "no locals when deleting %R", w);
- break;
+ err = PyObject_DelItem(ns, name);
+ if (err != 0) {
+ format_exc_check_arg(PyExc_NameError,
+ NAME_ERROR_MSG,
+ name);
+ goto error;
+ }
+ DISPATCH();
+ }
PREDICTED_WITH_ARG(UNPACK_SEQUENCE);
- TARGET(UNPACK_SEQUENCE)
- v = POP();
- if (PyTuple_CheckExact(v) &&
- PyTuple_GET_SIZE(v) == oparg) {
- PyObject **items = \
- ((PyTupleObject *)v)->ob_item;
+ TARGET(UNPACK_SEQUENCE) {
+ PyObject *seq = POP(), *item, **items;
+ if (PyTuple_CheckExact(seq) &&
+ PyTuple_GET_SIZE(seq) == oparg) {
+ items = ((PyTupleObject *)seq)->ob_item;
while (oparg--) {
- w = items[oparg];
- Py_INCREF(w);
- PUSH(w);
+ item = items[oparg];
+ Py_INCREF(item);
+ PUSH(item);
}
- Py_DECREF(v);
- DISPATCH();
- } else if (PyList_CheckExact(v) &&
- PyList_GET_SIZE(v) == oparg) {
- PyObject **items = \
- ((PyListObject *)v)->ob_item;
+ } else if (PyList_CheckExact(seq) &&
+ PyList_GET_SIZE(seq) == oparg) {
+ items = ((PyListObject *)seq)->ob_item;
while (oparg--) {
- w = items[oparg];
- Py_INCREF(w);
- PUSH(w);
+ item = items[oparg];
+ Py_INCREF(item);
+ PUSH(item);
}
- } else if (unpack_iterable(v, oparg, -1,
+ } else if (unpack_iterable(seq, oparg, -1,
stack_pointer + oparg)) {
STACKADJ(oparg);
} else {
/* unpack_iterable() raised an exception */
- why = WHY_EXCEPTION;
+ Py_DECREF(seq);
+ goto error;
}
- Py_DECREF(v);
- break;
+ Py_DECREF(seq);
+ DISPATCH();
+ }
- TARGET(UNPACK_EX)
- {
+ TARGET(UNPACK_EX) {
int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8);
- v = POP();
+ PyObject *seq = POP();
- if (unpack_iterable(v, oparg & 0xFF, oparg >> 8,
+ if (unpack_iterable(seq, oparg & 0xFF, oparg >> 8,
stack_pointer + totalargs)) {
stack_pointer += totalargs;
} else {
- why = WHY_EXCEPTION;
+ Py_DECREF(seq);
+ goto error;
}
- Py_DECREF(v);
- break;
+ Py_DECREF(seq);
+ DISPATCH();
}
- TARGET(STORE_ATTR)
- w = GETITEM(names, oparg);
- v = TOP();
- u = SECOND();
+ TARGET(STORE_ATTR) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *owner = TOP();
+ PyObject *v = SECOND();
+ int err;
STACKADJ(-2);
- err = PyObject_SetAttr(v, w, u); /* v.w = u */
+ err = PyObject_SetAttr(owner, name, v);
Py_DECREF(v);
- Py_DECREF(u);
- if (err == 0) DISPATCH();
- break;
+ Py_DECREF(owner);
+ if (err != 0)
+ goto error;
+ DISPATCH();
+ }
- TARGET(DELETE_ATTR)
- w = GETITEM(names, oparg);
- v = POP();
- err = PyObject_SetAttr(v, w, (PyObject *)NULL);
- /* del v.w */
- Py_DECREF(v);
- break;
+ TARGET(DELETE_ATTR) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *owner = POP();
+ int err;
+ err = PyObject_SetAttr(owner, name, (PyObject *)NULL);
+ Py_DECREF(owner);
+ if (err != 0)
+ goto error;
+ DISPATCH();
+ }
- TARGET(STORE_GLOBAL)
- w = GETITEM(names, oparg);
- v = POP();
- err = PyDict_SetItem(f->f_globals, w, v);
+ TARGET(STORE_GLOBAL) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *v = POP();
+ int err;
+ err = PyDict_SetItem(f->f_globals, name, v);
Py_DECREF(v);
- if (err == 0) DISPATCH();
- break;
+ if (err != 0)
+ goto error;
+ DISPATCH();
+ }
- TARGET(DELETE_GLOBAL)
- w = GETITEM(names, oparg);
- if ((err = PyDict_DelItem(f->f_globals, w)) != 0)
+ TARGET(DELETE_GLOBAL) {
+ PyObject *name = GETITEM(names, oparg);
+ int err;
+ err = PyDict_DelItem(f->f_globals, name);
+ if (err != 0) {
format_exc_check_arg(
- PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w);
- break;
+ PyExc_NameError, NAME_ERROR_MSG, name);
+ goto error;
+ }
+ DISPATCH();
+ }
- TARGET(LOAD_NAME)
- w = GETITEM(names, oparg);
- if ((v = f->f_locals) == NULL) {
+ TARGET(LOAD_NAME) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *locals = f->f_locals;
+ PyObject *v;
+ if (locals == NULL) {
PyErr_Format(PyExc_SystemError,
- "no locals when loading %R", w);
- why = WHY_EXCEPTION;
- break;
+ "no locals when loading %R", name);
+ goto error;
}
- if (PyDict_CheckExact(v)) {
- x = PyDict_GetItem(v, w);
- Py_XINCREF(x);
+ if (PyDict_CheckExact(locals)) {
+ v = PyDict_GetItem(locals, name);
+ Py_XINCREF(v);
}
else {
- x = PyObject_GetItem(v, w);
- if (x == NULL && _PyErr_OCCURRED()) {
- if (!PyErr_ExceptionMatches(
- PyExc_KeyError))
- break;
+ v = PyObject_GetItem(locals, name);
+ if (v == NULL && _PyErr_OCCURRED()) {
+ if (!PyErr_ExceptionMatches(PyExc_KeyError))
+ goto error;
PyErr_Clear();
}
}
- if (x == NULL) {
- x = PyDict_GetItem(f->f_globals, w);
- Py_XINCREF(x);
- if (x == NULL) {
+ if (v == NULL) {
+ v = PyDict_GetItem(f->f_globals, name);
+ Py_XINCREF(v);
+ if (v == NULL) {
if (PyDict_CheckExact(f->f_builtins)) {
- x = PyDict_GetItem(f->f_builtins, w);
- if (x == NULL) {
+ v = PyDict_GetItem(f->f_builtins, name);
+ if (v == NULL) {
format_exc_check_arg(
PyExc_NameError,
- NAME_ERROR_MSG, w);
- break;
+ NAME_ERROR_MSG, name);
+ goto error;
}
- Py_INCREF(x);
+ Py_INCREF(v);
}
else {
- x = PyObject_GetItem(f->f_builtins, w);
- if (x == NULL) {
+ v = PyObject_GetItem(f->f_builtins, name);
+ if (v == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyError))
format_exc_check_arg(
PyExc_NameError,
- NAME_ERROR_MSG, w);
- break;
+ NAME_ERROR_MSG, name);
+ goto error;
}
}
}
}
- PUSH(x);
+ PUSH(v);
DISPATCH();
+ }
- TARGET(LOAD_GLOBAL)
- w = GETITEM(names, oparg);
+ TARGET(LOAD_GLOBAL) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *v;
if (PyDict_CheckExact(f->f_globals)
&& PyDict_CheckExact(f->f_builtins)) {
- x = _PyDict_LoadGlobal((PyDictObject *)f->f_globals,
+ v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals,
(PyDictObject *)f->f_builtins,
- w);
- if (x == NULL) {
+ name);
+ if (v == NULL) {
if (!_PyErr_OCCURRED())
format_exc_check_arg(PyExc_NameError,
- GLOBAL_NAME_ERROR_MSG, w);
- break;
+ NAME_ERROR_MSG, name);
+ goto error;
}
- Py_INCREF(x);
+ Py_INCREF(v);
}
else {
/* Slow-path if globals or builtins is not a dict */
- x = PyObject_GetItem(f->f_globals, w);
- if (x == NULL) {
- x = PyObject_GetItem(f->f_builtins, w);
- if (x == NULL) {
+ v = PyObject_GetItem(f->f_globals, name);
+ if (v == NULL) {
+ v = PyObject_GetItem(f->f_builtins, name);
+ if (v == NULL) {
if (PyErr_ExceptionMatches(PyExc_KeyError))
format_exc_check_arg(
PyExc_NameError,
- GLOBAL_NAME_ERROR_MSG, w);
- break;
+ NAME_ERROR_MSG, name);
+ goto error;
}
}
}
- PUSH(x);
+ PUSH(v);
DISPATCH();
+ }
- TARGET(DELETE_FAST)
- x = GETLOCAL(oparg);
- if (x != NULL) {
+ TARGET(DELETE_FAST) {
+ PyObject *v = GETLOCAL(oparg);
+ if (v != NULL) {
SETLOCAL(oparg, NULL);
DISPATCH();
}
@@ -2162,252 +2258,312 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(co->co_varnames, oparg)
);
- break;
+ goto error;
+ }
- TARGET(DELETE_DEREF)
- x = freevars[oparg];
- if (PyCell_GET(x) != NULL) {
- PyCell_Set(x, NULL);
+ TARGET(DELETE_DEREF) {
+ PyObject *cell = freevars[oparg];
+ if (PyCell_GET(cell) != NULL) {
+ PyCell_Set(cell, NULL);
DISPATCH();
}
- err = -1;
format_exc_unbound(co, oparg);
- break;
+ goto error;
+ }
- TARGET(LOAD_CLOSURE)
- x = freevars[oparg];
- Py_INCREF(x);
- PUSH(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(LOAD_CLOSURE) {
+ PyObject *cell = freevars[oparg];
+ Py_INCREF(cell);
+ PUSH(cell);
+ DISPATCH();
+ }
- TARGET(LOAD_DEREF)
- x = freevars[oparg];
- w = PyCell_Get(x);
- if (w != NULL) {
- PUSH(w);
- DISPATCH();
+ TARGET(LOAD_CLASSDEREF) {
+ PyObject *name, *value, *locals = f->f_locals;
+ Py_ssize_t idx;
+ assert(locals);
+ assert(oparg >= PyTuple_GET_SIZE(co->co_cellvars));
+ idx = oparg - PyTuple_GET_SIZE(co->co_cellvars);
+ assert(idx >= 0 && idx < PyTuple_GET_SIZE(co->co_freevars));
+ name = PyTuple_GET_ITEM(co->co_freevars, idx);
+ if (PyDict_CheckExact(locals)) {
+ value = PyDict_GetItem(locals, name);
+ Py_XINCREF(value);
}
- err = -1;
- format_exc_unbound(co, oparg);
- break;
+ else {
+ value = PyObject_GetItem(locals, name);
+ if (value == NULL && PyErr_Occurred()) {
+ if (!PyErr_ExceptionMatches(PyExc_KeyError))
+ goto error;
+ PyErr_Clear();
+ }
+ }
+ if (!value) {
+ PyObject *cell = freevars[oparg];
+ value = PyCell_GET(cell);
+ if (value == NULL) {
+ format_exc_unbound(co, oparg);
+ goto error;
+ }
+ Py_INCREF(value);
+ }
+ PUSH(value);
+ DISPATCH();
+ }
- TARGET(STORE_DEREF)
- w = POP();
- x = freevars[oparg];
- PyCell_Set(x, w);
- Py_DECREF(w);
+ TARGET(LOAD_DEREF) {
+ PyObject *cell = freevars[oparg];
+ PyObject *value = PyCell_GET(cell);
+ if (value == NULL) {
+ format_exc_unbound(co, oparg);
+ goto error;
+ }
+ Py_INCREF(value);
+ PUSH(value);
DISPATCH();
+ }
- TARGET(BUILD_TUPLE)
- x = PyTuple_New(oparg);
- if (x != NULL) {
- for (; --oparg >= 0;) {
- w = POP();
- PyTuple_SET_ITEM(x, oparg, w);
- }
- PUSH(x);
- DISPATCH();
+ TARGET(STORE_DEREF) {
+ PyObject *v = POP();
+ PyObject *cell = freevars[oparg];
+ PyCell_Set(cell, v);
+ Py_DECREF(v);
+ DISPATCH();
+ }
+
+ TARGET(BUILD_TUPLE) {
+ PyObject *tup = PyTuple_New(oparg);
+ if (tup == NULL)
+ goto error;
+ while (--oparg >= 0) {
+ PyObject *item = POP();
+ PyTuple_SET_ITEM(tup, oparg, item);
}
- break;
+ PUSH(tup);
+ DISPATCH();
+ }
- TARGET(BUILD_LIST)
- x = PyList_New(oparg);
- if (x != NULL) {
- for (; --oparg >= 0;) {
- w = POP();
- PyList_SET_ITEM(x, oparg, w);
- }
- PUSH(x);
- DISPATCH();
+ TARGET(BUILD_LIST) {
+ PyObject *list = PyList_New(oparg);
+ if (list == NULL)
+ goto error;
+ while (--oparg >= 0) {
+ PyObject *item = POP();
+ PyList_SET_ITEM(list, oparg, item);
}
- break;
+ PUSH(list);
+ DISPATCH();
+ }
- TARGET(BUILD_SET)
- x = PySet_New(NULL);
- if (x != NULL) {
- for (; --oparg >= 0;) {
- w = POP();
- if (err == 0)
- err = PySet_Add(x, w);
- Py_DECREF(w);
- }
- if (err != 0) {
- Py_DECREF(x);
- break;
- }
- PUSH(x);
- DISPATCH();
+ TARGET(BUILD_SET) {
+ PyObject *set = PySet_New(NULL);
+ int err = 0;
+ if (set == NULL)
+ goto error;
+ while (--oparg >= 0) {
+ PyObject *item = POP();
+ if (err == 0)
+ err = PySet_Add(set, item);
+ Py_DECREF(item);
}
- break;
+ if (err != 0) {
+ Py_DECREF(set);
+ goto error;
+ }
+ PUSH(set);
+ DISPATCH();
+ }
- TARGET(BUILD_MAP)
- x = _PyDict_NewPresized((Py_ssize_t)oparg);
- PUSH(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(BUILD_MAP) {
+ PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg);
+ if (map == NULL)
+ goto error;
+ PUSH(map);
+ DISPATCH();
+ }
- TARGET(STORE_MAP)
- w = TOP(); /* key */
- u = SECOND(); /* value */
- v = THIRD(); /* dict */
+ TARGET(STORE_MAP) {
+ PyObject *key = TOP();
+ PyObject *value = SECOND();
+ PyObject *map = THIRD();
+ int err;
STACKADJ(-2);
- assert (PyDict_CheckExact(v));
- err = PyDict_SetItem(v, w, u); /* v[w] = u */
- Py_DECREF(u);
- Py_DECREF(w);
- if (err == 0) DISPATCH();
- break;
+ assert(PyDict_CheckExact(map));
+ err = PyDict_SetItem(map, key, value);
+ Py_DECREF(value);
+ Py_DECREF(key);
+ if (err != 0)
+ goto error;
+ DISPATCH();
+ }
- TARGET(MAP_ADD)
- w = TOP(); /* key */
- u = SECOND(); /* value */
+ TARGET(MAP_ADD) {
+ PyObject *key = TOP();
+ PyObject *value = SECOND();
+ PyObject *map;
+ int err;
STACKADJ(-2);
- v = stack_pointer[-oparg]; /* dict */
- assert (PyDict_CheckExact(v));
- err = PyDict_SetItem(v, w, u); /* v[w] = u */
- Py_DECREF(u);
- Py_DECREF(w);
- if (err == 0) {
- PREDICT(JUMP_ABSOLUTE);
- DISPATCH();
- }
- break;
+ map = stack_pointer[-oparg]; /* dict */
+ assert(PyDict_CheckExact(map));
+ err = PyDict_SetItem(map, key, value); /* v[w] = u */
+ Py_DECREF(value);
+ Py_DECREF(key);
+ if (err != 0)
+ goto error;
+ PREDICT(JUMP_ABSOLUTE);
+ DISPATCH();
+ }
- TARGET(LOAD_ATTR)
- w = GETITEM(names, oparg);
- v = TOP();
- x = PyObject_GetAttr(v, w);
- Py_DECREF(v);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ TARGET(LOAD_ATTR) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *owner = TOP();
+ PyObject *res = PyObject_GetAttr(owner, name);
+ Py_DECREF(owner);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(COMPARE_OP)
- w = POP();
- v = TOP();
- x = cmp_outcome(oparg, v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x == NULL) break;
+ TARGET(COMPARE_OP) {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ PyObject *res = cmp_outcome(oparg, left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
PREDICT(POP_JUMP_IF_FALSE);
PREDICT(POP_JUMP_IF_TRUE);
DISPATCH();
+ }
- TARGET(IMPORT_NAME)
- {
+ TARGET(IMPORT_NAME) {
_Py_IDENTIFIER(__import__);
- w = GETITEM(names, oparg);
- x = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
- if (x == NULL) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *func = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
+ PyObject *from, *level, *args, *res;
+ if (func == NULL) {
PyErr_SetString(PyExc_ImportError,
"__import__ not found");
- break;
+ goto error;
}
- Py_INCREF(x);
- v = POP();
- u = TOP();
- if (PyLong_AsLong(u) != -1 || PyErr_Occurred())
- w = PyTuple_Pack(5,
- w,
+ Py_INCREF(func);
+ from = POP();
+ level = TOP();
+ if (PyLong_AsLong(level) != -1 || PyErr_Occurred())
+ args = PyTuple_Pack(5,
+ name,
f->f_globals,
f->f_locals == NULL ?
Py_None : f->f_locals,
- v,
- u);
+ from,
+ level);
else
- w = PyTuple_Pack(4,
- w,
+ args = PyTuple_Pack(4,
+ name,
f->f_globals,
f->f_locals == NULL ?
Py_None : f->f_locals,
- v);
- Py_DECREF(v);
- Py_DECREF(u);
- if (w == NULL) {
- u = POP();
- Py_DECREF(x);
- x = NULL;
- break;
+ from);
+ Py_DECREF(level);
+ Py_DECREF(from);
+ if (args == NULL) {
+ Py_DECREF(func);
+ STACKADJ(-1);
+ goto error;
}
READ_TIMESTAMP(intr0);
- v = x;
- x = PyEval_CallObject(v, w);
- Py_DECREF(v);
+ res = PyEval_CallObject(func, args);
READ_TIMESTAMP(intr1);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ Py_DECREF(args);
+ Py_DECREF(func);
+ SET_TOP(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
}
- TARGET(IMPORT_STAR)
- v = POP();
- PyFrame_FastToLocals(f);
- if ((x = f->f_locals) == NULL) {
+ TARGET(IMPORT_STAR) {
+ PyObject *from = POP(), *locals;
+ int err;
+ if (PyFrame_FastToLocalsWithError(f) < 0)
+ goto error;
+
+ locals = f->f_locals;
+ if (locals == NULL) {
PyErr_SetString(PyExc_SystemError,
"no locals found during 'import *'");
- break;
+ goto error;
}
READ_TIMESTAMP(intr0);
- err = import_all_from(x, v);
+ err = import_all_from(locals, from);
READ_TIMESTAMP(intr1);
PyFrame_LocalsToFast(f, 0);
- Py_DECREF(v);
- if (err == 0) DISPATCH();
- break;
+ Py_DECREF(from);
+ if (err != 0)
+ goto error;
+ DISPATCH();
+ }
- TARGET(IMPORT_FROM)
- w = GETITEM(names, oparg);
- v = TOP();
+ TARGET(IMPORT_FROM) {
+ PyObject *name = GETITEM(names, oparg);
+ PyObject *from = TOP();
+ PyObject *res;
READ_TIMESTAMP(intr0);
- x = import_from(v, w);
+ res = import_from(from, name);
READ_TIMESTAMP(intr1);
- PUSH(x);
- if (x != NULL) DISPATCH();
- break;
+ PUSH(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(JUMP_FORWARD)
+ TARGET(JUMP_FORWARD) {
JUMPBY(oparg);
FAST_DISPATCH();
+ }
PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);
- TARGET(POP_JUMP_IF_FALSE)
- w = POP();
- if (w == Py_True) {
- Py_DECREF(w);
+ TARGET(POP_JUMP_IF_FALSE) {
+ PyObject *cond = POP();
+ int err;
+ if (cond == Py_True) {
+ Py_DECREF(cond);
FAST_DISPATCH();
}
- if (w == Py_False) {
- Py_DECREF(w);
+ if (cond == Py_False) {
+ Py_DECREF(cond);
JUMPTO(oparg);
FAST_DISPATCH();
}
- err = PyObject_IsTrue(w);
- Py_DECREF(w);
+ err = PyObject_IsTrue(cond);
+ Py_DECREF(cond);
if (err > 0)
err = 0;
else if (err == 0)
JUMPTO(oparg);
else
- break;
+ goto error;
DISPATCH();
+ }
PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
- TARGET(POP_JUMP_IF_TRUE)
- w = POP();
- if (w == Py_False) {
- Py_DECREF(w);
+ TARGET(POP_JUMP_IF_TRUE) {
+ PyObject *cond = POP();
+ int err;
+ if (cond == Py_False) {
+ Py_DECREF(cond);
FAST_DISPATCH();
}
- if (w == Py_True) {
- Py_DECREF(w);
+ if (cond == Py_True) {
+ Py_DECREF(cond);
JUMPTO(oparg);
FAST_DISPATCH();
}
- err = PyObject_IsTrue(w);
- Py_DECREF(w);
+ err = PyObject_IsTrue(cond);
+ Py_DECREF(cond);
if (err > 0) {
err = 0;
JUMPTO(oparg);
@@ -2415,58 +2571,63 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
else if (err == 0)
;
else
- break;
+ goto error;
DISPATCH();
+ }
- TARGET(JUMP_IF_FALSE_OR_POP)
- w = TOP();
- if (w == Py_True) {
+ TARGET(JUMP_IF_FALSE_OR_POP) {
+ PyObject *cond = TOP();
+ int err;
+ if (cond == Py_True) {
STACKADJ(-1);
- Py_DECREF(w);
+ Py_DECREF(cond);
FAST_DISPATCH();
}
- if (w == Py_False) {
+ if (cond == Py_False) {
JUMPTO(oparg);
FAST_DISPATCH();
}
- err = PyObject_IsTrue(w);
+ err = PyObject_IsTrue(cond);
if (err > 0) {
STACKADJ(-1);
- Py_DECREF(w);
+ Py_DECREF(cond);
err = 0;
}
else if (err == 0)
JUMPTO(oparg);
else
- break;
+ goto error;
DISPATCH();
+ }
- TARGET(JUMP_IF_TRUE_OR_POP)
- w = TOP();
- if (w == Py_False) {
+ TARGET(JUMP_IF_TRUE_OR_POP) {
+ PyObject *cond = TOP();
+ int err;
+ if (cond == Py_False) {
STACKADJ(-1);
- Py_DECREF(w);
+ Py_DECREF(cond);
FAST_DISPATCH();
}
- if (w == Py_True) {
+ if (cond == Py_True) {
JUMPTO(oparg);
FAST_DISPATCH();
}
- err = PyObject_IsTrue(w);
+ err = PyObject_IsTrue(cond);
if (err > 0) {
err = 0;
JUMPTO(oparg);
}
else if (err == 0) {
STACKADJ(-1);
- Py_DECREF(w);
+ Py_DECREF(cond);
}
else
- break;
+ goto error;
DISPATCH();
+ }
PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
- TARGET(JUMP_ABSOLUTE)
+ TARGET(JUMP_ABSOLUTE) {
JUMPTO(oparg);
#if FAST_LOOPS
/* Enabling this path speeds-up all while and for-loops by bypassing
@@ -2480,60 +2641,62 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
#else
DISPATCH();
#endif
+ }
- TARGET(GET_ITER)
+ TARGET(GET_ITER) {
/* before: [obj]; after [getiter(obj)] */
- v = TOP();
- x = PyObject_GetIter(v);
- Py_DECREF(v);
- if (x != NULL) {
- SET_TOP(x);
- PREDICT(FOR_ITER);
- DISPATCH();
- }
- STACKADJ(-1);
- break;
+ PyObject *iterable = TOP();
+ PyObject *iter = PyObject_GetIter(iterable);
+ Py_DECREF(iterable);
+ SET_TOP(iter);
+ if (iter == NULL)
+ goto error;
+ PREDICT(FOR_ITER);
+ DISPATCH();
+ }
PREDICTED_WITH_ARG(FOR_ITER);
- TARGET(FOR_ITER)
+ TARGET(FOR_ITER) {
/* before: [iter]; after: [iter, iter()] *or* [] */
- v = TOP();
- x = (*v->ob_type->tp_iternext)(v);
- if (x != NULL) {
- PUSH(x);
+ PyObject *iter = TOP();
+ PyObject *next = (*iter->ob_type->tp_iternext)(iter);
+ if (next != NULL) {
+ PUSH(next);
PREDICT(STORE_FAST);
PREDICT(UNPACK_SEQUENCE);
DISPATCH();
}
if (PyErr_Occurred()) {
- if (!PyErr_ExceptionMatches(
- PyExc_StopIteration))
- break;
+ if (!PyErr_ExceptionMatches(PyExc_StopIteration))
+ goto error;
+ else if (tstate->c_tracefunc != NULL)
+ call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f);
PyErr_Clear();
}
/* iterator ended normally */
- x = v = POP();
- Py_DECREF(v);
+ STACKADJ(-1);
+ Py_DECREF(iter);
JUMPBY(oparg);
DISPATCH();
+ }
- TARGET(BREAK_LOOP)
+ TARGET(BREAK_LOOP) {
why = WHY_BREAK;
goto fast_block_end;
+ }
- TARGET(CONTINUE_LOOP)
+ TARGET(CONTINUE_LOOP) {
retval = PyLong_FromLong(oparg);
- if (!retval) {
- x = NULL;
- break;
- }
+ if (retval == NULL)
+ goto error;
why = WHY_CONTINUE;
goto fast_block_end;
+ }
TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally)
TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally)
TARGET(SETUP_FINALLY)
- _setup_finally:
+ _setup_finally: {
/* NOTE: If you add any new block-setup opcodes that
are not try/except/finally handlers, you may need
to update the PyGen_NeedsFinalizing() function.
@@ -2542,37 +2705,35 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg,
STACK_LEVEL());
DISPATCH();
+ }
- TARGET(SETUP_WITH)
- {
+ TARGET(SETUP_WITH) {
_Py_IDENTIFIER(__exit__);
_Py_IDENTIFIER(__enter__);
- w = TOP();
- x = special_lookup(w, &PyId___exit__);
- if (!x)
- break;
- SET_TOP(x);
- u = special_lookup(w, &PyId___enter__);
- Py_DECREF(w);
- if (!u) {
- x = NULL;
- break;
- }
- x = PyObject_CallFunctionObjArgs(u, NULL);
- Py_DECREF(u);
- if (!x)
- break;
+ PyObject *mgr = TOP();
+ PyObject *exit = special_lookup(mgr, &PyId___exit__), *enter;
+ PyObject *res;
+ if (exit == NULL)
+ goto error;
+ SET_TOP(exit);
+ enter = special_lookup(mgr, &PyId___enter__);
+ Py_DECREF(mgr);
+ if (enter == NULL)
+ goto error;
+ res = PyObject_CallFunctionObjArgs(enter, NULL);
+ Py_DECREF(enter);
+ if (res == NULL)
+ goto error;
/* Setup the finally block before pushing the result
of __enter__ on the stack. */
PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg,
STACK_LEVEL());
- PUSH(x);
+ PUSH(res);
DISPATCH();
}
- TARGET(WITH_CLEANUP)
- {
+ TARGET(WITH_CLEANUP) {
/* At the top of the stack are 1-6 values indicating
how/why we entered the finally clause:
- TOP = None
@@ -2599,42 +2760,42 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
*/
PyObject *exit_func;
- u = TOP();
- if (u == Py_None) {
+ PyObject *exc = TOP(), *val = Py_None, *tb = Py_None, *res;
+ int err;
+ if (exc == Py_None) {
(void)POP();
exit_func = TOP();
- SET_TOP(u);
- v = w = Py_None;
+ SET_TOP(exc);
}
- else if (PyLong_Check(u)) {
- (void)POP();
- switch(PyLong_AsLong(u)) {
+ else if (PyLong_Check(exc)) {
+ STACKADJ(-1);
+ switch (PyLong_AsLong(exc)) {
case WHY_RETURN:
case WHY_CONTINUE:
/* Retval in TOP. */
exit_func = SECOND();
SET_SECOND(TOP());
- SET_TOP(u);
+ SET_TOP(exc);
break;
default:
exit_func = TOP();
- SET_TOP(u);
+ SET_TOP(exc);
break;
}
- u = v = w = Py_None;
+ exc = Py_None;
}
else {
- PyObject *tp, *exc, *tb;
+ PyObject *tp2, *exc2, *tb2;
PyTryBlock *block;
- v = SECOND();
- w = THIRD();
- tp = FOURTH();
- exc = PEEK(5);
- tb = PEEK(6);
+ val = SECOND();
+ tb = THIRD();
+ tp2 = FOURTH();
+ exc2 = PEEK(5);
+ tb2 = PEEK(6);
exit_func = PEEK(7);
- SET_VALUE(7, tb);
- SET_VALUE(6, exc);
- SET_VALUE(5, tp);
+ SET_VALUE(7, tb2);
+ SET_VALUE(6, exc2);
+ SET_VALUE(5, tp2);
/* UNWIND_EXCEPT_HANDLER will pop this off. */
SET_FOURTH(NULL);
/* We just shifted the stack down, so we have
@@ -2645,56 +2806,53 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
block->b_level--;
}
/* XXX Not the fastest way to call it... */
- x = PyObject_CallFunctionObjArgs(exit_func, u, v, w,
- NULL);
+ res = PyObject_CallFunctionObjArgs(exit_func, exc, val, tb, NULL);
Py_DECREF(exit_func);
- if (x == NULL)
- break; /* Go to error exit */
+ if (res == NULL)
+ goto error;
- if (u != Py_None)
- err = PyObject_IsTrue(x);
+ if (exc != Py_None)
+ err = PyObject_IsTrue(res);
else
err = 0;
- Py_DECREF(x);
+ Py_DECREF(res);
if (err < 0)
- break; /* Go to error exit */
+ goto error;
else if (err > 0) {
err = 0;
/* There was an exception and a True return */
PUSH(PyLong_FromLong((long) WHY_SILENCED));
}
PREDICT(END_FINALLY);
- break;
+ DISPATCH();
}
- TARGET(CALL_FUNCTION)
- {
- PyObject **sp;
+ TARGET(CALL_FUNCTION) {
+ PyObject **sp, *res;
PCALL(PCALL_ALL);
sp = stack_pointer;
#ifdef WITH_TSC
- x = call_function(&sp, oparg, &intr0, &intr1);
+ res = call_function(&sp, oparg, &intr0, &intr1);
#else
- x = call_function(&sp, oparg);
+ res = call_function(&sp, oparg);
#endif
stack_pointer = sp;
- PUSH(x);
- if (x != NULL)
- DISPATCH();
- break;
+ PUSH(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
}
TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw)
TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw)
TARGET(CALL_FUNCTION_VAR_KW)
- _call_function_var_kw:
- {
+ _call_function_var_kw: {
int na = oparg & 0xff;
int nk = (oparg>>8) & 0xff;
int flags = (opcode - CALL_FUNCTION) & 3;
int n = na + 2 * nk;
- PyObject **pfunc, *func, **sp;
+ PyObject **pfunc, *func, **sp, *res;
PCALL(PCALL_ALL);
if (flags & CALL_FLAG_VAR)
n++;
@@ -2717,137 +2875,156 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_INCREF(func);
sp = stack_pointer;
READ_TIMESTAMP(intr0);
- x = ext_do_call(func, &sp, flags, na, nk);
+ res = ext_do_call(func, &sp, flags, na, nk);
READ_TIMESTAMP(intr1);
stack_pointer = sp;
Py_DECREF(func);
while (stack_pointer > pfunc) {
- w = POP();
- Py_DECREF(w);
+ PyObject *o = POP();
+ Py_DECREF(o);
}
- PUSH(x);
- if (x != NULL)
- DISPATCH();
- break;
+ PUSH(res);
+ if (res == NULL)
+ goto error;
+ DISPATCH();
}
TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function)
TARGET(MAKE_FUNCTION)
- _make_function:
- {
+ _make_function: {
int posdefaults = oparg & 0xff;
int kwdefaults = (oparg>>8) & 0xff;
int num_annotations = (oparg >> 16) & 0x7fff;
- w = POP(); /* qualname */
- v = POP(); /* code object */
- x = PyFunction_NewWithQualName(v, f->f_globals, w);
- Py_DECREF(v);
- Py_DECREF(w);
+ PyObject *qualname = POP(); /* qualname */
+ PyObject *code = POP(); /* code object */
+ PyObject *func = PyFunction_NewWithQualName(code, f->f_globals, qualname);
+ Py_DECREF(code);
+ Py_DECREF(qualname);
+
+ if (func == NULL)
+ goto error;
- if (x != NULL && opcode == MAKE_CLOSURE) {
- v = POP();
- if (PyFunction_SetClosure(x, v) != 0) {
+ if (opcode == MAKE_CLOSURE) {
+ PyObject *closure = POP();
+ if (PyFunction_SetClosure(func, closure) != 0) {
/* Can't happen unless bytecode is corrupt. */
- why = WHY_EXCEPTION;
+ Py_DECREF(func);
+ Py_DECREF(closure);
+ goto error;
}
- Py_DECREF(v);
+ Py_DECREF(closure);
}
- if (x != NULL && num_annotations > 0) {
+ if (num_annotations > 0) {
Py_ssize_t name_ix;
- u = POP(); /* names of args with annotations */
- v = PyDict_New();
- if (v == NULL) {
- Py_DECREF(x);
- x = NULL;
- break;
+ PyObject *names = POP(); /* names of args with annotations */
+ PyObject *anns = PyDict_New();
+ if (anns == NULL) {
+ Py_DECREF(func);
+ goto error;
}
- name_ix = PyTuple_Size(u);
+ name_ix = PyTuple_Size(names);
assert(num_annotations == name_ix+1);
while (name_ix > 0) {
+ PyObject *name, *value;
+ int err;
--name_ix;
- t = PyTuple_GET_ITEM(u, name_ix);
- w = POP();
- /* XXX(nnorwitz): check for errors */
- PyDict_SetItem(v, t, w);
- Py_DECREF(w);
+ name = PyTuple_GET_ITEM(names, name_ix);
+ value = POP();
+ err = PyDict_SetItem(anns, name, value);
+ Py_DECREF(value);
+ if (err != 0) {
+ Py_DECREF(anns);
+ Py_DECREF(func);
+ goto error;
+ }
}
- if (PyFunction_SetAnnotations(x, v) != 0) {
+ if (PyFunction_SetAnnotations(func, anns) != 0) {
/* Can't happen unless
PyFunction_SetAnnotations changes. */
- why = WHY_EXCEPTION;
+ Py_DECREF(anns);
+ Py_DECREF(func);
+ goto error;
}
- Py_DECREF(v);
- Py_DECREF(u);
+ Py_DECREF(anns);
+ Py_DECREF(names);
}
/* XXX Maybe this should be a separate opcode? */
- if (x != NULL && posdefaults > 0) {
- v = PyTuple_New(posdefaults);
- if (v == NULL) {
- Py_DECREF(x);
- x = NULL;
- break;
+ if (kwdefaults > 0) {
+ PyObject *defs = PyDict_New();
+ if (defs == NULL) {
+ Py_DECREF(func);
+ goto error;
}
- while (--posdefaults >= 0) {
- w = POP();
- PyTuple_SET_ITEM(v, posdefaults, w);
+ while (--kwdefaults >= 0) {
+ PyObject *v = POP(); /* default value */
+ PyObject *key = POP(); /* kw only arg name */
+ int err = PyDict_SetItem(defs, key, v);
+ Py_DECREF(v);
+ Py_DECREF(key);
+ if (err != 0) {
+ Py_DECREF(defs);
+ Py_DECREF(func);
+ goto error;
+ }
}
- if (PyFunction_SetDefaults(x, v) != 0) {
+ if (PyFunction_SetKwDefaults(func, defs) != 0) {
/* Can't happen unless
- PyFunction_SetDefaults changes. */
- why = WHY_EXCEPTION;
+ PyFunction_SetKwDefaults changes. */
+ Py_DECREF(func);
+ Py_DECREF(defs);
+ goto error;
}
- Py_DECREF(v);
+ Py_DECREF(defs);
}
- if (x != NULL && kwdefaults > 0) {
- v = PyDict_New();
- if (v == NULL) {
- Py_DECREF(x);
- x = NULL;
- break;
- }
- while (--kwdefaults >= 0) {
- w = POP(); /* default value */
- u = POP(); /* kw only arg name */
- /* XXX(nnorwitz): check for errors */
- PyDict_SetItem(v, u, w);
- Py_DECREF(w);
- Py_DECREF(u);
+ if (posdefaults > 0) {
+ PyObject *defs = PyTuple_New(posdefaults);
+ if (defs == NULL) {
+ Py_DECREF(func);
+ goto error;
}
- if (PyFunction_SetKwDefaults(x, v) != 0) {
+ while (--posdefaults >= 0)
+ PyTuple_SET_ITEM(defs, posdefaults, POP());
+ if (PyFunction_SetDefaults(func, defs) != 0) {
/* Can't happen unless
- PyFunction_SetKwDefaults changes. */
- why = WHY_EXCEPTION;
+ PyFunction_SetDefaults changes. */
+ Py_DECREF(defs);
+ Py_DECREF(func);
+ goto error;
}
- Py_DECREF(v);
+ Py_DECREF(defs);
}
- PUSH(x);
- break;
+ PUSH(func);
+ DISPATCH();
}
- TARGET(BUILD_SLICE)
+ TARGET(BUILD_SLICE) {
+ PyObject *start, *stop, *step, *slice;
if (oparg == 3)
- w = POP();
+ step = POP();
else
- w = NULL;
- v = POP();
- u = TOP();
- x = PySlice_New(u, v, w);
- Py_DECREF(u);
- Py_DECREF(v);
- Py_XDECREF(w);
- SET_TOP(x);
- if (x != NULL) DISPATCH();
- break;
+ step = NULL;
+ stop = POP();
+ start = TOP();
+ slice = PySlice_New(start, stop, step);
+ Py_DECREF(start);
+ Py_DECREF(stop);
+ Py_XDECREF(step);
+ SET_TOP(slice);
+ if (slice == NULL)
+ goto error;
+ DISPATCH();
+ }
- TARGET(EXTENDED_ARG)
+ TARGET(EXTENDED_ARG) {
opcode = NEXTOP();
oparg = oparg<<16 | NEXTARG();
goto dispatch_opcode;
+ }
#if USE_COMPUTED_GOTOS
_unknown_opcode:
@@ -2858,8 +3035,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PyFrame_GetLineNumber(f),
opcode);
PyErr_SetString(PyExc_SystemError, "unknown opcode");
- why = WHY_EXCEPTION;
- break;
+ goto error;
#ifdef CASE_TOO_BIG
}
@@ -2867,71 +3043,36 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
} /* switch */
- on_error:
+ /* This should never be reached. Every opcode should end with DISPATCH()
+ or goto error. */
+ assert(0);
+error:
READ_TIMESTAMP(inst1);
- /* Quickly continue if no error occurred */
-
- if (why == WHY_NOT) {
- if (err == 0 && x != NULL) {
-#ifdef CHECKEXC
- /* This check is expensive! */
- if (PyErr_Occurred())
- fprintf(stderr,
- "XXX undetected error\n");
- else {
-#endif
- READ_TIMESTAMP(loop1);
- continue; /* Normal, fast path */
-#ifdef CHECKEXC
- }
-#endif
- }
- why = WHY_EXCEPTION;
- x = Py_None;
- err = 0;
- }
-
- /* Double-check exception status */
+ assert(why == WHY_NOT);
+ why = WHY_EXCEPTION;
- if (why == WHY_EXCEPTION || why == WHY_RERAISE) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_SystemError,
- "error return without exception set");
- why = WHY_EXCEPTION;
- }
- }
-#ifdef CHECKEXC
- else {
- /* This check is expensive! */
- if (PyErr_Occurred()) {
- char buf[128];
- sprintf(buf, "Stack unwind with exception "
- "set and why=%d", why);
- Py_FatalError(buf);
- }
- }
+ /* Double-check exception status. */
+#ifdef NDEBUG
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_SystemError,
+ "error return without exception set");
+#else
+ assert(PyErr_Occurred());
#endif
- /* Log traceback info if this is a real exception */
+ /* Log traceback info. */
+ PyTraceBack_Here(f);
- if (why == WHY_EXCEPTION) {
- PyTraceBack_Here(f);
+ if (tstate->c_tracefunc != NULL)
+ call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj,
+ tstate, f);
- if (tstate->c_tracefunc != NULL)
- call_exc_trace(tstate->c_tracefunc,
- tstate->c_traceobj, f);
- }
-
- /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */
-
- if (why == WHY_RERAISE)
- why = WHY_EXCEPTION;
+fast_block_end:
+ assert(why != WHY_NOT);
/* Unwind stacks if a (pseudo) exception occurred */
-
-fast_block_end:
while (why != WHY_NOT && f->f_iblock > 0) {
/* Peek at the current block. */
PyTryBlock *b = &f->f_blockstack[f->f_iblock - 1];
@@ -2978,7 +3119,10 @@ fast_block_end:
Python main loop. */
PyErr_NormalizeException(
&exc, &val, &tb);
- PyException_SetTraceback(val, tb);
+ if (tb != NULL)
+ PyException_SetTraceback(val, tb);
+ else
+ PyException_SetTraceback(val, Py_None);
Py_INCREF(exc);
tstate->exc_type = exc;
Py_INCREF(val);
@@ -3010,20 +3154,26 @@ fast_block_end:
break;
READ_TIMESTAMP(loop1);
+ assert(!PyErr_Occurred());
+
} /* main loop */
assert(why != WHY_YIELD);
/* Pop remaining stack entries. */
while (!EMPTY()) {
- v = POP();
- Py_XDECREF(v);
+ PyObject *o = POP();
+ Py_XDECREF(o);
}
if (why != WHY_RETURN)
retval = NULL;
+ assert((retval != NULL && !PyErr_Occurred())
+ || (retval == NULL && PyErr_Occurred()));
+
fast_yield:
- if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN)) {
+ if (co->co_flags & CO_GENERATOR) {
+
/* The purpose of this block is to put aside the generator's exception
state and restore that of the calling frame. If the current
exception state is from the caller, we clear the exception values
@@ -3046,26 +3196,27 @@ fast_yield:
if (tstate->use_tracing) {
if (tstate->c_tracefunc) {
if (why == WHY_RETURN || why == WHY_YIELD) {
- if (call_trace(tstate->c_tracefunc,
- tstate->c_traceobj, f,
+ if (call_trace(tstate->c_tracefunc, tstate->c_traceobj,
+ tstate, f,
PyTrace_RETURN, retval)) {
Py_CLEAR(retval);
why = WHY_EXCEPTION;
}
}
else if (why == WHY_EXCEPTION) {
- call_trace_protected(tstate->c_tracefunc,
- tstate->c_traceobj, f,
+ call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj,
+ tstate, f,
PyTrace_RETURN, NULL);
}
}
if (tstate->c_profilefunc) {
if (why == WHY_EXCEPTION)
call_trace_protected(tstate->c_profilefunc,
- tstate->c_profileobj, f,
+ tstate->c_profileobj,
+ tstate, f,
PyTrace_RETURN, NULL);
- else if (call_trace(tstate->c_profilefunc,
- tstate->c_profileobj, f,
+ else if (call_trace(tstate->c_profilefunc, tstate->c_profileobj,
+ tstate, f,
PyTrace_RETURN, retval)) {
Py_CLEAR(retval);
/* why = WHY_EXCEPTION; */
@@ -3076,6 +3227,7 @@ fast_yield:
/* pop frame */
exit_eval_frame:
Py_LeaveRecursiveCall();
+ f->f_executing = 0;
tstate->frame = f->f_back;
return retval;
@@ -3241,9 +3393,9 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
{
PyCodeObject* co = (PyCodeObject*)_co;
- register PyFrameObject *f;
- register PyObject *retval = NULL;
- register PyObject **fastlocals, **freevars;
+ PyFrameObject *f;
+ PyObject *retval = NULL;
+ PyObject **fastlocals, **freevars;
PyThreadState *tstate = PyThreadState_GET();
PyObject *x, *u;
int total_args = co->co_argcount + co->co_kwonlyargcount;
@@ -3519,7 +3671,7 @@ restore_and_clear_exc_state(PyThreadState *tstate, PyFrameObject *f)
/* Logic for the raise statement (too complicated for inlining).
This *consumes* a reference count to each of its arguments. */
-static enum why_code
+static int
do_raise(PyObject *exc, PyObject *cause)
{
PyObject *type = NULL, *value = NULL;
@@ -3534,13 +3686,13 @@ do_raise(PyObject *exc, PyObject *cause)
if (type == Py_None) {
PyErr_SetString(PyExc_RuntimeError,
"No active exception to reraise");
- return WHY_EXCEPTION;
- }
+ return 0;
+ }
Py_XINCREF(type);
Py_XINCREF(value);
Py_XINCREF(tb);
PyErr_Restore(type, value, tb);
- return WHY_RERAISE;
+ return 1;
}
/* We support the following forms of raise:
@@ -3603,13 +3755,13 @@ do_raise(PyObject *exc, PyObject *cause)
/* PyErr_SetObject incref's its arguments */
Py_XDECREF(value);
Py_XDECREF(type);
- return WHY_EXCEPTION;
+ return 0;
raise_error:
Py_XDECREF(value);
Py_XDECREF(type);
Py_XDECREF(cause);
- return WHY_EXCEPTION;
+ return 0;
}
/* Iterate v argcnt times and store the results on the stack (via decreasing
@@ -3706,40 +3858,43 @@ prtrace(PyObject *v, char *str)
#endif
static void
-call_exc_trace(Py_tracefunc func, PyObject *self, PyFrameObject *f)
+call_exc_trace(Py_tracefunc func, PyObject *self,
+ PyThreadState *tstate, PyFrameObject *f)
{
- PyObject *type, *value, *traceback, *arg;
+ PyObject *type, *value, *traceback, *orig_traceback, *arg;
int err;
- PyErr_Fetch(&type, &value, &traceback);
+ PyErr_Fetch(&type, &value, &orig_traceback);
if (value == NULL) {
value = Py_None;
Py_INCREF(value);
}
- PyErr_NormalizeException(&type, &value, &traceback);
+ PyErr_NormalizeException(&type, &value, &orig_traceback);
+ traceback = (orig_traceback != NULL) ? orig_traceback : Py_None;
arg = PyTuple_Pack(3, type, value, traceback);
if (arg == NULL) {
- PyErr_Restore(type, value, traceback);
+ PyErr_Restore(type, value, orig_traceback);
return;
}
- err = call_trace(func, self, f, PyTrace_EXCEPTION, arg);
+ err = call_trace(func, self, tstate, f, PyTrace_EXCEPTION, arg);
Py_DECREF(arg);
if (err == 0)
- PyErr_Restore(type, value, traceback);
+ PyErr_Restore(type, value, orig_traceback);
else {
Py_XDECREF(type);
Py_XDECREF(value);
- Py_XDECREF(traceback);
+ Py_XDECREF(orig_traceback);
}
}
static int
-call_trace_protected(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
+call_trace_protected(Py_tracefunc func, PyObject *obj,
+ PyThreadState *tstate, PyFrameObject *frame,
int what, PyObject *arg)
{
PyObject *type, *value, *traceback;
int err;
PyErr_Fetch(&type, &value, &traceback);
- err = call_trace(func, obj, frame, what, arg);
+ err = call_trace(func, obj, tstate, frame, what, arg);
if (err == 0)
{
PyErr_Restore(type, value, traceback);
@@ -3754,10 +3909,10 @@ call_trace_protected(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
}
static int
-call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
+call_trace(Py_tracefunc func, PyObject *obj,
+ PyThreadState *tstate, PyFrameObject *frame,
int what, PyObject *arg)
{
- register PyThreadState *tstate = frame->f_tstate;
int result;
if (tstate->tracing)
return 0;
@@ -3773,8 +3928,7 @@ call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
PyObject *
_PyEval_CallTracing(PyObject *func, PyObject *args)
{
- PyFrameObject *frame = PyEval_GetFrame();
- PyThreadState *tstate = frame->f_tstate;
+ PyThreadState *tstate = PyThreadState_GET();
int save_tracing = tstate->tracing;
int save_use_tracing = tstate->use_tracing;
PyObject *result;
@@ -3791,8 +3945,8 @@ _PyEval_CallTracing(PyObject *func, PyObject *args)
/* See Objects/lnotab_notes.txt for a description of how tracing works. */
static int
maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
- PyFrameObject *frame, int *instr_lb, int *instr_ub,
- int *instr_prev)
+ PyThreadState *tstate, PyFrameObject *frame,
+ int *instr_lb, int *instr_ub, int *instr_prev)
{
int result = 0;
int line = frame->f_lineno;
@@ -3812,7 +3966,7 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
number and call the trace function. */
if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) {
frame->f_lineno = line;
- result = call_trace(func, obj, frame, PyTrace_LINE, Py_None);
+ result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None);
}
*instr_prev = frame->f_lasti;
return result;
@@ -3868,9 +4022,15 @@ PyObject *
PyEval_GetLocals(void)
{
PyFrameObject *current_frame = PyEval_GetFrame();
- if (current_frame == NULL)
+ if (current_frame == NULL) {
+ PyErr_SetString(PyExc_SystemError, "frame does not exist");
return NULL;
- PyFrame_FastToLocals(current_frame);
+ }
+
+ if (PyFrame_FastToLocalsWithError(current_frame) < 0)
+ return NULL;
+
+ assert(current_frame->f_locals != NULL);
return current_frame->f_locals;
}
@@ -3880,8 +4040,9 @@ PyEval_GetGlobals(void)
PyFrameObject *current_frame = PyEval_GetFrame();
if (current_frame == NULL)
return NULL;
- else
- return current_frame->f_globals;
+
+ assert(current_frame->f_globals != NULL);
+ return current_frame->f_globals;
}
PyFrameObject *
@@ -3923,6 +4084,13 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
{
PyObject *result;
+#ifdef Py_DEBUG
+ /* PyEval_CallObjectWithKeywords() must not be called with an exception
+ set, because it may clear it (directly or indirectly)
+ and so the caller loses its exception */
+ assert(!PyErr_Occurred());
+#endif
+
if (arg == NULL) {
arg = PyTuple_New(0);
if (arg == NULL)
@@ -3945,6 +4113,9 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
result = PyObject_Call(func, arg, kw);
Py_DECREF(arg);
+
+ assert((result != NULL && !PyErr_Occurred())
+ || (result == NULL && PyErr_Occurred()));
return result;
}
@@ -3991,10 +4162,9 @@ err_args(PyObject *func, int flags, int nargs)
#define C_TRACE(x, call) \
if (tstate->use_tracing && tstate->c_profilefunc) { \
- if (call_trace(tstate->c_profilefunc, \
- tstate->c_profileobj, \
- tstate->frame, PyTrace_C_CALL, \
- func)) { \
+ if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, \
+ tstate, tstate->frame, \
+ PyTrace_C_CALL, func)) { \
x = NULL; \
} \
else { \
@@ -4003,14 +4173,14 @@ if (tstate->use_tracing && tstate->c_profilefunc) { \
if (x == NULL) { \
call_trace_protected(tstate->c_profilefunc, \
tstate->c_profileobj, \
- tstate->frame, PyTrace_C_EXCEPTION, \
- func); \
+ tstate, tstate->frame, \
+ PyTrace_C_EXCEPTION, func); \
/* XXX should pass (type, value, tb) */ \
} else { \
if (call_trace(tstate->c_profilefunc, \
tstate->c_profileobj, \
- tstate->frame, PyTrace_C_RETURN, \
- func)) { \
+ tstate, tstate->frame, \
+ PyTrace_C_RETURN, func)) { \
Py_DECREF(x); \
x = NULL; \
} \
@@ -4062,10 +4232,15 @@ call_function(PyObject ***pp_stack, int oparg
else {
PyObject *callargs;
callargs = load_args(pp_stack, na);
- READ_TIMESTAMP(*pintr0);
- C_TRACE(x, PyCFunction_Call(func,callargs,NULL));
- READ_TIMESTAMP(*pintr1);
- Py_XDECREF(callargs);
+ if (callargs != NULL) {
+ READ_TIMESTAMP(*pintr0);
+ C_TRACE(x, PyCFunction_Call(func,callargs,NULL));
+ READ_TIMESTAMP(*pintr1);
+ Py_XDECREF(callargs);
+ }
+ else {
+ x = NULL;
+ }
}
} else {
if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
@@ -4090,6 +4265,8 @@ call_function(PyObject ***pp_stack, int oparg
READ_TIMESTAMP(*pintr1);
Py_DECREF(func);
}
+ assert((x != NULL && !PyErr_Occurred())
+ || (x == NULL && PyErr_Occurred()));
/* Clear the stack of the function object. Also removes
the arguments in case they weren't consumed already
@@ -4100,6 +4277,9 @@ call_function(PyObject ***pp_stack, int oparg
Py_DECREF(w);
PCALL(PCALL_POP);
}
+
+ assert((x != NULL && !PyErr_Occurred())
+ || (x == NULL && PyErr_Occurred()));
return x;
}
@@ -4383,6 +4563,8 @@ ext_call_fail:
Py_XDECREF(callargs);
Py_XDECREF(kwdict);
Py_XDECREF(stararg);
+ assert((result != NULL && !PyErr_Occurred())
+ || (result == NULL && PyErr_Occurred()));
return result;
}
@@ -4421,7 +4603,7 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
"BaseException is not allowed"
static PyObject *
-cmp_outcome(int op, register PyObject *v, register PyObject *w)
+cmp_outcome(int op, PyObject *v, PyObject *w)
{
int res = 0;
switch (op) {
@@ -4479,7 +4661,7 @@ import_from(PyObject *v, PyObject *name)
x = PyObject_GetAttr(v, name);
if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyErr_Format(PyExc_ImportError, "cannot import name %S", name);
+ PyErr_Format(PyExc_ImportError, "cannot import name %R", name);
}
return x;
}