diff -r d3be5c4507b4 Makefile.pre.in --- a/Makefile.pre.in Sat Feb 06 01:08:40 2016 +0000 +++ b/Makefile.pre.in Fri Feb 05 18:40:06 2016 +0100 @@ -864,7 +864,21 @@ Objects/setobject.o: $(srcdir)/Objects/s $(OPCODETARGETS_H): $(OPCODETARGETGEN_FILES) $(OPCODETARGETGEN) $(OPCODETARGETS_H) -Python/ceval.o: $(OPCODETARGETS_H) $(srcdir)/Python/ceval_gil.h +CEVAL_DEPS = \ + $(OPCODETARGETS_H) \ + $(srcdir)/Python/ceval_build.h \ + $(srcdir)/Python/ceval_condjump.h \ + $(srcdir)/Python/ceval_ctx.h \ + $(srcdir)/Python/ceval_fast.h \ + $(srcdir)/Python/ceval_func.h \ + $(srcdir)/Python/ceval_gil.h \ + $(srcdir)/Python/ceval_iter.h \ + $(srcdir)/Python/ceval_misc.h \ + $(srcdir)/Python/ceval_module.h \ + $(srcdir)/Python/ceval_number.h \ + $(srcdir)/Python/ceval_stack.h + +Python/ceval.o: $(CEVAL_DEPS) Python/frozen.o: Python/importlib.h Python/importlib_external.h diff -r d3be5c4507b4 Python/ceval.c --- a/Python/ceval.c Sat Feb 06 01:08:40 2016 +0000 +++ b/Python/ceval.c Fri Feb 05 18:40:06 2016 +0100 @@ -1361,2074 +1361,22 @@ PyEval_EvalFrameEx(PyFrameObject *f, int x to NULL, err to nonzero, or why to anything but WHY_NOT, and that no operation that succeeds does this! */ - TARGET(NOP) - 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; - } - Py_INCREF(value); - PUSH(value); - FAST_DISPATCH(); - } - - TARGET(LOAD_CONST) { - PyObject *value = GETITEM(consts, oparg); - Py_INCREF(value); - PUSH(value); - FAST_DISPATCH(); - } - - PREDICTED_WITH_ARG(STORE_FAST); - TARGET(STORE_FAST) { - PyObject *value = POP(); - SETLOCAL(oparg, value); - FAST_DISPATCH(); - } - - TARGET(POP_TOP) { - PyObject *value = POP(); - Py_DECREF(value); - FAST_DISPATCH(); - } - - TARGET(ROT_TWO) { - PyObject *top = TOP(); - PyObject *second = SECOND(); - SET_TOP(second); - SET_SECOND(top); - FAST_DISPATCH(); - } - - 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) { - PyObject *top = TOP(); - Py_INCREF(top); - PUSH(top); - FAST_DISPATCH(); - } - - TARGET(DUP_TOP_TWO) { - PyObject *top = TOP(); - PyObject *second = SECOND(); - Py_INCREF(top); - Py_INCREF(second); - STACKADJ(2); - SET_TOP(top); - SET_SECOND(second); - FAST_DISPATCH(); - } - - 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) { - PyObject *value = TOP(); - PyObject *res = PyNumber_Negative(value); - Py_DECREF(value); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - 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); - DISPATCH(); - } - else if (err > 0) { - Py_INCREF(Py_False); - SET_TOP(Py_False); - err = 0; - DISPATCH(); - } - STACKADJ(-1); - goto error; - } - - 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) { - 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) { - 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_MATRIX_MULTIPLY) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_MatrixMultiply(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - 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) { - 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) { - 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) { - 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 */ - } - else { - sum = PyNumber_Add(left, right); - Py_DECREF(left); - } - Py_DECREF(right); - SET_TOP(sum); - if (sum == NULL) - goto error; - DISPATCH(); - } - - 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_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_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_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_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(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(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(LIST_APPEND) { - PyObject *v = POP(); - PyObject *list = PEEK(oparg); - int err; - err = PyList_Append(list, v); - Py_DECREF(v); - if (err != 0) - goto error; - PREDICT(JUMP_ABSOLUTE); - DISPATCH(); - } - - TARGET(SET_ADD) { - PyObject *v = POP(); - PyObject *set = stack_pointer[-oparg]; - int err; - err = PySet_Add(set, v); - Py_DECREF(v); - if (err != 0) - goto error; - PREDICT(JUMP_ABSOLUTE); - DISPATCH(); - } - - 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_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_MATRIX_MULTIPLY) { - PyObject *right = POP(); - PyObject *left = TOP(); - PyObject *res = PyNumber_InPlaceMatrixMultiply(left, right); - Py_DECREF(left); - Py_DECREF(right); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - 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_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 */ - } - else { - sum = PyNumber_InPlaceAdd(left, right); - Py_DECREF(left); - } - Py_DECREF(right); - SET_TOP(sum); - if (sum == NULL) - goto error; - DISPATCH(); - } - - 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) { - 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) { - 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) { - 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) { - 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) { - 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) { - PyObject *sub = TOP(); - PyObject *container = SECOND(); - PyObject *v = THIRD(); - int err; - STACKADJ(-3); - /* v[w] = u */ - err = PyObject_SetItem(container, sub, v); - Py_DECREF(v); - Py_DECREF(container); - Py_DECREF(sub); - if (err != 0) - goto error; - DISPATCH(); - } - - TARGET(DELETE_SUBSCR) { - PyObject *sub = TOP(); - PyObject *container = SECOND(); - int err; - STACKADJ(-2); - /* del v[w] */ - err = PyObject_DelItem(container, sub); - Py_DECREF(container); - Py_DECREF(sub); - if (err != 0) - goto error; - DISPATCH(); - } - - 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"); - Py_DECREF(value); - goto error; - } - res = PyObject_CallFunctionObjArgs(hook, value, NULL); - Py_DECREF(value); - if (res == NULL) - goto error; - Py_DECREF(res); - DISPATCH(); - } +#define PY_CEVAL_INTERNAL +#include "ceval_fast.h" +#include "ceval_stack.h" +#include "ceval_number.h" #ifdef CASE_TOO_BIG default: switch (opcode) { #endif - TARGET(RAISE_VARARGS) { - PyObject *cause = NULL, *exc = NULL; - switch (oparg) { - case 2: - cause = POP(); /* cause */ - case 1: - exc = POP(); /* exc */ - case 0: /* Fallthrough */ - if (do_raise(exc, cause)) { - why = WHY_EXCEPTION; - goto fast_block_end; - } - break; - default: - PyErr_SetString(PyExc_SystemError, - "bad RAISE_VARARGS oparg"); - break; - } - goto error; - } - - TARGET(RETURN_VALUE) { - retval = POP(); - why = WHY_RETURN; - goto fast_block_end; - } - - TARGET(GET_AITER) { - unaryfunc getter = NULL; - PyObject *iter = NULL; - PyObject *awaitable = NULL; - PyObject *obj = TOP(); - PyTypeObject *type = Py_TYPE(obj); - - if (type->tp_as_async != NULL) - getter = type->tp_as_async->am_aiter; - - if (getter != NULL) { - iter = (*getter)(obj); - Py_DECREF(obj); - if (iter == NULL) { - SET_TOP(NULL); - goto error; - } - } - else { - SET_TOP(NULL); - PyErr_Format( - PyExc_TypeError, - "'async for' requires an object with " - "__aiter__ method, got %.100s", - type->tp_name); - Py_DECREF(obj); - goto error; - } - - awaitable = _PyCoro_GetAwaitableIter(iter); - if (awaitable == NULL) { - SET_TOP(NULL); - PyErr_Format( - PyExc_TypeError, - "'async for' received an invalid object " - "from __aiter__: %.100s", - Py_TYPE(iter)->tp_name); - - Py_DECREF(iter); - goto error; - } else - Py_DECREF(iter); - - SET_TOP(awaitable); - DISPATCH(); - } - - TARGET(GET_ANEXT) { - unaryfunc getter = NULL; - PyObject *next_iter = NULL; - PyObject *awaitable = NULL; - PyObject *aiter = TOP(); - PyTypeObject *type = Py_TYPE(aiter); - - if (type->tp_as_async != NULL) - getter = type->tp_as_async->am_anext; - - if (getter != NULL) { - next_iter = (*getter)(aiter); - if (next_iter == NULL) { - goto error; - } - } - else { - PyErr_Format( - PyExc_TypeError, - "'async for' requires an iterator with " - "__anext__ method, got %.100s", - type->tp_name); - goto error; - } - - awaitable = _PyCoro_GetAwaitableIter(next_iter); - if (awaitable == NULL) { - PyErr_Format( - PyExc_TypeError, - "'async for' received an invalid object " - "from __anext__: %.100s", - Py_TYPE(next_iter)->tp_name); - - Py_DECREF(next_iter); - goto error; - } else - Py_DECREF(next_iter); - - PUSH(awaitable); - DISPATCH(); - } - - TARGET(GET_AWAITABLE) { - PyObject *iterable = TOP(); - PyObject *iter = _PyCoro_GetAwaitableIter(iterable); - - Py_DECREF(iterable); - - SET_TOP(iter); /* Even if it's NULL */ - - if (iter == NULL) { - goto error; - } - - DISPATCH(); - } - - TARGET(YIELD_FROM) { - PyObject *v = POP(); - PyObject *reciever = TOP(); - int err; - if (PyGen_CheckExact(reciever) || PyCoro_CheckExact(reciever)) { - retval = _PyGen_Send((PyGenObject *)reciever, v); - } else { - _Py_IDENTIFIER(send); - if (v == Py_None) - retval = Py_TYPE(reciever)->tp_iternext(reciever); - else - retval = _PyObject_CallMethodIdObjArgs(reciever, &PyId_send, v, NULL); - } - Py_DECREF(v); - if (retval == NULL) { - PyObject *val; - 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) - goto error; - Py_DECREF(reciever); - SET_TOP(val); - DISPATCH(); - } - /* x remains on stack, retval is value to be yielded */ - f->f_stacktop = stack_pointer; - why = WHY_YIELD; - /* and repeat... */ - f->f_lasti--; - goto fast_yield; - } - - 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"); - goto error; - } - UNWIND_EXCEPT_HANDLER(b); - DISPATCH(); - } - - TARGET(POP_BLOCK) { - PyTryBlock *b = PyFrame_BlockPop(f); - UNWIND_BLOCK(b); - DISPATCH(); - } - - PREDICTED(END_FINALLY); - 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(); - if (why == WHY_SILENCED) { - /* An exception was silenced by 'with', we must - manually unwind the EXCEPT_HANDLER block which was - created when the exception was caught, otherwise - the stack will be in an inconsistent state. */ - PyTryBlock *b = PyFrame_BlockPop(f); - 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(status)) { - PyObject *exc = POP(); - PyObject *tb = POP(); - PyErr_Restore(status, exc, tb); - why = WHY_EXCEPTION; - goto fast_block_end; - } - else if (status != Py_None) { - PyErr_SetString(PyExc_SystemError, - "'finally' pops bad exception"); - Py_DECREF(status); - goto error; - } - Py_DECREF(status); - DISPATCH(); - } - - TARGET(LOAD_BUILD_CLASS) { - _Py_IDENTIFIER(__build_class__); - - PyObject *bc; - if (PyDict_CheckExact(f->f_builtins)) { - bc = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); - if (bc == NULL) { - PyErr_SetString(PyExc_NameError, - "__build_class__ not found"); - goto error; - } - Py_INCREF(bc); - } - else { - PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__); - if (build_class_str == NULL) - break; - 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"); - goto error; - } - } - PUSH(bc); - DISPATCH(); - } - - 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); - goto error; - } - 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) { - 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; - } - 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) { - PyObject *seq = POP(), *item, **items; - if (PyTuple_CheckExact(seq) && - PyTuple_GET_SIZE(seq) == oparg) { - items = ((PyTupleObject *)seq)->ob_item; - while (oparg--) { - item = items[oparg]; - Py_INCREF(item); - PUSH(item); - } - } else if (PyList_CheckExact(seq) && - PyList_GET_SIZE(seq) == oparg) { - items = ((PyListObject *)seq)->ob_item; - while (oparg--) { - item = items[oparg]; - Py_INCREF(item); - PUSH(item); - } - } else if (unpack_iterable(seq, oparg, -1, - stack_pointer + oparg)) { - STACKADJ(oparg); - } else { - /* unpack_iterable() raised an exception */ - Py_DECREF(seq); - goto error; - } - Py_DECREF(seq); - DISPATCH(); - } - - TARGET(UNPACK_EX) { - int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); - PyObject *seq = POP(); - - if (unpack_iterable(seq, oparg & 0xFF, oparg >> 8, - stack_pointer + totalargs)) { - stack_pointer += totalargs; - } else { - Py_DECREF(seq); - goto error; - } - Py_DECREF(seq); - DISPATCH(); - } - - TARGET(STORE_ATTR) { - PyObject *name = GETITEM(names, oparg); - PyObject *owner = TOP(); - PyObject *v = SECOND(); - int err; - STACKADJ(-2); - err = PyObject_SetAttr(owner, name, v); - Py_DECREF(v); - Py_DECREF(owner); - if (err != 0) - goto error; - DISPATCH(); - } - - 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) { - PyObject *name = GETITEM(names, oparg); - PyObject *v = POP(); - int err; - err = PyDict_SetItem(f->f_globals, name, v); - Py_DECREF(v); - if (err != 0) - goto error; - DISPATCH(); - } - - 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, NAME_ERROR_MSG, name); - goto error; - } - DISPATCH(); - } - - 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", name); - goto error; - } - if (PyDict_CheckExact(locals)) { - v = PyDict_GetItem(locals, name); - Py_XINCREF(v); - } - else { - v = PyObject_GetItem(locals, name); - if (v == NULL) { - if (!PyErr_ExceptionMatches(PyExc_KeyError)) - goto error; - PyErr_Clear(); - } - } - if (v == NULL) { - v = PyDict_GetItem(f->f_globals, name); - Py_XINCREF(v); - if (v == NULL) { - if (PyDict_CheckExact(f->f_builtins)) { - v = PyDict_GetItem(f->f_builtins, name); - if (v == NULL) { - format_exc_check_arg( - PyExc_NameError, - NAME_ERROR_MSG, name); - goto error; - } - Py_INCREF(v); - } - else { - v = PyObject_GetItem(f->f_builtins, name); - if (v == NULL) { - if (PyErr_ExceptionMatches(PyExc_KeyError)) - format_exc_check_arg( - PyExc_NameError, - NAME_ERROR_MSG, name); - goto error; - } - } - } - } - PUSH(v); - DISPATCH(); - } - - TARGET(LOAD_GLOBAL) { - PyObject *name = GETITEM(names, oparg); - PyObject *v; - if (PyDict_CheckExact(f->f_globals) - && PyDict_CheckExact(f->f_builtins)) - { - v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals, - (PyDictObject *)f->f_builtins, - name); - if (v == NULL) { - if (!_PyErr_OCCURRED()) { - /* _PyDict_LoadGlobal() returns NULL without raising - * an exception if the key doesn't exist */ - format_exc_check_arg(PyExc_NameError, - NAME_ERROR_MSG, name); - } - goto error; - } - Py_INCREF(v); - } - else { - /* Slow-path if globals or builtins is not a dict */ - - /* namespace 1: globals */ - v = PyObject_GetItem(f->f_globals, name); - if (v == NULL) { - if (!PyErr_ExceptionMatches(PyExc_KeyError)) - goto error; - PyErr_Clear(); - - /* namespace 2: builtins */ - v = PyObject_GetItem(f->f_builtins, name); - if (v == NULL) { - if (PyErr_ExceptionMatches(PyExc_KeyError)) - format_exc_check_arg( - PyExc_NameError, - NAME_ERROR_MSG, name); - goto error; - } - } - } - PUSH(v); - DISPATCH(); - } - - TARGET(DELETE_FAST) { - PyObject *v = GETLOCAL(oparg); - if (v != NULL) { - SETLOCAL(oparg, NULL); - DISPATCH(); - } - format_exc_check_arg( - PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_varnames, oparg) - ); - goto error; - } - - TARGET(DELETE_DEREF) { - PyObject *cell = freevars[oparg]; - if (PyCell_GET(cell) != NULL) { - PyCell_Set(cell, NULL); - DISPATCH(); - } - format_exc_unbound(co, oparg); - goto error; - } - - TARGET(LOAD_CLOSURE) { - PyObject *cell = freevars[oparg]; - Py_INCREF(cell); - PUSH(cell); - 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); - } - else { - value = PyObject_GetItem(locals, name); - if (value == NULL) { - 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(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(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); - } - PUSH(tup); - 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); - } - PUSH(list); - DISPATCH(); - } - - TARGET_WITH_IMPL(BUILD_TUPLE_UNPACK, _build_list_unpack) - TARGET(BUILD_LIST_UNPACK) - _build_list_unpack: { - int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK; - int i; - PyObject *sum = PyList_New(0); - PyObject *return_value; - if (sum == NULL) - goto error; - - for (i = oparg; i > 0; i--) { - PyObject *none_val; - - none_val = _PyList_Extend((PyListObject *)sum, PEEK(i)); - if (none_val == NULL) { - Py_DECREF(sum); - goto error; - } - Py_DECREF(none_val); - } - - if (convert_to_tuple) { - return_value = PyList_AsTuple(sum); - Py_DECREF(sum); - if (return_value == NULL) - goto error; - } - else { - return_value = sum; - } - - while (oparg--) - Py_DECREF(POP()); - PUSH(return_value); - 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); - } - if (err != 0) { - Py_DECREF(set); - goto error; - } - PUSH(set); - DISPATCH(); - } - - TARGET(BUILD_SET_UNPACK) { - int i; - PyObject *sum = PySet_New(NULL); - if (sum == NULL) - goto error; - - for (i = oparg; i > 0; i--) { - if (_PySet_Update(sum, PEEK(i)) < 0) { - Py_DECREF(sum); - goto error; - } - } - - while (oparg--) - Py_DECREF(POP()); - PUSH(sum); - DISPATCH(); - } - - TARGET(BUILD_MAP) { - int i; - PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); - if (map == NULL) - goto error; - for (i = oparg; i > 0; i--) { - int err; - PyObject *key = PEEK(2*i); - PyObject *value = PEEK(2*i - 1); - err = PyDict_SetItem(map, key, value); - if (err != 0) { - Py_DECREF(map); - goto error; - } - } - - while (oparg--) { - Py_DECREF(POP()); - Py_DECREF(POP()); - } - PUSH(map); - DISPATCH(); - } - - TARGET_WITH_IMPL(BUILD_MAP_UNPACK_WITH_CALL, _build_map_unpack) - TARGET(BUILD_MAP_UNPACK) - _build_map_unpack: { - int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL; - int num_maps; - int function_location; - int i; - PyObject *sum = PyDict_New(); - if (sum == NULL) - goto error; - if (with_call) { - num_maps = oparg & 0xff; - function_location = (oparg>>8) & 0xff; - } - else { - num_maps = oparg; - } - - for (i = num_maps; i > 0; i--) { - PyObject *arg = PEEK(i); - if (with_call) { - PyObject *intersection = _PyDictView_Intersect(sum, arg); - - if (intersection == NULL) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyObject *func = ( - PEEK(function_location + num_maps)); - PyErr_Format(PyExc_TypeError, - "%.200s%.200s argument after ** " - "must be a mapping, not %.200s", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - arg->ob_type->tp_name); - } - Py_DECREF(sum); - goto error; - } - - if (PySet_GET_SIZE(intersection)) { - Py_ssize_t idx = 0; - PyObject *key; - PyObject *func = PEEK(function_location + num_maps); - Py_hash_t hash; - _PySet_NextEntry(intersection, &idx, &key, &hash); - if (!PyUnicode_Check(key)) { - PyErr_Format(PyExc_TypeError, - "%.200s%.200s keywords must be strings", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func)); - } else { - PyErr_Format(PyExc_TypeError, - "%.200s%.200s got multiple " - "values for keyword argument '%U'", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - key); - } - Py_DECREF(intersection); - Py_DECREF(sum); - goto error; - } - Py_DECREF(intersection); - } - - if (PyDict_Update(sum, arg) < 0) { - if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Format(PyExc_TypeError, - "'%.200s' object is not a mapping", - arg->ob_type->tp_name); - } - Py_DECREF(sum); - goto error; - } - } - - while (num_maps--) - Py_DECREF(POP()); - PUSH(sum); - DISPATCH(); - } - - TARGET(MAP_ADD) { - PyObject *key = TOP(); - PyObject *value = SECOND(); - PyObject *map; - int err; - STACKADJ(-2); - 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) { - 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) { - 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) { - _Py_IDENTIFIER(__import__); - 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"); - goto error; - } - 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, - from, - level); - else - args = PyTuple_Pack(4, - name, - f->f_globals, - f->f_locals == NULL ? - Py_None : f->f_locals, - from); - Py_DECREF(level); - Py_DECREF(from); - if (args == NULL) { - Py_DECREF(func); - STACKADJ(-1); - goto error; - } - READ_TIMESTAMP(intr0); - res = PyEval_CallObject(func, args); - READ_TIMESTAMP(intr1); - Py_DECREF(args); - Py_DECREF(func); - SET_TOP(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - 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 *'"); - goto error; - } - READ_TIMESTAMP(intr0); - err = import_all_from(locals, from); - READ_TIMESTAMP(intr1); - PyFrame_LocalsToFast(f, 0); - Py_DECREF(from); - if (err != 0) - goto error; - DISPATCH(); - } - - TARGET(IMPORT_FROM) { - PyObject *name = GETITEM(names, oparg); - PyObject *from = TOP(); - PyObject *res; - READ_TIMESTAMP(intr0); - res = import_from(from, name); - READ_TIMESTAMP(intr1); - PUSH(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET(JUMP_FORWARD) { - JUMPBY(oparg); - FAST_DISPATCH(); - } - - PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); - TARGET(POP_JUMP_IF_FALSE) { - PyObject *cond = POP(); - int err; - if (cond == Py_True) { - Py_DECREF(cond); - FAST_DISPATCH(); - } - if (cond == Py_False) { - Py_DECREF(cond); - JUMPTO(oparg); - FAST_DISPATCH(); - } - err = PyObject_IsTrue(cond); - Py_DECREF(cond); - if (err > 0) - err = 0; - else if (err == 0) - JUMPTO(oparg); - else - goto error; - DISPATCH(); - } - - PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); - TARGET(POP_JUMP_IF_TRUE) { - PyObject *cond = POP(); - int err; - if (cond == Py_False) { - Py_DECREF(cond); - FAST_DISPATCH(); - } - if (cond == Py_True) { - Py_DECREF(cond); - JUMPTO(oparg); - FAST_DISPATCH(); - } - err = PyObject_IsTrue(cond); - Py_DECREF(cond); - if (err > 0) { - err = 0; - JUMPTO(oparg); - } - else if (err == 0) - ; - else - goto error; - DISPATCH(); - } - - TARGET(JUMP_IF_FALSE_OR_POP) { - PyObject *cond = TOP(); - int err; - if (cond == Py_True) { - STACKADJ(-1); - Py_DECREF(cond); - FAST_DISPATCH(); - } - if (cond == Py_False) { - JUMPTO(oparg); - FAST_DISPATCH(); - } - err = PyObject_IsTrue(cond); - if (err > 0) { - STACKADJ(-1); - Py_DECREF(cond); - err = 0; - } - else if (err == 0) - JUMPTO(oparg); - else - goto error; - DISPATCH(); - } - - TARGET(JUMP_IF_TRUE_OR_POP) { - PyObject *cond = TOP(); - int err; - if (cond == Py_False) { - STACKADJ(-1); - Py_DECREF(cond); - FAST_DISPATCH(); - } - if (cond == Py_True) { - JUMPTO(oparg); - FAST_DISPATCH(); - } - err = PyObject_IsTrue(cond); - if (err > 0) { - err = 0; - JUMPTO(oparg); - } - else if (err == 0) { - STACKADJ(-1); - Py_DECREF(cond); - } - else - goto error; - DISPATCH(); - } - - PREDICTED_WITH_ARG(JUMP_ABSOLUTE); - TARGET(JUMP_ABSOLUTE) { - JUMPTO(oparg); -#if FAST_LOOPS - /* Enabling this path speeds-up all while and for-loops by bypassing - the per-loop checks for signals. By default, this should be turned-off - because it prevents detection of a control-break in tight loops like - "while 1: pass". Compile with this option turned-on when you need - the speed-up and do not need break checking inside tight loops (ones - that contain only instructions ending with FAST_DISPATCH). - */ - FAST_DISPATCH(); -#else - DISPATCH(); -#endif - } - - TARGET(GET_ITER) { - /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); - PyObject *iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) - goto error; - PREDICT(FOR_ITER); - DISPATCH(); - } - - TARGET(GET_YIELD_FROM_ITER) { - /* before: [obj]; after [getiter(obj)] */ - PyObject *iterable = TOP(); - PyObject *iter; - if (PyCoro_CheckExact(iterable)) { - /* `iterable` is a coroutine */ - if (!(co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { - /* and it is used in a 'yield from' expression of a - regular generator. */ - Py_DECREF(iterable); - SET_TOP(NULL); - PyErr_SetString(PyExc_TypeError, - "cannot 'yield from' a coroutine object " - "in a non-coroutine generator"); - goto error; - } - } - else if (!PyGen_CheckExact(iterable)) { - /* `iterable` is not a generator. */ - iter = PyObject_GetIter(iterable); - Py_DECREF(iterable); - SET_TOP(iter); - if (iter == NULL) - goto error; - } - DISPATCH(); - } - - PREDICTED_WITH_ARG(FOR_ITER); - TARGET(FOR_ITER) { - /* before: [iter]; after: [iter, iter()] *or* [] */ - 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)) - goto error; - else if (tstate->c_tracefunc != NULL) - call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f); - PyErr_Clear(); - } - /* iterator ended normally */ - STACKADJ(-1); - Py_DECREF(iter); - JUMPBY(oparg); - DISPATCH(); - } - - TARGET(BREAK_LOOP) { - why = WHY_BREAK; - goto fast_block_end; - } - - TARGET(CONTINUE_LOOP) { - retval = PyLong_FromLong(oparg); - 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: { - /* 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. - */ - - PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, - STACK_LEVEL()); - DISPATCH(); - } - - TARGET(BEFORE_ASYNC_WITH) { - _Py_IDENTIFIER(__aexit__); - _Py_IDENTIFIER(__aenter__); - - PyObject *mgr = TOP(); - PyObject *exit = special_lookup(mgr, &PyId___aexit__), - *enter; - PyObject *res; - if (exit == NULL) - goto error; - SET_TOP(exit); - enter = special_lookup(mgr, &PyId___aenter__); - Py_DECREF(mgr); - if (enter == NULL) - goto error; - res = PyObject_CallFunctionObjArgs(enter, NULL); - Py_DECREF(enter); - if (res == NULL) - goto error; - PUSH(res); - DISPATCH(); - } - - TARGET(SETUP_ASYNC_WITH) { - PyObject *res = POP(); - /* Setup the finally block before pushing the result - of __aenter__ on the stack. */ - PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg, - STACK_LEVEL()); - PUSH(res); - DISPATCH(); - } - - TARGET(SETUP_WITH) { - _Py_IDENTIFIER(__exit__); - _Py_IDENTIFIER(__enter__); - 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(res); - DISPATCH(); - } - - TARGET(WITH_CLEANUP_START) { - /* At the top of the stack are 1-6 values indicating - how/why we entered the finally clause: - - TOP = None - - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval - - TOP = WHY_*; no retval below it - - (TOP, SECOND, THIRD) = exc_info() - (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER - Below them is EXIT, the context.__exit__ bound method. - In the last case, we must call - EXIT(TOP, SECOND, THIRD) - otherwise we must call - EXIT(None, None, None) - - In the first three cases, we remove EXIT from the - stack, leaving the rest in the same order. In the - fourth case, we shift the bottom 3 values of the - stack down, and replace the empty spot with NULL. - - In addition, if the stack represents an exception, - *and* the function call returns a 'true' value, we - push WHY_SILENCED onto the stack. END_FINALLY will - then not re-raise the exception. (But non-local - gotos should still be resumed.) - */ - - PyObject *exit_func; - PyObject *exc = TOP(), *val = Py_None, *tb = Py_None, *res; - if (exc == Py_None) { - (void)POP(); - exit_func = TOP(); - SET_TOP(exc); - } - 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(exc); - break; - default: - exit_func = TOP(); - SET_TOP(exc); - break; - } - exc = Py_None; - } - else { - PyObject *tp2, *exc2, *tb2; - PyTryBlock *block; - val = SECOND(); - tb = THIRD(); - tp2 = FOURTH(); - exc2 = PEEK(5); - tb2 = PEEK(6); - exit_func = PEEK(7); - 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 - to tell the except handler block that the - values are lower than it expects. */ - block = &f->f_blockstack[f->f_iblock - 1]; - assert(block->b_type == EXCEPT_HANDLER); - block->b_level--; - } - /* XXX Not the fastest way to call it... */ - res = PyObject_CallFunctionObjArgs(exit_func, exc, val, tb, NULL); - Py_DECREF(exit_func); - if (res == NULL) - goto error; - - Py_INCREF(exc); /* Duplicating the exception on the stack */ - PUSH(exc); - PUSH(res); - PREDICT(WITH_CLEANUP_FINISH); - DISPATCH(); - } - - PREDICTED(WITH_CLEANUP_FINISH); - TARGET(WITH_CLEANUP_FINISH) { - PyObject *res = POP(); - PyObject *exc = POP(); - int err; - - if (exc != Py_None) - err = PyObject_IsTrue(res); - else - err = 0; - - Py_DECREF(res); - Py_DECREF(exc); - - if (err < 0) - 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); - DISPATCH(); - } - - TARGET(CALL_FUNCTION) { - PyObject **sp, *res; - PCALL(PCALL_ALL); - sp = stack_pointer; -#ifdef WITH_TSC - res = call_function(&sp, oparg, &intr0, &intr1); -#else - res = call_function(&sp, oparg); -#endif - stack_pointer = sp; - 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: { - int na = oparg & 0xff; - int nk = (oparg>>8) & 0xff; - int flags = (opcode - CALL_FUNCTION) & 3; - int n = na + 2 * nk; - PyObject **pfunc, *func, **sp, *res; - PCALL(PCALL_ALL); - if (flags & CALL_FLAG_VAR) - n++; - if (flags & CALL_FLAG_KW) - n++; - pfunc = stack_pointer - n - 1; - func = *pfunc; - - if (PyMethod_Check(func) - && PyMethod_GET_SELF(func) != NULL) { - PyObject *self = PyMethod_GET_SELF(func); - Py_INCREF(self); - func = PyMethod_GET_FUNCTION(func); - Py_INCREF(func); - Py_SETREF(*pfunc, self); - na++; - /* n++; */ - } else - Py_INCREF(func); - sp = stack_pointer; - READ_TIMESTAMP(intr0); - res = ext_do_call(func, &sp, flags, na, nk); - READ_TIMESTAMP(intr1); - stack_pointer = sp; - Py_DECREF(func); - - while (stack_pointer > pfunc) { - PyObject *o = POP(); - Py_DECREF(o); - } - PUSH(res); - if (res == NULL) - goto error; - DISPATCH(); - } - - TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function) - TARGET(MAKE_FUNCTION) - _make_function: { - int posdefaults = oparg & 0xff; - int kwdefaults = (oparg>>8) & 0xff; - int num_annotations = (oparg >> 16) & 0x7fff; - - 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 (opcode == MAKE_CLOSURE) { - PyObject *closure = POP(); - if (PyFunction_SetClosure(func, closure) != 0) { - /* Can't happen unless bytecode is corrupt. */ - Py_DECREF(func); - Py_DECREF(closure); - goto error; - } - Py_DECREF(closure); - } - - if (num_annotations > 0) { - Py_ssize_t name_ix; - PyObject *names = POP(); /* names of args with annotations */ - PyObject *anns = PyDict_New(); - if (anns == NULL) { - Py_DECREF(func); - goto error; - } - name_ix = PyTuple_Size(names); - assert(num_annotations == name_ix+1); - while (name_ix > 0) { - PyObject *name, *value; - int err; - --name_ix; - 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(func, anns) != 0) { - /* Can't happen unless - PyFunction_SetAnnotations changes. */ - Py_DECREF(anns); - Py_DECREF(func); - goto error; - } - Py_DECREF(anns); - Py_DECREF(names); - } - - /* XXX Maybe this should be a separate opcode? */ - if (kwdefaults > 0) { - PyObject *defs = PyDict_New(); - if (defs == NULL) { - Py_DECREF(func); - goto error; - } - 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_SetKwDefaults(func, defs) != 0) { - /* Can't happen unless - PyFunction_SetKwDefaults changes. */ - Py_DECREF(func); - Py_DECREF(defs); - goto error; - } - Py_DECREF(defs); - } - if (posdefaults > 0) { - PyObject *defs = PyTuple_New(posdefaults); - if (defs == NULL) { - Py_DECREF(func); - goto error; - } - while (--posdefaults >= 0) - PyTuple_SET_ITEM(defs, posdefaults, POP()); - if (PyFunction_SetDefaults(func, defs) != 0) { - /* Can't happen unless - PyFunction_SetDefaults changes. */ - Py_DECREF(defs); - Py_DECREF(func); - goto error; - } - Py_DECREF(defs); - } - PUSH(func); - DISPATCH(); - } - - TARGET(BUILD_SLICE) { - PyObject *start, *stop, *step, *slice; - if (oparg == 3) - step = POP(); - else - 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(FORMAT_VALUE) { - /* Handles f-string value formatting. */ - PyObject *result; - PyObject *fmt_spec; - PyObject *value; - PyObject *(*conv_fn)(PyObject *); - int which_conversion = oparg & FVC_MASK; - int have_fmt_spec = (oparg & FVS_MASK) == FVS_HAVE_SPEC; - - fmt_spec = have_fmt_spec ? POP() : NULL; - value = TOP(); - - /* See if any conversion is specified. */ - switch (which_conversion) { - case FVC_STR: conv_fn = PyObject_Str; break; - case FVC_REPR: conv_fn = PyObject_Repr; break; - case FVC_ASCII: conv_fn = PyObject_ASCII; break; - - /* Must be 0 (meaning no conversion), since only four - values are allowed by (oparg & FVC_MASK). */ - default: conv_fn = NULL; break; - } - - /* If there's a conversion function, call it and replace - value with that result. Otherwise, just use value, - without conversion. */ - if (conv_fn) { - result = conv_fn(value); - Py_DECREF(value); - if (!result) { - Py_XDECREF(fmt_spec); - goto error; - } - value = result; - } - - /* If value is a unicode object, and there's no fmt_spec, - then we know the result of format(value) is value - itself. In that case, skip calling format(). I plan to - move this optimization in to PyObject_Format() - itself. */ - if (PyUnicode_CheckExact(value) && fmt_spec == NULL) { - /* Do nothing, just transfer ownership to result. */ - result = value; - } else { - /* Actually call format(). */ - result = PyObject_Format(value, fmt_spec); - Py_DECREF(value); - Py_XDECREF(fmt_spec); - if (!result) - goto error; - } - - SET_TOP(result); - DISPATCH(); - } + +#include "ceval_func.h" +#include "ceval_build.h" +#include "ceval_condjump.h" +#include "ceval_iter.h" +#include "ceval_ctx.h" +#include "ceval_module.h" +#include "ceval_misc.h" TARGET(EXTENDED_ARG) { opcode = NEXTOP(); diff -r d3be5c4507b4 Python/ceval_build.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_build.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,268 @@ +/* Instructions to build tuple, list, set, etc. */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +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); + } + PUSH(tup); + 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); + } + PUSH(list); + DISPATCH(); +} + +TARGET_WITH_IMPL(BUILD_TUPLE_UNPACK, _build_list_unpack) +TARGET(BUILD_LIST_UNPACK) +_build_list_unpack: { + int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK; + int i; + PyObject *sum = PyList_New(0); + PyObject *return_value; + if (sum == NULL) + goto error; + + for (i = oparg; i > 0; i--) { + PyObject *none_val; + + none_val = _PyList_Extend((PyListObject *)sum, PEEK(i)); + if (none_val == NULL) { + Py_DECREF(sum); + goto error; + } + Py_DECREF(none_val); + } + + if (convert_to_tuple) { + return_value = PyList_AsTuple(sum); + Py_DECREF(sum); + if (return_value == NULL) + goto error; + } + else { + return_value = sum; + } + + while (oparg--) + Py_DECREF(POP()); + PUSH(return_value); + 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); + } + if (err != 0) { + Py_DECREF(set); + goto error; + } + PUSH(set); + DISPATCH(); +} + +TARGET(BUILD_SET_UNPACK) { + int i; + PyObject *sum = PySet_New(NULL); + if (sum == NULL) + goto error; + + for (i = oparg; i > 0; i--) { + if (_PySet_Update(sum, PEEK(i)) < 0) { + Py_DECREF(sum); + goto error; + } + } + + while (oparg--) + Py_DECREF(POP()); + PUSH(sum); + DISPATCH(); +} + +TARGET(BUILD_MAP) { + int i; + PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); + if (map == NULL) + goto error; + for (i = oparg; i > 0; i--) { + int err; + PyObject *key = PEEK(2*i); + PyObject *value = PEEK(2*i - 1); + err = PyDict_SetItem(map, key, value); + if (err != 0) { + Py_DECREF(map); + goto error; + } + } + + while (oparg--) { + Py_DECREF(POP()); + Py_DECREF(POP()); + } + PUSH(map); + DISPATCH(); +} + +TARGET_WITH_IMPL(BUILD_MAP_UNPACK_WITH_CALL, _build_map_unpack) +TARGET(BUILD_MAP_UNPACK) +_build_map_unpack: { + int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL; + int num_maps; + int function_location; + int i; + PyObject *sum = PyDict_New(); + if (sum == NULL) + goto error; + if (with_call) { + num_maps = oparg & 0xff; + function_location = (oparg>>8) & 0xff; + } + else { + num_maps = oparg; + } + + for (i = num_maps; i > 0; i--) { + PyObject *arg = PEEK(i); + if (with_call) { + PyObject *intersection = _PyDictView_Intersect(sum, arg); + + if (intersection == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyObject *func = ( + PEEK(function_location + num_maps)); + PyErr_Format(PyExc_TypeError, + "%.200s%.200s argument after ** " + "must be a mapping, not %.200s", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + arg->ob_type->tp_name); + } + Py_DECREF(sum); + goto error; + } + + if (PySet_GET_SIZE(intersection)) { + Py_ssize_t idx = 0; + PyObject *key; + PyObject *func = PEEK(function_location + num_maps); + Py_hash_t hash; + _PySet_NextEntry(intersection, &idx, &key, &hash); + if (!PyUnicode_Check(key)) { + PyErr_Format(PyExc_TypeError, + "%.200s%.200s keywords must be strings", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func)); + } else { + PyErr_Format(PyExc_TypeError, + "%.200s%.200s got multiple " + "values for keyword argument '%U'", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + key); + } + Py_DECREF(intersection); + Py_DECREF(sum); + goto error; + } + Py_DECREF(intersection); + } + + if (PyDict_Update(sum, arg) < 0) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_TypeError, + "'%.200s' object is not a mapping", + arg->ob_type->tp_name); + } + Py_DECREF(sum); + goto error; + } + } + + while (num_maps--) + Py_DECREF(POP()); + PUSH(sum); + DISPATCH(); +} + +TARGET(LIST_APPEND) { + PyObject *v = POP(); + PyObject *list = PEEK(oparg); + int err; + err = PyList_Append(list, v); + Py_DECREF(v); + if (err != 0) + goto error; + PREDICT(JUMP_ABSOLUTE); + DISPATCH(); +} + +TARGET(SET_ADD) { + PyObject *v = POP(); + PyObject *set = stack_pointer[-oparg]; + int err; + err = PySet_Add(set, v); + Py_DECREF(v); + if (err != 0) + goto error; + PREDICT(JUMP_ABSOLUTE); + DISPATCH(); +} + +TARGET(MAP_ADD) { + PyObject *key = TOP(); + PyObject *value = SECOND(); + PyObject *map; + int err; + STACKADJ(-2); + 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(BUILD_SLICE) { + PyObject *start, *stop, *step, *slice; + if (oparg == 3) + step = POP(); + else + 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(); +} diff -r d3be5c4507b4 Python/ceval_condjump.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_condjump.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,142 @@ +/* Instructions to compare, conditional jumps and jumps */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +TARGET(JUMP_FORWARD) { + JUMPBY(oparg); + FAST_DISPATCH(); +} + +PREDICTED_WITH_ARG(JUMP_ABSOLUTE); +TARGET(JUMP_ABSOLUTE) { + JUMPTO(oparg); +#if FAST_LOOPS + /* Enabling this path speeds-up all while and for-loops by bypassing + the per-loop checks for signals. By default, this should be turned-off + because it prevents detection of a control-break in tight loops like + "while 1: pass". Compile with this option turned-on when you need + the speed-up and do not need break checking inside tight loops (ones + that contain only instructions ending with FAST_DISPATCH). + */ + FAST_DISPATCH(); +#else + DISPATCH(); +#endif +} + +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(); +} + +PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); +TARGET(POP_JUMP_IF_FALSE) { + PyObject *cond = POP(); + int err; + if (cond == Py_True) { + Py_DECREF(cond); + FAST_DISPATCH(); + } + if (cond == Py_False) { + Py_DECREF(cond); + JUMPTO(oparg); + FAST_DISPATCH(); + } + err = PyObject_IsTrue(cond); + Py_DECREF(cond); + if (err > 0) + err = 0; + else if (err == 0) + JUMPTO(oparg); + else + goto error; + DISPATCH(); +} + +PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); +TARGET(POP_JUMP_IF_TRUE) { + PyObject *cond = POP(); + int err; + if (cond == Py_False) { + Py_DECREF(cond); + FAST_DISPATCH(); + } + if (cond == Py_True) { + Py_DECREF(cond); + JUMPTO(oparg); + FAST_DISPATCH(); + } + err = PyObject_IsTrue(cond); + Py_DECREF(cond); + if (err > 0) { + err = 0; + JUMPTO(oparg); + } + else if (err == 0) + ; + else + goto error; + DISPATCH(); +} + +TARGET(JUMP_IF_FALSE_OR_POP) { + PyObject *cond = TOP(); + int err; + if (cond == Py_True) { + STACKADJ(-1); + Py_DECREF(cond); + FAST_DISPATCH(); + } + if (cond == Py_False) { + JUMPTO(oparg); + FAST_DISPATCH(); + } + err = PyObject_IsTrue(cond); + if (err > 0) { + STACKADJ(-1); + Py_DECREF(cond); + err = 0; + } + else if (err == 0) + JUMPTO(oparg); + else + goto error; + DISPATCH(); +} + +TARGET(JUMP_IF_TRUE_OR_POP) { + PyObject *cond = TOP(); + int err; + if (cond == Py_False) { + STACKADJ(-1); + Py_DECREF(cond); + FAST_DISPATCH(); + } + if (cond == Py_True) { + JUMPTO(oparg); + FAST_DISPATCH(); + } + err = PyObject_IsTrue(cond); + if (err > 0) { + err = 0; + JUMPTO(oparg); + } + else if (err == 0) { + STACKADJ(-1); + Py_DECREF(cond); + } + else + goto error; + DISPATCH(); +} diff -r d3be5c4507b4 Python/ceval_ctx.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_ctx.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,238 @@ +/* Instructions to handle contexts: + * - SETUP_FINALLY, END_FINALLY + * - SETUP_WITH, WITH_CLEANUP_START, WITH_CLEANUP_FINISH + * - RAISE_VARARGS + * - POP_EXCEPT, POP_BLOCK + */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally) +TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally) +TARGET(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. + */ + + PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, + STACK_LEVEL()); + DISPATCH(); +} + +TARGET(SETUP_WITH) { + _Py_IDENTIFIER(__exit__); + _Py_IDENTIFIER(__enter__); + 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(res); + DISPATCH(); +} + +TARGET(WITH_CLEANUP_START) { + /* At the top of the stack are 1-6 values indicating + how/why we entered the finally clause: + - TOP = None + - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval + - TOP = WHY_*; no retval below it + - (TOP, SECOND, THIRD) = exc_info() + (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER + Below them is EXIT, the context.__exit__ bound method. + In the last case, we must call + EXIT(TOP, SECOND, THIRD) + otherwise we must call + EXIT(None, None, None) + + In the first three cases, we remove EXIT from the + stack, leaving the rest in the same order. In the + fourth case, we shift the bottom 3 values of the + stack down, and replace the empty spot with NULL. + + In addition, if the stack represents an exception, + *and* the function call returns a 'true' value, we + push WHY_SILENCED onto the stack. END_FINALLY will + then not re-raise the exception. (But non-local + gotos should still be resumed.) + */ + + PyObject *exit_func; + PyObject *exc = TOP(), *val = Py_None, *tb = Py_None, *res; + if (exc == Py_None) { + (void)POP(); + exit_func = TOP(); + SET_TOP(exc); + } + 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(exc); + break; + default: + exit_func = TOP(); + SET_TOP(exc); + break; + } + exc = Py_None; + } + else { + PyObject *tp2, *exc2, *tb2; + PyTryBlock *block; + val = SECOND(); + tb = THIRD(); + tp2 = FOURTH(); + exc2 = PEEK(5); + tb2 = PEEK(6); + exit_func = PEEK(7); + 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 + to tell the except handler block that the + values are lower than it expects. */ + block = &f->f_blockstack[f->f_iblock - 1]; + assert(block->b_type == EXCEPT_HANDLER); + block->b_level--; + } + /* XXX Not the fastest way to call it... */ + res = PyObject_CallFunctionObjArgs(exit_func, exc, val, tb, NULL); + Py_DECREF(exit_func); + if (res == NULL) + goto error; + + Py_INCREF(exc); /* Duplicating the exception on the stack */ + PUSH(exc); + PUSH(res); + PREDICT(WITH_CLEANUP_FINISH); + DISPATCH(); +} + +PREDICTED(WITH_CLEANUP_FINISH); +TARGET(WITH_CLEANUP_FINISH) { + PyObject *res = POP(); + PyObject *exc = POP(); + int err; + + if (exc != Py_None) + err = PyObject_IsTrue(res); + else + err = 0; + + Py_DECREF(res); + Py_DECREF(exc); + + if (err < 0) + 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); + DISPATCH(); +} + +TARGET(RAISE_VARARGS) { + PyObject *cause = NULL, *exc = NULL; + switch (oparg) { + case 2: + cause = POP(); /* cause */ + case 1: + exc = POP(); /* exc */ + case 0: /* Fallthrough */ + if (do_raise(exc, cause)) { + why = WHY_EXCEPTION; + goto fast_block_end; + } + break; + default: + PyErr_SetString(PyExc_SystemError, + "bad RAISE_VARARGS oparg"); + break; + } + goto error; +} + +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); + DISPATCH(); +} + +PREDICTED(END_FINALLY); +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(); + if (why == WHY_SILENCED) { + /* An exception was silenced by 'with', we must + manually unwind the EXCEPT_HANDLER block which was + created when the exception was caught, otherwise + the stack will be in an inconsistent state. */ + PyTryBlock *b = PyFrame_BlockPop(f); + 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(status)) { + PyObject *exc = POP(); + PyObject *tb = POP(); + PyErr_Restore(status, exc, tb); + why = WHY_EXCEPTION; + goto fast_block_end; + } + else if (status != Py_None) { + PyErr_SetString(PyExc_SystemError, + "'finally' pops bad exception"); + Py_DECREF(status); + goto error; + } + Py_DECREF(status); + DISPATCH(); +} diff -r d3be5c4507b4 Python/ceval_fast.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_fast.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,162 @@ +/* "Fast" instructions: instructions to be the most common + * - LOAD_CONST + * - RETURN_VALUE + * - fast variables + * - global variables + * - attributes + */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +TARGET(LOAD_CONST) { + PyObject *value = GETITEM(consts, oparg); + Py_INCREF(value); + PUSH(value); + 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; + } + Py_INCREF(value); + PUSH(value); + FAST_DISPATCH(); +} + +PREDICTED_WITH_ARG(STORE_FAST); +TARGET(STORE_FAST) { + PyObject *value = POP(); + SETLOCAL(oparg, value); + FAST_DISPATCH(); +} + +TARGET(DELETE_FAST) { + PyObject *v = GETLOCAL(oparg); + if (v != NULL) { + SETLOCAL(oparg, NULL); + DISPATCH(); + } + format_exc_check_arg( + PyExc_UnboundLocalError, + UNBOUNDLOCAL_ERROR_MSG, + PyTuple_GetItem(co->co_varnames, oparg) + ); + goto error; +} + +TARGET(RETURN_VALUE) { + retval = POP(); + why = WHY_RETURN; + goto fast_block_end; +} + +TARGET(LOAD_GLOBAL) { + PyObject *name = GETITEM(names, oparg); + PyObject *v; + if (PyDict_CheckExact(f->f_globals) + && PyDict_CheckExact(f->f_builtins)) + { + v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals, + (PyDictObject *)f->f_builtins, + name); + if (v == NULL) { + if (!_PyErr_OCCURRED()) { + /* _PyDict_LoadGlobal() returns NULL without raising + * an exception if the key doesn't exist */ + format_exc_check_arg(PyExc_NameError, + NAME_ERROR_MSG, name); + } + goto error; + } + Py_INCREF(v); + } + else { + /* Slow-path if globals or builtins is not a dict */ + + /* namespace 1: globals */ + v = PyObject_GetItem(f->f_globals, name); + if (v == NULL) { + if (!PyErr_ExceptionMatches(PyExc_KeyError)) + goto error; + PyErr_Clear(); + + /* namespace 2: builtins */ + v = PyObject_GetItem(f->f_builtins, name); + if (v == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + NAME_ERROR_MSG, name); + goto error; + } + } + } + PUSH(v); + DISPATCH(); +} + +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) + goto error; + DISPATCH(); +} + +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, NAME_ERROR_MSG, name); + goto error; + } + DISPATCH(); +} + +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(STORE_ATTR) { + PyObject *name = GETITEM(names, oparg); + PyObject *owner = TOP(); + PyObject *v = SECOND(); + int err; + STACKADJ(-2); + err = PyObject_SetAttr(owner, name, v); + Py_DECREF(v); + Py_DECREF(owner); + if (err != 0) + goto error; + DISPATCH(); +} + +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(); +} diff -r d3be5c4507b4 Python/ceval_func.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_func.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,249 @@ +/* Instructions to handle free variables, call functions and make functions */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +TARGET(LOAD_CLOSURE) { + PyObject *cell = freevars[oparg]; + Py_INCREF(cell); + PUSH(cell); + DISPATCH(); +} + +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(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); + } + else { + value = PyObject_GetItem(locals, name); + if (value == NULL) { + 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) { + PyObject *v = POP(); + PyObject *cell = freevars[oparg]; + PyCell_Set(cell, v); + Py_DECREF(v); + DISPATCH(); +} + +TARGET(DELETE_DEREF) { + PyObject *cell = freevars[oparg]; + if (PyCell_GET(cell) != NULL) { + PyCell_Set(cell, NULL); + DISPATCH(); + } + format_exc_unbound(co, oparg); + goto error; +} + +TARGET(CALL_FUNCTION) { + PyObject **sp, *res; + PCALL(PCALL_ALL); + sp = stack_pointer; +#ifdef WITH_TSC + res = call_function(&sp, oparg, &intr0, &intr1); +#else + res = call_function(&sp, oparg); +#endif + stack_pointer = sp; + 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: { + int na = oparg & 0xff; + int nk = (oparg>>8) & 0xff; + int flags = (opcode - CALL_FUNCTION) & 3; + int n = na + 2 * nk; + PyObject **pfunc, *func, **sp, *res; + PCALL(PCALL_ALL); + if (flags & CALL_FLAG_VAR) + n++; + if (flags & CALL_FLAG_KW) + n++; + pfunc = stack_pointer - n - 1; + func = *pfunc; + + if (PyMethod_Check(func) + && PyMethod_GET_SELF(func) != NULL) { + PyObject *self = PyMethod_GET_SELF(func); + Py_INCREF(self); + func = PyMethod_GET_FUNCTION(func); + Py_INCREF(func); + Py_SETREF(*pfunc, self); + na++; + /* n++; */ + } else + Py_INCREF(func); + sp = stack_pointer; + READ_TIMESTAMP(intr0); + res = ext_do_call(func, &sp, flags, na, nk); + READ_TIMESTAMP(intr1); + stack_pointer = sp; + Py_DECREF(func); + + while (stack_pointer > pfunc) { + PyObject *o = POP(); + Py_DECREF(o); + } + PUSH(res); + if (res == NULL) + goto error; + DISPATCH(); +} + +TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function) +TARGET(MAKE_FUNCTION) +_make_function: { + int posdefaults = oparg & 0xff; + int kwdefaults = (oparg>>8) & 0xff; + int num_annotations = (oparg >> 16) & 0x7fff; + + 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 (opcode == MAKE_CLOSURE) { + PyObject *closure = POP(); + if (PyFunction_SetClosure(func, closure) != 0) { + /* Can't happen unless bytecode is corrupt. */ + Py_DECREF(func); + Py_DECREF(closure); + goto error; + } + Py_DECREF(closure); + } + + if (num_annotations > 0) { + Py_ssize_t name_ix; + PyObject *names = POP(); /* names of args with annotations */ + PyObject *anns = PyDict_New(); + if (anns == NULL) { + Py_DECREF(func); + goto error; + } + name_ix = PyTuple_Size(names); + assert(num_annotations == name_ix+1); + while (name_ix > 0) { + PyObject *name, *value; + int err; + --name_ix; + 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(func, anns) != 0) { + /* Can't happen unless + PyFunction_SetAnnotations changes. */ + Py_DECREF(anns); + Py_DECREF(func); + goto error; + } + Py_DECREF(anns); + Py_DECREF(names); + } + + /* XXX Maybe this should be a separate opcode? */ + if (kwdefaults > 0) { + PyObject *defs = PyDict_New(); + if (defs == NULL) { + Py_DECREF(func); + goto error; + } + 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_SetKwDefaults(func, defs) != 0) { + /* Can't happen unless + PyFunction_SetKwDefaults changes. */ + Py_DECREF(func); + Py_DECREF(defs); + goto error; + } + Py_DECREF(defs); + } + if (posdefaults > 0) { + PyObject *defs = PyTuple_New(posdefaults); + if (defs == NULL) { + Py_DECREF(func); + goto error; + } + while (--posdefaults >= 0) + PyTuple_SET_ITEM(defs, posdefaults, POP()); + if (PyFunction_SetDefaults(func, defs) != 0) { + /* Can't happen unless + PyFunction_SetDefaults changes. */ + Py_DECREF(defs); + Py_DECREF(func); + goto error; + } + Py_DECREF(defs); + } + PUSH(func); + DISPATCH(); +} + diff -r d3be5c4507b4 Python/ceval_iter.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_iter.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,262 @@ +/* Instructions to handle iterators, awaitable, async with, yield from, etc. */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +TARGET(BEFORE_ASYNC_WITH) { + _Py_IDENTIFIER(__aexit__); + _Py_IDENTIFIER(__aenter__); + + PyObject *mgr = TOP(); + PyObject *exit = special_lookup(mgr, &PyId___aexit__), + *enter; + PyObject *res; + if (exit == NULL) + goto error; + SET_TOP(exit); + enter = special_lookup(mgr, &PyId___aenter__); + Py_DECREF(mgr); + if (enter == NULL) + goto error; + res = PyObject_CallFunctionObjArgs(enter, NULL); + Py_DECREF(enter); + if (res == NULL) + goto error; + PUSH(res); + DISPATCH(); +} + +TARGET(SETUP_ASYNC_WITH) { + PyObject *res = POP(); + /* Setup the finally block before pushing the result + of __aenter__ on the stack. */ + PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg, + STACK_LEVEL()); + PUSH(res); + DISPATCH(); +} + +TARGET(GET_AITER) { + unaryfunc getter = NULL; + PyObject *iter = NULL; + PyObject *awaitable = NULL; + PyObject *obj = TOP(); + PyTypeObject *type = Py_TYPE(obj); + + if (type->tp_as_async != NULL) + getter = type->tp_as_async->am_aiter; + + if (getter != NULL) { + iter = (*getter)(obj); + Py_DECREF(obj); + if (iter == NULL) { + SET_TOP(NULL); + goto error; + } + } + else { + SET_TOP(NULL); + PyErr_Format( + PyExc_TypeError, + "'async for' requires an object with " + "__aiter__ method, got %.100s", + type->tp_name); + Py_DECREF(obj); + goto error; + } + + awaitable = _PyCoro_GetAwaitableIter(iter); + if (awaitable == NULL) { + SET_TOP(NULL); + PyErr_Format( + PyExc_TypeError, + "'async for' received an invalid object " + "from __aiter__: %.100s", + Py_TYPE(iter)->tp_name); + + Py_DECREF(iter); + goto error; + } else + Py_DECREF(iter); + + SET_TOP(awaitable); + DISPATCH(); +} + +TARGET(GET_ANEXT) { + unaryfunc getter = NULL; + PyObject *next_iter = NULL; + PyObject *awaitable = NULL; + PyObject *aiter = TOP(); + PyTypeObject *type = Py_TYPE(aiter); + + if (type->tp_as_async != NULL) + getter = type->tp_as_async->am_anext; + + if (getter != NULL) { + next_iter = (*getter)(aiter); + if (next_iter == NULL) { + goto error; + } + } + else { + PyErr_Format( + PyExc_TypeError, + "'async for' requires an iterator with " + "__anext__ method, got %.100s", + type->tp_name); + goto error; + } + + awaitable = _PyCoro_GetAwaitableIter(next_iter); + if (awaitable == NULL) { + PyErr_Format( + PyExc_TypeError, + "'async for' received an invalid object " + "from __anext__: %.100s", + Py_TYPE(next_iter)->tp_name); + + Py_DECREF(next_iter); + goto error; + } else + Py_DECREF(next_iter); + + PUSH(awaitable); + DISPATCH(); +} + +TARGET(GET_AWAITABLE) { + PyObject *iterable = TOP(); + PyObject *iter = _PyCoro_GetAwaitableIter(iterable); + + Py_DECREF(iterable); + + SET_TOP(iter); /* Even if it's NULL */ + + if (iter == NULL) { + goto error; + } + + DISPATCH(); +} + +TARGET(YIELD_FROM) { + PyObject *v = POP(); + PyObject *reciever = TOP(); + int err; + if (PyGen_CheckExact(reciever) || PyCoro_CheckExact(reciever)) { + retval = _PyGen_Send((PyGenObject *)reciever, v); + } else { + _Py_IDENTIFIER(send); + if (v == Py_None) + retval = Py_TYPE(reciever)->tp_iternext(reciever); + else + retval = _PyObject_CallMethodIdObjArgs(reciever, &PyId_send, v, NULL); + } + Py_DECREF(v); + if (retval == NULL) { + PyObject *val; + 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) + goto error; + Py_DECREF(reciever); + SET_TOP(val); + DISPATCH(); + } + /* x remains on stack, retval is value to be yielded */ + f->f_stacktop = stack_pointer; + why = WHY_YIELD; + /* and repeat... */ + f->f_lasti--; + goto fast_yield; +} + +TARGET(YIELD_VALUE) { + retval = POP(); + f->f_stacktop = stack_pointer; + why = WHY_YIELD; + goto fast_yield; +} + +TARGET(GET_ITER) { + /* before: [obj]; after [getiter(obj)] */ + PyObject *iterable = TOP(); + PyObject *iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + SET_TOP(iter); + if (iter == NULL) + goto error; + PREDICT(FOR_ITER); + DISPATCH(); +} + +TARGET(GET_YIELD_FROM_ITER) { + /* before: [obj]; after [getiter(obj)] */ + PyObject *iterable = TOP(); + PyObject *iter; + if (PyCoro_CheckExact(iterable)) { + /* `iterable` is a coroutine */ + if (!(co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { + /* and it is used in a 'yield from' expression of a + regular generator. */ + Py_DECREF(iterable); + SET_TOP(NULL); + PyErr_SetString(PyExc_TypeError, + "cannot 'yield from' a coroutine object " + "in a non-coroutine generator"); + goto error; + } + } + else if (!PyGen_CheckExact(iterable)) { + /* `iterable` is not a generator. */ + iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + SET_TOP(iter); + if (iter == NULL) + goto error; + } + DISPATCH(); +} + +PREDICTED_WITH_ARG(FOR_ITER); +TARGET(FOR_ITER) { + /* before: [iter]; after: [iter, iter()] *or* [] */ + 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)) + goto error; + else if (tstate->c_tracefunc != NULL) + call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f); + PyErr_Clear(); + } + /* iterator ended normally */ + STACKADJ(-1); + Py_DECREF(iter); + JUMPBY(oparg); + DISPATCH(); +} + +TARGET(BREAK_LOOP) { + why = WHY_BREAK; + goto fast_block_end; +} + +TARGET(CONTINUE_LOOP) { + retval = PyLong_FromLong(oparg); + if (retval == NULL) + goto error; + why = WHY_CONTINUE; + goto fast_block_end; +} + diff -r d3be5c4507b4 Python/ceval_misc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_misc.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,155 @@ +/* Misc instructions */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +TARGET(NOP) + FAST_DISPATCH(); + +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(STORE_SUBSCR) { + PyObject *sub = TOP(); + PyObject *container = SECOND(); + PyObject *v = THIRD(); + int err; + STACKADJ(-3); + /* v[w] = u */ + err = PyObject_SetItem(container, sub, v); + Py_DECREF(v); + Py_DECREF(container); + Py_DECREF(sub); + if (err != 0) + goto error; + DISPATCH(); +} + +TARGET(DELETE_SUBSCR) { + PyObject *sub = TOP(); + PyObject *container = SECOND(); + int err; + STACKADJ(-2); + /* del v[w] */ + err = PyObject_DelItem(container, sub); + Py_DECREF(container); + Py_DECREF(sub); + if (err != 0) + goto error; + DISPATCH(); +} + +TARGET(LOAD_BUILD_CLASS) { + _Py_IDENTIFIER(__build_class__); + + PyObject *bc; + if (PyDict_CheckExact(f->f_builtins)) { + bc = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); + if (bc == NULL) { + PyErr_SetString(PyExc_NameError, + "__build_class__ not found"); + goto error; + } + Py_INCREF(bc); + } + else { + PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__); + if (build_class_str == NULL) + break; + 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"); + goto error; + } + } + PUSH(bc); + DISPATCH(); +} + +TARGET(FORMAT_VALUE) { + /* Handles f-string value formatting. */ + PyObject *result; + PyObject *fmt_spec; + PyObject *value; + PyObject *(*conv_fn)(PyObject *); + int which_conversion = oparg & FVC_MASK; + int have_fmt_spec = (oparg & FVS_MASK) == FVS_HAVE_SPEC; + + fmt_spec = have_fmt_spec ? POP() : NULL; + value = TOP(); + + /* See if any conversion is specified. */ + switch (which_conversion) { + case FVC_STR: conv_fn = PyObject_Str; break; + case FVC_REPR: conv_fn = PyObject_Repr; break; + case FVC_ASCII: conv_fn = PyObject_ASCII; break; + + /* Must be 0 (meaning no conversion), since only four + values are allowed by (oparg & FVC_MASK). */ + default: conv_fn = NULL; break; + } + + /* If there's a conversion function, call it and replace + value with that result. Otherwise, just use value, + without conversion. */ + if (conv_fn) { + result = conv_fn(value); + Py_DECREF(value); + if (!result) { + Py_XDECREF(fmt_spec); + goto error; + } + value = result; + } + + /* If value is a unicode object, and there's no fmt_spec, + then we know the result of format(value) is value + itself. In that case, skip calling format(). I plan to + move this optimization in to PyObject_Format() + itself. */ + if (PyUnicode_CheckExact(value) && fmt_spec == NULL) { + /* Do nothing, just transfer ownership to result. */ + result = value; + } else { + /* Actually call format(). */ + result = PyObject_Format(value, fmt_spec); + Py_DECREF(value); + Py_XDECREF(fmt_spec); + if (!result) + goto error; + } + + SET_TOP(result); + DISPATCH(); +} + +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"); + Py_DECREF(value); + goto error; + } + res = PyObject_CallFunctionObjArgs(hook, value, NULL); + Py_DECREF(value); + if (res == NULL) + goto error; + Py_DECREF(res); + DISPATCH(); +} diff -r d3be5c4507b4 Python/ceval_module.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_module.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,180 @@ +/* Instructions usually only used at module-level + * - module level variables ("NAME") + * - imports: IMPORT_NAME, IMPORT_STAR, IMPORT_FROM + * */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +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", name); + goto error; + } + if (PyDict_CheckExact(locals)) { + v = PyDict_GetItem(locals, name); + Py_XINCREF(v); + } + else { + v = PyObject_GetItem(locals, name); + if (v == NULL) { + if (!PyErr_ExceptionMatches(PyExc_KeyError)) + goto error; + PyErr_Clear(); + } + } + if (v == NULL) { + v = PyDict_GetItem(f->f_globals, name); + Py_XINCREF(v); + if (v == NULL) { + if (PyDict_CheckExact(f->f_builtins)) { + v = PyDict_GetItem(f->f_builtins, name); + if (v == NULL) { + format_exc_check_arg( + PyExc_NameError, + NAME_ERROR_MSG, name); + goto error; + } + Py_INCREF(v); + } + else { + v = PyObject_GetItem(f->f_builtins, name); + if (v == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + NAME_ERROR_MSG, name); + goto error; + } + } + } + } + PUSH(v); + DISPATCH(); +} + +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); + goto error; + } + 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) { + 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; + } + err = PyObject_DelItem(ns, name); + if (err != 0) { + format_exc_check_arg(PyExc_NameError, + NAME_ERROR_MSG, + name); + goto error; + } + DISPATCH(); +} + +TARGET(IMPORT_NAME) { + _Py_IDENTIFIER(__import__); + 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"); + goto error; + } + 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, + from, + level); + else + args = PyTuple_Pack(4, + name, + f->f_globals, + f->f_locals == NULL ? + Py_None : f->f_locals, + from); + Py_DECREF(level); + Py_DECREF(from); + if (args == NULL) { + Py_DECREF(func); + STACKADJ(-1); + goto error; + } + READ_TIMESTAMP(intr0); + res = PyEval_CallObject(func, args); + READ_TIMESTAMP(intr1); + Py_DECREF(args); + Py_DECREF(func); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); +} + +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 *'"); + goto error; + } + READ_TIMESTAMP(intr0); + err = import_all_from(locals, from); + READ_TIMESTAMP(intr1); + PyFrame_LocalsToFast(f, 0); + Py_DECREF(from); + if (err != 0) + goto error; + DISPATCH(); +} + +TARGET(IMPORT_FROM) { + PyObject *name = GETITEM(names, oparg); + PyObject *from = TOP(); + PyObject *res; + READ_TIMESTAMP(intr0); + res = import_from(from, name); + READ_TIMESTAMP(intr1); + PUSH(res); + if (res == NULL) + goto error; + DISPATCH(); +} diff -r d3be5c4507b4 Python/ceval_number.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_number.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,384 @@ +/* Instructions to handle numbers (PyNumber_xxx() functions: tp_as_number) + * and UNARY_NOT */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +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); + DISPATCH(); + } + else if (err > 0) { + Py_INCREF(Py_False); + SET_TOP(Py_False); + err = 0; + DISPATCH(); + } + STACKADJ(-1); + goto error; +} + +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) { + PyObject *value = TOP(); + PyObject *res = PyNumber_Negative(value); + Py_DECREF(value); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); +} + +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) { + 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) { + 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_MATRIX_MULTIPLY) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_MatrixMultiply(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); +} + +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) { + 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) { + 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) { + 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 */ + } + else { + sum = PyNumber_Add(left, right); + Py_DECREF(left); + } + Py_DECREF(right); + SET_TOP(sum); + if (sum == NULL) + goto error; + DISPATCH(); +} + +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_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_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_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(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(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) { + 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_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_MATRIX_MULTIPLY) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_InPlaceMatrixMultiply(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); +} + +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_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 */ + } + else { + sum = PyNumber_InPlaceAdd(left, right); + Py_DECREF(left); + } + Py_DECREF(right); + SET_TOP(sum); + if (sum == NULL) + goto error; + DISPATCH(); +} + +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) { + 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) { + 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) { + 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) { + 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) { + 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(); +} diff -r d3be5c4507b4 Python/ceval_stack.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Python/ceval_stack.h Fri Feb 05 18:40:06 2016 +0100 @@ -0,0 +1,93 @@ +/* Instructions to handle the stack */ + +#ifndef PY_CEVAL_INTERNAL +# error "must only be used inside ceval.c" +#endif + +TARGET(POP_TOP) { + PyObject *value = POP(); + Py_DECREF(value); + FAST_DISPATCH(); +} + +TARGET(DUP_TOP) { + PyObject *top = TOP(); + Py_INCREF(top); + PUSH(top); + FAST_DISPATCH(); +} + +TARGET(DUP_TOP_TWO) { + PyObject *top = TOP(); + PyObject *second = SECOND(); + Py_INCREF(top); + Py_INCREF(second); + STACKADJ(2); + SET_TOP(top); + SET_SECOND(second); + FAST_DISPATCH(); +} + +TARGET(ROT_TWO) { + PyObject *top = TOP(); + PyObject *second = SECOND(); + SET_TOP(second); + SET_SECOND(top); + FAST_DISPATCH(); +} + +TARGET(ROT_THREE) { + PyObject *top = TOP(); + PyObject *second = SECOND(); + PyObject *third = THIRD(); + SET_TOP(second); + SET_SECOND(third); + SET_THIRD(top); + FAST_DISPATCH(); +} + +PREDICTED_WITH_ARG(UNPACK_SEQUENCE); +TARGET(UNPACK_SEQUENCE) { + PyObject *seq = POP(), *item, **items; + if (PyTuple_CheckExact(seq) && + PyTuple_GET_SIZE(seq) == oparg) { + items = ((PyTupleObject *)seq)->ob_item; + while (oparg--) { + item = items[oparg]; + Py_INCREF(item); + PUSH(item); + } + } else if (PyList_CheckExact(seq) && + PyList_GET_SIZE(seq) == oparg) { + items = ((PyListObject *)seq)->ob_item; + while (oparg--) { + item = items[oparg]; + Py_INCREF(item); + PUSH(item); + } + } else if (unpack_iterable(seq, oparg, -1, + stack_pointer + oparg)) { + STACKADJ(oparg); + } else { + /* unpack_iterable() raised an exception */ + Py_DECREF(seq); + goto error; + } + Py_DECREF(seq); + DISPATCH(); +} + +TARGET(UNPACK_EX) { + int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); + PyObject *seq = POP(); + + if (unpack_iterable(seq, oparg & 0xFF, oparg >> 8, + stack_pointer + totalargs)) { + stack_pointer += totalargs; + } else { + Py_DECREF(seq); + goto error; + } + Py_DECREF(seq); + DISPATCH(); +}