diff -r 1addc5d2c246 Doc/whatsnew/3.6.rst --- a/Doc/whatsnew/3.6.rst Tue Nov 22 23:04:39 2016 +0100 +++ b/Doc/whatsnew/3.6.rst Thu Nov 24 00:53:40 2016 +0100 @@ -2220,6 +2220,10 @@ Changes in the Python API Changes in the C API -------------------- +* The ``f_lasti`` field of the frames (:c:type:`PyFrameObject`) is now + initialized to ``-2`` instead of ``-1`` to work better with the new bytecode + format using 16-bit units. (:issue:`28782`). + * The :c:func:`PyMem_Malloc` allocator family now uses the :ref:`pymalloc allocator ` rather than the system :c:func:`malloc`. Applications calling :c:func:`PyMem_Malloc` without holding the GIL can now crash. Set the diff -r 1addc5d2c246 Objects/frameobject.c --- a/Objects/frameobject.c Tue Nov 22 23:04:39 2016 +0100 +++ b/Objects/frameobject.c Thu Nov 24 00:53:40 2016 +0100 @@ -14,11 +14,21 @@ static PyMemberDef frame_memberlist[] = {"f_code", T_OBJECT, OFF(f_code), READONLY}, {"f_builtins", T_OBJECT, OFF(f_builtins), READONLY}, {"f_globals", T_OBJECT, OFF(f_globals), READONLY}, - {"f_lasti", T_INT, OFF(f_lasti), READONLY}, {NULL} /* Sentinel */ }; static PyObject * +frame_getlasti(PyFrameObject *f, void *closure) +{ + int lasti = f->f_lasti; + if (lasti < 0) { + /* replace -2 with -1 for backward compatibility with Python 3.5 */ + lasti = -1; + } + return PyLong_FromLong(lasti); +} + +static PyObject * frame_getlocals(PyFrameObject *f, void *closure) { if (PyFrame_FastToLocalsWithError(f) < 0) @@ -354,6 +364,7 @@ frame_settrace(PyFrameObject *f, PyObjec static PyGetSetDef frame_getsetlist[] = { + {"f_lasti", (getter)frame_getlasti, NULL, NULL}, {"f_locals", (getter)frame_getlocals, NULL, NULL}, {"f_lineno", (getter)frame_getlineno, (setter)frame_setlineno, NULL}, @@ -721,7 +732,7 @@ PyFrame_New(PyThreadState *tstate, PyCod f->f_locals = locals; } - f->f_lasti = -1; + f->f_lasti = -(int)sizeof(_Py_CODEUNIT); f->f_lineno = code->co_firstlineno; f->f_iblock = 0; f->f_executing = 0; diff -r 1addc5d2c246 Objects/genobject.c --- a/Objects/genobject.c Tue Nov 22 23:04:39 2016 +0100 +++ b/Objects/genobject.c Thu Nov 24 00:53:40 2016 +0100 @@ -63,7 +63,7 @@ void issue a RuntimeWarning. */ if (gen->gi_code != NULL && ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE && - gen->gi_frame->f_lasti == -1) { + gen->gi_frame->f_lasti < 0) { if (!error_value) { PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "coroutine '%.50S' was never awaited", @@ -158,7 +158,7 @@ gen_send_ex(PyGenObject *gen, PyObject * return NULL; } - if (f->f_lasti == -1) { + if (f->f_lasti < 0) { if (arg && arg != Py_None) { char *msg = "can't send non-None value to a " "just-started generator"; @@ -463,6 +463,7 @@ static PyObject * assert(ret == yf); Py_DECREF(ret); /* Termination repetition of YIELD_FROM */ + assert(gen->gi_frame->f_lasti >= 0); gen->gi_frame->f_lasti += sizeof(_Py_CODEUNIT); if (_PyGen_FetchStopIterationValue(&val) == 0) { ret = gen_send_ex(gen, val, 0, 0); diff -r 1addc5d2c246 Python/ceval.c --- a/Python/ceval.c Tue Nov 22 23:04:39 2016 +0100 +++ b/Python/ceval.c Thu Nov 24 00:53:40 2016 +0100 @@ -1053,8 +1053,8 @@ PyObject* _Py_HOT_FUNCTION assert(_Py_IS_ALIGNED(PyBytes_AS_STRING(co->co_code), sizeof(_Py_CODEUNIT))); first_instr = (_Py_CODEUNIT *) PyBytes_AS_STRING(co->co_code); /* - f->f_lasti refers to the index of the last instruction, - unless it's -1 in which case next_instr should be first_instr. + f->f_lasti refers to the index of the last instruction, unless it's + negative in which case next_instr should be first_instr. YIELD_FROM sets f_lasti to itself, in order to repeatedly yield multiple values. @@ -1067,12 +1067,10 @@ PyObject* _Py_HOT_FUNCTION FOR_ITER is effectively a single opcode and f->f_lasti will point to the beginning of the combined pair.) */ - assert(f->f_lasti >= -1); + assert(f->f_lasti >= -(int)sizeof(_Py_CODEUNIT)); next_instr = first_instr; - if (f->f_lasti >= 0) { - assert(f->f_lasti % sizeof(_Py_CODEUNIT) == 0); - next_instr += f->f_lasti / sizeof(_Py_CODEUNIT) + 1; - } + assert((f->f_lasti + sizeof(_Py_CODEUNIT)) % sizeof(_Py_CODEUNIT) == 0); + next_instr += (f->f_lasti + sizeof(_Py_CODEUNIT)) / sizeof(_Py_CODEUNIT); stack_pointer = f->f_stacktop; assert(stack_pointer != NULL); f->f_stacktop = NULL; /* remains NULL unless yield suspends frame */ @@ -2049,6 +2047,7 @@ PyObject* _Py_HOT_FUNCTION f->f_stacktop = stack_pointer; why = WHY_YIELD; /* and repeat... */ + assert(f->f_lasti >= (int)sizeof(_Py_CODEUNIT)); f->f_lasti -= sizeof(_Py_CODEUNIT); goto fast_yield; }