diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-04-18 12:39:32 +0300 |
---|---|---|
committer | shadchin <shadchin@yandex-team.ru> | 2022-04-18 12:39:32 +0300 |
commit | d4be68e361f4258cf0848fc70018dfe37a2acc24 (patch) | |
tree | 153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Objects/codeobject.c | |
parent | 260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff) | |
download | ydb-d4be68e361f4258cf0848fc70018dfe37a2acc24.tar.gz |
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Objects/codeobject.c')
-rw-r--r-- | contrib/tools/python3/src/Objects/codeobject.c | 485 |
1 files changed, 360 insertions, 125 deletions
diff --git a/contrib/tools/python3/src/Objects/codeobject.c b/contrib/tools/python3/src/Objects/codeobject.c index cb4fb681243..c9f922707e9 100644 --- a/contrib/tools/python3/src/Objects/codeobject.c +++ b/contrib/tools/python3/src/Objects/codeobject.c @@ -4,10 +4,10 @@ #include "code.h" #include "opcode.h" #include "structmember.h" // PyMemberDef -#include "pycore_code.h" +#include "pycore_code.h" // _PyOpcache #include "pycore_interp.h" // PyInterpreterState.co_extra_freefuncs #include "pycore_pystate.h" // _PyInterpreterState_GET() -#include "pycore_tupleobject.h" +#include "pycore_tuple.h" // _PyTuple_ITEMS() #include "clinic/codeobject.c.h" /* Holder for co_extra information */ @@ -119,7 +119,7 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, int firstlineno, - PyObject *lnotab) + PyObject *linetable) { PyCodeObject *co; Py_ssize_t *cell2arg = NULL; @@ -137,7 +137,7 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, cellvars == NULL || !PyTuple_Check(cellvars) || name == NULL || !PyUnicode_Check(name) || filename == NULL || !PyUnicode_Check(filename) || - lnotab == NULL || !PyBytes_Check(lnotab)) { + linetable == NULL || !PyBytes_Check(linetable)) { PyErr_BadInternalCall(); return NULL; } @@ -213,7 +213,7 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, PyObject *arg = PyTuple_GET_ITEM(varnames, j); int cmp = PyUnicode_Compare(cell, arg); if (cmp == -1 && PyErr_Occurred()) { - PyMem_FREE(cell2arg); + PyMem_Free(cell2arg); return NULL; } if (cmp == 0) { @@ -224,14 +224,14 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, } } if (!used_cell2arg) { - PyMem_FREE(cell2arg); + PyMem_Free(cell2arg); cell2arg = NULL; } } co = PyObject_New(PyCodeObject, &PyCode_Type); if (co == NULL) { if (cell2arg) - PyMem_FREE(cell2arg); + PyMem_Free(cell2arg); return NULL; } co->co_argcount = argcount; @@ -258,8 +258,8 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, Py_INCREF(name); co->co_name = name; co->co_firstlineno = firstlineno; - Py_INCREF(lnotab); - co->co_lnotab = lnotab; + Py_INCREF(linetable); + co->co_linetable = linetable; co->co_zombieframe = NULL; co->co_weakreflist = NULL; co->co_extra = NULL; @@ -277,12 +277,12 @@ PyCode_New(int argcount, int kwonlyargcount, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, int firstlineno, - PyObject *lnotab) + PyObject *linetable) { return PyCode_NewWithPosOnlyArgs(argcount, 0, kwonlyargcount, nlocals, stacksize, flags, code, consts, names, varnames, freevars, cellvars, filename, - name, firstlineno, lnotab); + name, firstlineno, linetable); } int @@ -294,15 +294,15 @@ _PyCode_InitOpcache(PyCodeObject *co) return -1; } - _Py_CODEUNIT *opcodes = (_Py_CODEUNIT*)PyBytes_AS_STRING(co->co_code); + const _Py_CODEUNIT *opcodes = (_Py_CODEUNIT*)PyBytes_AS_STRING(co->co_code); Py_ssize_t opts = 0; for (Py_ssize_t i = 0; i < co_size;) { unsigned char opcode = _Py_OPCODE(opcodes[i]); i++; // 'i' is now aligned to (next_instr - first_instr) - // TODO: LOAD_METHOD, LOAD_ATTR - if (opcode == LOAD_GLOBAL) { + // TODO: LOAD_METHOD + if (opcode == LOAD_GLOBAL || opcode == LOAD_ATTR) { opts++; co->co_opcache_map[i] = (unsigned char)opts; if (opts > 254) { @@ -314,12 +314,12 @@ _PyCode_InitOpcache(PyCodeObject *co) if (opts) { co->co_opcache = (_PyOpcache *)PyMem_Calloc(opts, sizeof(_PyOpcache)); if (co->co_opcache == NULL) { - PyMem_FREE(co->co_opcache_map); + PyMem_Free(co->co_opcache_map); return -1; } } else { - PyMem_FREE(co->co_opcache_map); + PyMem_Free(co->co_opcache_map); co->co_opcache_map = NULL; co->co_opcache = NULL; } @@ -369,7 +369,7 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) filename_ob, /* filename */ funcname_ob, /* name */ firstlineno, /* firstlineno */ - emptystring /* lnotab */ + emptystring /* linetable */ ); failed: @@ -395,11 +395,89 @@ static PyMemberDef code_memberlist[] = { {"co_cellvars", T_OBJECT, OFF(co_cellvars), READONLY}, {"co_filename", T_OBJECT, OFF(co_filename), READONLY}, {"co_name", T_OBJECT, OFF(co_name), READONLY}, - {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY}, - {"co_lnotab", T_OBJECT, OFF(co_lnotab), READONLY}, + {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY}, + {"co_linetable", T_OBJECT, OFF(co_linetable), READONLY}, {NULL} /* Sentinel */ }; +static int +emit_pair(PyObject **bytes, int *offset, int a, int b) +{ + Py_ssize_t len = PyBytes_GET_SIZE(*bytes); + if (*offset + 2 >= len) { + if (_PyBytes_Resize(bytes, len * 2) < 0) + return 0; + } + unsigned char *lnotab = (unsigned char *) PyBytes_AS_STRING(*bytes); + lnotab += *offset; + *lnotab++ = a; + *lnotab++ = b; + *offset += 2; + return 1; +} + +static int +emit_delta(PyObject **bytes, int bdelta, int ldelta, int *offset) +{ + while (bdelta > 255) { + if (!emit_pair(bytes, offset, 255, 0)) { + return 0; + } + bdelta -= 255; + } + while (ldelta > 127) { + if (!emit_pair(bytes, offset, bdelta, 127)) { + return 0; + } + bdelta = 0; + ldelta -= 127; + } + while (ldelta < -128) { + if (!emit_pair(bytes, offset, bdelta, -128)) { + return 0; + } + bdelta = 0; + ldelta += 128; + } + return emit_pair(bytes, offset, bdelta, ldelta); +} + +static PyObject * +code_getlnotab(PyCodeObject *code, void *closure) +{ + PyCodeAddressRange bounds; + PyObject *bytes; + int table_offset = 0; + int code_offset = 0; + int line = code->co_firstlineno; + bytes = PyBytes_FromStringAndSize(NULL, 64); + if (bytes == NULL) { + return NULL; + } + _PyCode_InitAddressRange(code, &bounds); + while (PyLineTable_NextAddressRange(&bounds)) { + if (bounds.opaque.computed_line != line) { + int bdelta = bounds.ar_start - code_offset; + int ldelta = bounds.opaque.computed_line - line; + if (!emit_delta(&bytes, bdelta, ldelta, &table_offset)) { + Py_DECREF(bytes); + return NULL; + } + code_offset = bounds.ar_start; + line = bounds.opaque.computed_line; + } + } + _PyBytes_Resize(&bytes, table_offset); + return bytes; +} + + +static PyGetSetDef code_getsetlist[] = { + {"co_lnotab", (getter)code_getlnotab, NULL, NULL}, + {0} +}; + + /* Helper for code_new: return a shallow copy of a tuple that is guaranteed to contain exact strings, by converting string subclasses to exact strings and complaining if a non-string is found. */ @@ -442,46 +520,45 @@ validate_and_copy_tuple(PyObject *tup) return newtuple; } -PyDoc_STRVAR(code_doc, -"code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize,\n\ - flags, codestring, constants, names, varnames, filename, name,\n\ - firstlineno, lnotab[, freevars[, cellvars]])\n\ -\n\ -Create a code object. Not for the faint of heart."); +/*[clinic input] +@classmethod +code.__new__ as code_new + + argcount: int + posonlyargcount: int + kwonlyargcount: int + nlocals: int + stacksize: int + flags: int + codestring as code: object(subclass_of="&PyBytes_Type") + constants as consts: object(subclass_of="&PyTuple_Type") + names: object(subclass_of="&PyTuple_Type") + varnames: object(subclass_of="&PyTuple_Type") + filename: unicode + name: unicode + firstlineno: int + linetable: object(subclass_of="&PyBytes_Type") + freevars: object(subclass_of="&PyTuple_Type", c_default="NULL") = () + cellvars: object(subclass_of="&PyTuple_Type", c_default="NULL") = () + / + +Create a code object. Not for the faint of heart. +[clinic start generated code]*/ static PyObject * -code_new(PyTypeObject *type, PyObject *args, PyObject *kw) +code_new_impl(PyTypeObject *type, int argcount, int posonlyargcount, + int kwonlyargcount, int nlocals, int stacksize, int flags, + PyObject *code, PyObject *consts, PyObject *names, + PyObject *varnames, PyObject *filename, PyObject *name, + int firstlineno, PyObject *linetable, PyObject *freevars, + PyObject *cellvars) +/*[clinic end generated code: output=42c1839b082ba293 input=0ec80da632b99f57]*/ { - int argcount; - int posonlyargcount; - int kwonlyargcount; - int nlocals; - int stacksize; - int flags; PyObject *co = NULL; - PyObject *code; - PyObject *consts; - PyObject *names, *ournames = NULL; - PyObject *varnames, *ourvarnames = NULL; - PyObject *freevars = NULL, *ourfreevars = NULL; - PyObject *cellvars = NULL, *ourcellvars = NULL; - PyObject *filename; - PyObject *name; - int firstlineno; - PyObject *lnotab; - - if (!PyArg_ParseTuple(args, "iiiiiiSO!O!O!UUiS|O!O!:code", - &argcount, &posonlyargcount, &kwonlyargcount, - &nlocals, &stacksize, &flags, - &code, - &PyTuple_Type, &consts, - &PyTuple_Type, &names, - &PyTuple_Type, &varnames, - &filename, &name, - &firstlineno, &lnotab, - &PyTuple_Type, &freevars, - &PyTuple_Type, &cellvars)) - return NULL; + PyObject *ournames = NULL; + PyObject *ourvarnames = NULL; + PyObject *ourfreevars = NULL; + PyObject *ourcellvars = NULL; if (PySys_Audit("code.__new__", "OOOiiiiii", code, filename, name, argcount, posonlyargcount, @@ -541,7 +618,7 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) code, consts, ournames, ourvarnames, ourfreevars, ourcellvars, filename, - name, firstlineno, lnotab); + name, firstlineno, linetable); cleanup: Py_XDECREF(ournames); Py_XDECREF(ourvarnames); @@ -554,10 +631,10 @@ static void code_dealloc(PyCodeObject *co) { if (co->co_opcache != NULL) { - PyMem_FREE(co->co_opcache); + PyMem_Free(co->co_opcache); } if (co->co_opcache_map != NULL) { - PyMem_FREE(co->co_opcache_map); + PyMem_Free(co->co_opcache_map); } co->co_opcache_flag = 0; co->co_opcache_size = 0; @@ -585,14 +662,14 @@ code_dealloc(PyCodeObject *co) Py_XDECREF(co->co_cellvars); Py_XDECREF(co->co_filename); Py_XDECREF(co->co_name); - Py_XDECREF(co->co_lnotab); + Py_XDECREF(co->co_linetable); if (co->co_cell2arg != NULL) - PyMem_FREE(co->co_cell2arg); + PyMem_Free(co->co_cell2arg); if (co->co_zombieframe != NULL) PyObject_GC_Del(co->co_zombieframe); if (co->co_weakreflist != NULL) PyObject_ClearWeakRefs((PyObject*)co); - PyObject_DEL(co); + PyObject_Free(co); } static PyObject * @@ -637,7 +714,7 @@ code.replace co_cellvars: object(subclass_of="&PyTuple_Type", c_default="self->co_cellvars") = None co_filename: unicode(c_default="self->co_filename") = None co_name: unicode(c_default="self->co_name") = None - co_lnotab: PyBytesObject(c_default="(PyBytesObject *)self->co_lnotab") = None + co_linetable: PyBytesObject(c_default="(PyBytesObject *)self->co_linetable") = None Return a copy of the code object with new values for the specified fields. [clinic start generated code]*/ @@ -650,8 +727,8 @@ code_replace_impl(PyCodeObject *self, int co_argcount, PyObject *co_consts, PyObject *co_names, PyObject *co_varnames, PyObject *co_freevars, PyObject *co_cellvars, PyObject *co_filename, - PyObject *co_name, PyBytesObject *co_lnotab) -/*[clinic end generated code: output=25c8e303913bcace input=d9051bc8f24e6b28]*/ + PyObject *co_name, PyBytesObject *co_linetable) +/*[clinic end generated code: output=50d77e668d3b449b input=a5f997b173d7f636]*/ { #define CHECK_INT_ARG(ARG) \ if (ARG < 0) { \ @@ -681,7 +758,7 @@ code_replace_impl(PyCodeObject *self, int co_argcount, co_argcount, co_posonlyargcount, co_kwonlyargcount, co_nlocals, co_stacksize, co_flags, (PyObject*)co_code, co_consts, co_names, co_varnames, co_freevars, co_cellvars, co_filename, co_name, - co_firstlineno, (PyObject*)co_lnotab); + co_firstlineno, (PyObject*)co_linetable); } static PyObject * @@ -934,10 +1011,188 @@ code_hash(PyCodeObject *co) return h; } +typedef struct { + PyObject_HEAD + PyCodeObject *li_code; + PyCodeAddressRange li_line; + char *li_end; +} lineiterator; + + +static void +lineiter_dealloc(lineiterator *li) +{ + Py_DECREF(li->li_code); + Py_TYPE(li)->tp_free(li); +} + +static PyObject * +lineiter_next(lineiterator *li) +{ + PyCodeAddressRange *bounds = &li->li_line; + if (!PyLineTable_NextAddressRange(bounds)) { + return NULL; + } + PyObject *start = NULL; + PyObject *end = NULL; + PyObject *line = NULL; + PyObject *result = PyTuple_New(3); + start = PyLong_FromLong(bounds->ar_start); + end = PyLong_FromLong(bounds->ar_end); + if (bounds->ar_line < 0) { + Py_INCREF(Py_None); + line = Py_None; + } + else { + line = PyLong_FromLong(bounds->ar_line); + } + if (result == NULL || start == NULL || end == NULL || line == NULL) { + goto error; + } + PyTuple_SET_ITEM(result, 0, start); + PyTuple_SET_ITEM(result, 1, end); + PyTuple_SET_ITEM(result, 2, line); + return result; +error: + Py_XDECREF(start); + Py_XDECREF(end); + Py_XDECREF(line); + Py_XDECREF(result); + return result; +} + +static PyTypeObject LineIterator = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "line_iterator", /* tp_name */ + sizeof(lineiterator), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)lineiter_dealloc, /* tp_dealloc */ + 0, /* tp_vectorcall_offset */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_as_async */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)lineiter_next, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + PyObject_Del, /* tp_free */ +}; + +static PyObject * +code_linesiterator(PyCodeObject *code, PyObject *Py_UNUSED(args)) +{ + lineiterator *li = (lineiterator *)PyType_GenericAlloc(&LineIterator, 0); + if (li == NULL) { + return NULL; + } + Py_INCREF(code); + li->li_code = code; + _PyCode_InitAddressRange(code, &li->li_line); + return (PyObject *)li; +} + +static void +retreat(PyCodeAddressRange *bounds) +{ + int ldelta = ((signed char *)bounds->opaque.lo_next)[-1]; + if (ldelta == -128) { + ldelta = 0; + } + bounds->opaque.computed_line -= ldelta; + bounds->opaque.lo_next -= 2; + bounds->ar_end = bounds->ar_start; + bounds->ar_start -= ((unsigned char *)bounds->opaque.lo_next)[-2]; + ldelta = ((signed char *)bounds->opaque.lo_next)[-1]; + if (ldelta == -128) { + bounds->ar_line = -1; + } + else { + bounds->ar_line = bounds->opaque.computed_line; + } +} + +static void +advance(PyCodeAddressRange *bounds) +{ + bounds->ar_start = bounds->ar_end; + int delta = ((unsigned char *)bounds->opaque.lo_next)[0]; + bounds->ar_end += delta; + int ldelta = ((signed char *)bounds->opaque.lo_next)[1]; + bounds->opaque.lo_next += 2; + if (ldelta == -128) { + bounds->ar_line = -1; + } + else { + bounds->opaque.computed_line += ldelta; + bounds->ar_line = bounds->opaque.computed_line; + } +} + +static inline int +at_end(PyCodeAddressRange *bounds) { + return bounds->opaque.lo_next >= bounds->opaque.limit; +} + +int +PyLineTable_PreviousAddressRange(PyCodeAddressRange *range) +{ + if (range->ar_start <= 0) { + return 0; + } + retreat(range); + while (range->ar_start == range->ar_end) { + assert(range->ar_start > 0); + retreat(range); + } + return 1; +} + +int +PyLineTable_NextAddressRange(PyCodeAddressRange *range) +{ + if (at_end(range)) { + return 0; + } + advance(range); + while (range->ar_start == range->ar_end && !at_end(range)) { + assert(!at_end(range)); + advance(range); + } + return 1; +} + + /* XXX code objects need to participate in GC? */ static struct PyMethodDef code_methods[] = { {"__sizeof__", (PyCFunction)code_sizeof, METH_NOARGS}, + {"co_lines", (PyCFunction)code_linesiterator, METH_NOARGS}, CODE_REPLACE_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -963,7 +1218,7 @@ PyTypeObject PyCode_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ - code_doc, /* tp_doc */ + code_new__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ code_richcompare, /* tp_richcompare */ @@ -972,7 +1227,7 @@ PyTypeObject PyCode_Type = { 0, /* tp_iternext */ code_methods, /* tp_methods */ code_memberlist, /* tp_members */ - 0, /* tp_getset */ + code_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ @@ -983,78 +1238,58 @@ PyTypeObject PyCode_Type = { code_new, /* tp_new */ }; -/* Use co_lnotab to compute the line number from a bytecode index, addrq. See +/* Use co_linetable to compute the line number from a bytecode index, addrq. See lnotab_notes.txt for the details of the lnotab representation. */ int PyCode_Addr2Line(PyCodeObject *co, int addrq) { - Py_ssize_t size = PyBytes_Size(co->co_lnotab) / 2; - unsigned char *p = (unsigned char*)PyBytes_AsString(co->co_lnotab); - int line = co->co_firstlineno; - int addr = 0; - while (--size >= 0) { - addr += *p++; - if (addr > addrq) - break; - line += (signed char)*p; - p++; - } - return line; + if (addrq < 0) { + return co->co_firstlineno; + } + assert(addrq >= 0 && addrq < PyBytes_GET_SIZE(co->co_code)); + PyCodeAddressRange bounds; + _PyCode_InitAddressRange(co, &bounds); + return _PyCode_CheckLineNumber(addrq, &bounds); +} + +void +PyLineTable_InitAddressRange(const char *linetable, Py_ssize_t length, int firstlineno, PyCodeAddressRange *range) +{ + range->opaque.lo_next = linetable; + range->opaque.limit = range->opaque.lo_next + length; + range->ar_start = -1; + range->ar_end = 0; + range->opaque.computed_line = firstlineno; + range->ar_line = -1; +} + +int +_PyCode_InitAddressRange(PyCodeObject* co, PyCodeAddressRange *bounds) +{ + const char *linetable = PyBytes_AS_STRING(co->co_linetable); + Py_ssize_t length = PyBytes_GET_SIZE(co->co_linetable); + PyLineTable_InitAddressRange(linetable, length, co->co_firstlineno, bounds); + return bounds->ar_line; } /* Update *bounds to describe the first and one-past-the-last instructions in - the same line as lasti. Return the number of that line. */ + the same line as lasti. Return the number of that line, or -1 if lasti is out of bounds. */ int -_PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) +_PyCode_CheckLineNumber(int lasti, PyCodeAddressRange *bounds) { - Py_ssize_t size; - int addr, line; - unsigned char* p; - - p = (unsigned char*)PyBytes_AS_STRING(co->co_lnotab); - size = PyBytes_GET_SIZE(co->co_lnotab) / 2; - - addr = 0; - line = co->co_firstlineno; - assert(line > 0); - - /* possible optimization: if f->f_lasti == instr_ub - (likely to be a common case) then we already know - instr_lb -- if we stored the matching value of p - somewhere we could skip the first while loop. */ - - /* See lnotab_notes.txt for the description of - co_lnotab. A point to remember: increments to p - come in (addr, line) pairs. */ - - bounds->ap_lower = 0; - while (size > 0) { - if (addr + *p > lasti) - break; - addr += *p++; - if ((signed char)*p) - bounds->ap_lower = addr; - line += (signed char)*p; - p++; - --size; - } - - if (size > 0) { - while (--size >= 0) { - addr += *p++; - if ((signed char)*p) - break; - p++; + while (bounds->ar_end <= lasti) { + if (!PyLineTable_NextAddressRange(bounds)) { + return -1; } - bounds->ap_upper = addr; } - else { - bounds->ap_upper = INT_MAX; + while (bounds->ar_start > lasti) { + if (!PyLineTable_PreviousAddressRange(bounds)) { + return -1; + } } - - return line; + return bounds->ar_line; } |