diff options
Diffstat (limited to 'Objects/codeobject.c')
-rw-r--r-- | Objects/codeobject.c | 688 |
1 files changed, 179 insertions, 509 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c index f0b62ec..d50e4c6 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -1,38 +1,28 @@ -#include <stdbool.h> - #include "Python.h" #include "code.h" -#include "opcode.h" #include "structmember.h" -#include "pycore_code.h" -#include "pycore_pystate.h" -#include "pycore_tupleobject.h" -#include "clinic/codeobject.c.h" - -/* Holder for co_extra information */ -typedef struct { - Py_ssize_t ce_size; - void *ce_extras[1]; -} _PyCodeObjectExtra; - -/*[clinic input] -class code "PyCodeObject *" "&PyCode_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=78aa5d576683bb4b]*/ - -/* all_name_chars(s): true iff s matches [a-zA-Z0-9_]* */ + +#define NAME_CHARS \ + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" + +/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */ + static int all_name_chars(PyObject *o) { + static char ok_name_char[256]; + static const unsigned char *name_chars = (unsigned char *)NAME_CHARS; const unsigned char *s, *e; - if (!PyUnicode_IS_ASCII(o)) - return 0; - - s = PyUnicode_1BYTE_DATA(o); - e = s + PyUnicode_GET_LENGTH(o); - for (; s != e; s++) { - if (!Py_ISALNUM(*s) && *s != '_') + if (ok_name_char[*name_chars] == 0) { + const unsigned char *p; + for (p = name_chars; *p; p++) + ok_name_char[*p] = 1; + } + s = (unsigned char *)PyString_AS_STRING(o); + e = s + PyString_GET_SIZE(o); + while (s != e) { + if (ok_name_char[*s++] == 0) return 0; } return 1; @@ -45,10 +35,10 @@ intern_strings(PyObject *tuple) for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) { PyObject *v = PyTuple_GET_ITEM(tuple, i); - if (v == NULL || !PyUnicode_CheckExact(v)) { + if (v == NULL || !PyString_CheckExact(v)) { Py_FatalError("non-string found in code slot"); } - PyUnicode_InternInPlace(&_PyTuple_ITEMS(tuple)[i]); + PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i)); } } @@ -61,14 +51,10 @@ intern_string_constants(PyObject *tuple) for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) { PyObject *v = PyTuple_GET_ITEM(tuple, i); - if (PyUnicode_CheckExact(v)) { - if (PyUnicode_READY(v) == -1) { - PyErr_Clear(); - continue; - } + if (PyString_CheckExact(v)) { if (all_name_chars(v)) { PyObject *w = v; - PyUnicode_InternInPlace(&v); + PyString_InternInPlace(&v); if (w != v) { PyTuple_SET_ITEM(tuple, i, v); modified = 1; @@ -102,204 +88,67 @@ intern_string_constants(PyObject *tuple) return modified; } + PyCodeObject * -PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, - int nlocals, int stacksize, int flags, - PyObject *code, PyObject *consts, PyObject *names, - PyObject *varnames, PyObject *freevars, PyObject *cellvars, - PyObject *filename, PyObject *name, int firstlineno, - PyObject *lnotab) +PyCode_New(int argcount, int nlocals, int stacksize, int flags, + PyObject *code, PyObject *consts, PyObject *names, + PyObject *varnames, PyObject *freevars, PyObject *cellvars, + PyObject *filename, PyObject *name, int firstlineno, + PyObject *lnotab) { PyCodeObject *co; - Py_ssize_t *cell2arg = NULL; - Py_ssize_t i, n_cellvars, n_varnames, total_args; - /* Check argument types */ - if (argcount < posonlyargcount || posonlyargcount < 0 || - kwonlyargcount < 0 || nlocals < 0 || - stacksize < 0 || flags < 0 || - code == NULL || !PyBytes_Check(code) || + if (argcount < 0 || nlocals < 0 || + code == NULL || consts == NULL || !PyTuple_Check(consts) || names == NULL || !PyTuple_Check(names) || varnames == NULL || !PyTuple_Check(varnames) || freevars == NULL || !PyTuple_Check(freevars) || cellvars == NULL || !PyTuple_Check(cellvars) || - name == NULL || !PyUnicode_Check(name) || - filename == NULL || !PyUnicode_Check(filename) || - lnotab == NULL || !PyBytes_Check(lnotab)) { + name == NULL || !PyString_Check(name) || + filename == NULL || !PyString_Check(filename) || + lnotab == NULL || !PyString_Check(lnotab) || + !PyObject_CheckReadBuffer(code)) { PyErr_BadInternalCall(); return NULL; } - - /* Ensure that strings are ready Unicode string */ - if (PyUnicode_READY(name) < 0) { - return NULL; - } - if (PyUnicode_READY(filename) < 0) { - return NULL; - } - intern_strings(names); intern_strings(varnames); intern_strings(freevars); intern_strings(cellvars); intern_string_constants(consts); - - /* Check for any inner or outer closure references */ - n_cellvars = PyTuple_GET_SIZE(cellvars); - if (!n_cellvars && !PyTuple_GET_SIZE(freevars)) { - flags |= CO_NOFREE; - } else { - flags &= ~CO_NOFREE; - } - - n_varnames = PyTuple_GET_SIZE(varnames); - if (argcount <= n_varnames && kwonlyargcount <= n_varnames) { - /* Never overflows. */ - total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount + - ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0); - } - else { - total_args = n_varnames + 1; - } - if (total_args > n_varnames) { - PyErr_SetString(PyExc_ValueError, "code: varnames is too small"); - return NULL; - } - - /* Create mapping between cells and arguments if needed. */ - if (n_cellvars) { - bool used_cell2arg = false; - cell2arg = PyMem_NEW(Py_ssize_t, n_cellvars); - if (cell2arg == NULL) { - PyErr_NoMemory(); - return NULL; - } - /* Find cells which are also arguments. */ - for (i = 0; i < n_cellvars; i++) { - Py_ssize_t j; - PyObject *cell = PyTuple_GET_ITEM(cellvars, i); - cell2arg[i] = CO_CELL_NOT_AN_ARG; - for (j = 0; j < total_args; j++) { - PyObject *arg = PyTuple_GET_ITEM(varnames, j); - int cmp = PyUnicode_Compare(cell, arg); - if (cmp == -1 && PyErr_Occurred()) { - PyMem_FREE(cell2arg); - return NULL; - } - if (cmp == 0) { - cell2arg[i] = j; - used_cell2arg = true; - break; - } - } - } - if (!used_cell2arg) { - PyMem_FREE(cell2arg); - cell2arg = NULL; - } - } co = PyObject_NEW(PyCodeObject, &PyCode_Type); - if (co == NULL) { - if (cell2arg) - PyMem_FREE(cell2arg); - return NULL; + if (co != NULL) { + co->co_argcount = argcount; + co->co_nlocals = nlocals; + co->co_stacksize = stacksize; + co->co_flags = flags; + Py_INCREF(code); + co->co_code = code; + Py_INCREF(consts); + co->co_consts = consts; + Py_INCREF(names); + co->co_names = names; + Py_INCREF(varnames); + co->co_varnames = varnames; + Py_INCREF(freevars); + co->co_freevars = freevars; + Py_INCREF(cellvars); + co->co_cellvars = cellvars; + Py_INCREF(filename); + co->co_filename = filename; + Py_INCREF(name); + co->co_name = name; + co->co_firstlineno = firstlineno; + Py_INCREF(lnotab); + co->co_lnotab = lnotab; + co->co_zombieframe = NULL; + co->co_weakreflist = NULL; } - co->co_argcount = argcount; - co->co_posonlyargcount = posonlyargcount; - co->co_kwonlyargcount = kwonlyargcount; - co->co_nlocals = nlocals; - co->co_stacksize = stacksize; - co->co_flags = flags; - Py_INCREF(code); - co->co_code = code; - Py_INCREF(consts); - co->co_consts = consts; - Py_INCREF(names); - co->co_names = names; - Py_INCREF(varnames); - co->co_varnames = varnames; - Py_INCREF(freevars); - co->co_freevars = freevars; - Py_INCREF(cellvars); - co->co_cellvars = cellvars; - co->co_cell2arg = cell2arg; - Py_INCREF(filename); - co->co_filename = filename; - Py_INCREF(name); - co->co_name = name; - co->co_firstlineno = firstlineno; - Py_INCREF(lnotab); - co->co_lnotab = lnotab; - co->co_zombieframe = NULL; - co->co_weakreflist = NULL; - co->co_extra = NULL; - - co->co_opcache_map = NULL; - co->co_opcache = NULL; - co->co_opcache_flag = 0; - co->co_opcache_size = 0; return co; } PyCodeObject * -PyCode_New(int argcount, int kwonlyargcount, - int nlocals, int stacksize, int flags, - PyObject *code, PyObject *consts, PyObject *names, - PyObject *varnames, PyObject *freevars, PyObject *cellvars, - PyObject *filename, PyObject *name, int firstlineno, - PyObject *lnotab) -{ - return PyCode_NewWithPosOnlyArgs(argcount, 0, kwonlyargcount, nlocals, - stacksize, flags, code, consts, names, - varnames, freevars, cellvars, filename, - name, firstlineno, lnotab); -} - -int -_PyCode_InitOpcache(PyCodeObject *co) -{ - Py_ssize_t co_size = PyBytes_Size(co->co_code) / sizeof(_Py_CODEUNIT); - co->co_opcache_map = (unsigned char *)PyMem_Calloc(co_size, 1); - if (co->co_opcache_map == NULL) { - return -1; - } - - _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) { - opts++; - co->co_opcache_map[i] = (unsigned char)opts; - if (opts > 254) { - break; - } - } - } - - if (opts) { - co->co_opcache = (_PyOpcache *)PyMem_Calloc(opts, sizeof(_PyOpcache)); - if (co->co_opcache == NULL) { - PyMem_FREE(co->co_opcache_map); - return -1; - } - } - else { - PyMem_FREE(co->co_opcache_map); - co->co_opcache_map = NULL; - co->co_opcache = NULL; - } - - co->co_opcache_size = (unsigned char)opts; - return 0; -} - -PyCodeObject * PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) { static PyObject *emptystring = NULL; @@ -308,7 +157,7 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) PyObject *funcname_ob = NULL; PyCodeObject *result = NULL; if (emptystring == NULL) { - emptystring = PyBytes_FromString(""); + emptystring = PyString_FromString(""); if (emptystring == NULL) goto failed; } @@ -317,17 +166,14 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) if (nulltuple == NULL) goto failed; } - funcname_ob = PyUnicode_FromString(funcname); + funcname_ob = PyString_FromString(funcname); if (funcname_ob == NULL) goto failed; - filename_ob = PyUnicode_DecodeFSDefault(filename); + filename_ob = PyString_FromString(filename); if (filename_ob == NULL) goto failed; - result = PyCode_NewWithPosOnlyArgs( - 0, /* argcount */ - 0, /* posonlyargcount */ - 0, /* kwonlyargcount */ + result = PyCode_New(0, /* argcount */ 0, /* nlocals */ 0, /* stacksize */ 0, /* flags */ @@ -352,22 +198,20 @@ failed: #define OFF(x) offsetof(PyCodeObject, x) static PyMemberDef code_memberlist[] = { - {"co_argcount", T_INT, OFF(co_argcount), READONLY}, - {"co_posonlyargcount", T_INT, OFF(co_posonlyargcount), READONLY}, - {"co_kwonlyargcount", T_INT, OFF(co_kwonlyargcount), READONLY}, - {"co_nlocals", T_INT, OFF(co_nlocals), READONLY}, - {"co_stacksize",T_INT, OFF(co_stacksize), READONLY}, - {"co_flags", T_INT, OFF(co_flags), READONLY}, - {"co_code", T_OBJECT, OFF(co_code), READONLY}, - {"co_consts", T_OBJECT, OFF(co_consts), READONLY}, - {"co_names", T_OBJECT, OFF(co_names), READONLY}, - {"co_varnames", T_OBJECT, OFF(co_varnames), READONLY}, - {"co_freevars", T_OBJECT, OFF(co_freevars), READONLY}, - {"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_argcount", T_INT, OFF(co_argcount), READONLY}, + {"co_nlocals", T_INT, OFF(co_nlocals), READONLY}, + {"co_stacksize",T_INT, OFF(co_stacksize), READONLY}, + {"co_flags", T_INT, OFF(co_flags), READONLY}, + {"co_code", T_OBJECT, OFF(co_code), READONLY}, + {"co_consts", T_OBJECT, OFF(co_consts), READONLY}, + {"co_names", T_OBJECT, OFF(co_names), READONLY}, + {"co_varnames", T_OBJECT, OFF(co_varnames), READONLY}, + {"co_freevars", T_OBJECT, OFF(co_freevars), READONLY}, + {"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}, {NULL} /* Sentinel */ }; @@ -388,10 +232,10 @@ validate_and_copy_tuple(PyObject *tup) for (i = 0; i < len; i++) { item = PyTuple_GET_ITEM(tup, i); - if (PyUnicode_CheckExact(item)) { + if (PyString_CheckExact(item)) { Py_INCREF(item); } - else if (!PyUnicode_Check(item)) { + else if (!PyString_Check(item)) { PyErr_Format( PyExc_TypeError, "name tuples must contain only " @@ -401,7 +245,9 @@ validate_and_copy_tuple(PyObject *tup) return NULL; } else { - item = _PyUnicode_Copy(item); + item = PyString_FromStringAndSize( + PyString_AS_STRING(item), + PyString_GET_SIZE(item)); if (item == NULL) { Py_DECREF(newtuple); return NULL; @@ -414,9 +260,8 @@ validate_and_copy_tuple(PyObject *tup) } PyDoc_STRVAR(code_doc, -"code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize,\n\ - flags, codestring, constants, names, varnames, filename, name,\n\ - firstlineno, lnotab[, freevars[, cellvars]])\n\ +"code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\ + varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\ \n\ Create a code object. Not for the faint of heart."); @@ -424,8 +269,6 @@ static PyObject * code_new(PyTypeObject *type, PyObject *args, PyObject *kw) { int argcount; - int posonlyargcount; - int kwonlyargcount; int nlocals; int stacksize; int flags; @@ -441,9 +284,8 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) int firstlineno; PyObject *lnotab; - if (!PyArg_ParseTuple(args, "iiiiiiSO!O!O!UUiS|O!O!:code", - &argcount, &posonlyargcount, &kwonlyargcount, - &nlocals, &stacksize, &flags, + if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code", + &argcount, &nlocals, &stacksize, &flags, &code, &PyTuple_Type, &consts, &PyTuple_Type, &names, @@ -454,12 +296,6 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) &PyTuple_Type, &cellvars)) return NULL; - if (PySys_Audit("code.__new__", "OOOiiiiii", - code, filename, name, argcount, posonlyargcount, - kwonlyargcount, nlocals, stacksize, flags) < 0) { - goto cleanup; - } - if (argcount < 0) { PyErr_SetString( PyExc_ValueError, @@ -467,19 +303,6 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) goto cleanup; } - if (posonlyargcount < 0) { - PyErr_SetString( - PyExc_ValueError, - "code: posonlyargcount must not be negative"); - goto cleanup; - } - - if (kwonlyargcount < 0) { - PyErr_SetString( - PyExc_ValueError, - "code: kwonlyargcount must not be negative"); - goto cleanup; - } if (nlocals < 0) { PyErr_SetString( PyExc_ValueError, @@ -506,14 +329,11 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) if (ourcellvars == NULL) goto cleanup; - co = (PyObject *)PyCode_NewWithPosOnlyArgs(argcount, posonlyargcount, - kwonlyargcount, - nlocals, stacksize, flags, - code, consts, ournames, - ourvarnames, ourfreevars, - ourcellvars, filename, - name, firstlineno, lnotab); - cleanup: + co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags, + code, consts, ournames, ourvarnames, + ourfreevars, ourcellvars, filename, + name, firstlineno, lnotab); + cleanup: Py_XDECREF(ournames); Py_XDECREF(ourvarnames); Py_XDECREF(ourfreevars); @@ -524,30 +344,6 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) static void code_dealloc(PyCodeObject *co) { - if (co->co_opcache != NULL) { - PyMem_FREE(co->co_opcache); - } - if (co->co_opcache_map != NULL) { - PyMem_FREE(co->co_opcache_map); - } - co->co_opcache_flag = 0; - co->co_opcache_size = 0; - - if (co->co_extra != NULL) { - PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - _PyCodeObjectExtra *co_extra = co->co_extra; - - for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) { - freefunc free_extra = interp->co_extra_freefuncs[i]; - - if (free_extra != NULL) { - free_extra(co_extra->ce_extras[i]); - } - } - - PyMem_Free(co_extra); - } - Py_XDECREF(co->co_code); Py_XDECREF(co->co_consts); Py_XDECREF(co->co_names); @@ -557,8 +353,6 @@ code_dealloc(PyCodeObject *co) Py_XDECREF(co->co_filename); Py_XDECREF(co->co_name); Py_XDECREF(co->co_lnotab); - if (co->co_cell2arg != NULL) - PyMem_FREE(co->co_cell2arg); if (co->co_zombieframe != NULL) PyObject_GC_Del(co->co_zombieframe); if (co->co_weakreflist != NULL) @@ -567,111 +361,59 @@ code_dealloc(PyCodeObject *co) } static PyObject * -code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args)) -{ - Py_ssize_t res = _PyObject_SIZE(Py_TYPE(co)); - _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) co->co_extra; - - if (co->co_cell2arg != NULL && co->co_cellvars != NULL) { - res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(Py_ssize_t); - } - if (co_extra != NULL) { - res += sizeof(_PyCodeObjectExtra) + - (co_extra->ce_size-1) * sizeof(co_extra->ce_extras[0]); - } - if (co->co_opcache != NULL) { - assert(co->co_opcache_map != NULL); - // co_opcache_map - res += PyBytes_GET_SIZE(co->co_code) / sizeof(_Py_CODEUNIT); - // co_opcache - res += co->co_opcache_size * sizeof(_PyOpcache); - } - return PyLong_FromSsize_t(res); -} - -/*[clinic input] -code.replace - - * - co_argcount: int(c_default="self->co_argcount") = -1 - co_posonlyargcount: int(c_default="self->co_posonlyargcount") = -1 - co_kwonlyargcount: int(c_default="self->co_kwonlyargcount") = -1 - co_nlocals: int(c_default="self->co_nlocals") = -1 - co_stacksize: int(c_default="self->co_stacksize") = -1 - co_flags: int(c_default="self->co_flags") = -1 - co_firstlineno: int(c_default="self->co_firstlineno") = -1 - co_code: PyBytesObject(c_default="(PyBytesObject *)self->co_code") = None - co_consts: object(subclass_of="&PyTuple_Type", c_default="self->co_consts") = None - co_names: object(subclass_of="&PyTuple_Type", c_default="self->co_names") = None - co_varnames: object(subclass_of="&PyTuple_Type", c_default="self->co_varnames") = None - co_freevars: object(subclass_of="&PyTuple_Type", c_default="self->co_freevars") = None - 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 - -Return a new code object with new specified fields. -[clinic start generated code]*/ - -static PyObject * -code_replace_impl(PyCodeObject *self, int co_argcount, - int co_posonlyargcount, int co_kwonlyargcount, - int co_nlocals, int co_stacksize, int co_flags, - int co_firstlineno, PyBytesObject *co_code, - 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=77189e46579ec426]*/ +code_repr(PyCodeObject *co) { -#define CHECK_INT_ARG(ARG) \ - if (ARG < 0) { \ - PyErr_SetString(PyExc_ValueError, \ - #ARG " must be a positive integer"); \ - return NULL; \ - } - - CHECK_INT_ARG(co_argcount); - CHECK_INT_ARG(co_posonlyargcount); - CHECK_INT_ARG(co_kwonlyargcount); - CHECK_INT_ARG(co_nlocals); - CHECK_INT_ARG(co_stacksize); - CHECK_INT_ARG(co_flags); - CHECK_INT_ARG(co_firstlineno); - -#undef CHECK_INT_ARG - - if (PySys_Audit("code.__new__", "OOOiiiiii", - co_code, co_filename, co_name, co_argcount, - co_posonlyargcount, co_kwonlyargcount, co_nlocals, - co_stacksize, co_flags) < 0) { - return NULL; - } + char buf[500]; + int lineno = -1; + char *filename = "???"; + char *name = "???"; - return (PyObject *)PyCode_NewWithPosOnlyArgs( - 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); + if (co->co_firstlineno != 0) + lineno = co->co_firstlineno; + if (co->co_filename && PyString_Check(co->co_filename)) + filename = PyString_AS_STRING(co->co_filename); + if (co->co_name && PyString_Check(co->co_name)) + name = PyString_AS_STRING(co->co_name); + PyOS_snprintf(buf, sizeof(buf), + "<code object %.100s at %p, file \"%.300s\", line %d>", + name, co, filename, lineno); + return PyString_FromString(buf); } -static PyObject * -code_repr(PyCodeObject *co) +static int +code_compare(PyCodeObject *co, PyCodeObject *cp) { - int lineno; - if (co->co_firstlineno != 0) - lineno = co->co_firstlineno; + int cmp; + cmp = PyObject_Compare(co->co_name, cp->co_name); + if (cmp) return cmp; + cmp = co->co_argcount - cp->co_argcount; + if (cmp) goto normalize; + cmp = co->co_nlocals - cp->co_nlocals; + if (cmp) goto normalize; + cmp = co->co_flags - cp->co_flags; + if (cmp) goto normalize; + cmp = co->co_firstlineno - cp->co_firstlineno; + if (cmp) goto normalize; + cmp = PyObject_Compare(co->co_code, cp->co_code); + if (cmp) return cmp; + cmp = PyObject_Compare(co->co_consts, cp->co_consts); + if (cmp) return cmp; + cmp = PyObject_Compare(co->co_names, cp->co_names); + if (cmp) return cmp; + cmp = PyObject_Compare(co->co_varnames, cp->co_varnames); + if (cmp) return cmp; + cmp = PyObject_Compare(co->co_freevars, cp->co_freevars); + if (cmp) return cmp; + cmp = PyObject_Compare(co->co_cellvars, cp->co_cellvars); + return cmp; + + normalize: + if (cmp > 0) + return 1; + else if (cmp < 0) + return -1; else - lineno = -1; - if (co->co_filename && PyUnicode_Check(co->co_filename)) { - return PyUnicode_FromFormat( - "<code object %U at %p, file \"%U\", line %d>", - co->co_name, co, co->co_filename, lineno); - } else { - return PyUnicode_FromFormat( - "<code object %U at %p, file ???, line %d>", - co->co_name, co, lineno); - } + return 0; } PyObject* @@ -679,21 +421,16 @@ _PyCode_ConstantKey(PyObject *op) { PyObject *key; - /* Py_None and Py_Ellipsis are singletons. */ - if (op == Py_None || op == Py_Ellipsis - || PyLong_CheckExact(op) + /* Py_None is a singleton */ + if (op == Py_None + || _PyAnyInt_CheckExact(op) + || PyBool_Check(op) + || PyBytes_CheckExact(op) +#ifdef Py_USING_UNICODE || PyUnicode_CheckExact(op) +#endif /* code_richcompare() uses _PyCode_ConstantKey() internally */ - || PyCode_Check(op)) - { - /* Objects of these types are always different from object of other - * type and from tuples. */ - Py_INCREF(op); - key = op; - } - else if (PyBool_Check(op) || PyBytes_CheckExact(op)) { - /* Make booleans different from integers 0 and 1. - * Avoid BytesWarning from comparing bytes with strings. */ + || PyCode_Check(op)) { key = PyTuple_Pack(2, Py_TYPE(op), op); } else if (PyFloat_CheckExact(op)) { @@ -706,6 +443,7 @@ _PyCode_ConstantKey(PyObject *op) else key = PyTuple_Pack(2, Py_TYPE(op), op); } +#ifndef WITHOUT_COMPLEX else if (PyComplex_CheckExact(op)) { Py_complex z; int real_negzero, imag_negzero; @@ -731,6 +469,7 @@ _PyCode_ConstantKey(PyObject *op) key = PyTuple_Pack(2, Py_TYPE(op), op); } } +#endif else if (PyTuple_CheckExact(op)) { Py_ssize_t i, len; PyObject *tuple; @@ -753,13 +492,13 @@ _PyCode_ConstantKey(PyObject *op) PyTuple_SET_ITEM(tuple, i, item_key); } - key = PyTuple_Pack(2, tuple, op); + key = PyTuple_Pack(3, Py_TYPE(op), op, tuple); Py_DECREF(tuple); } else if (PyFrozenSet_CheckExact(op)) { Py_ssize_t pos = 0; PyObject *item; - Py_hash_t hash; + long hash; Py_ssize_t i, len; PyObject *tuple, *set; @@ -787,7 +526,7 @@ _PyCode_ConstantKey(PyObject *op) if (set == NULL) return NULL; - key = PyTuple_Pack(2, set, op); + key = PyTuple_Pack(3, Py_TYPE(op), op, set); Py_DECREF(set); return key; } @@ -798,7 +537,7 @@ _PyCode_ConstantKey(PyObject *op) if (obj_id == NULL) return NULL; - key = PyTuple_Pack(2, obj_id, op); + key = PyTuple_Pack(3, Py_TYPE(op), op, obj_id); Py_DECREF(obj_id); } return key; @@ -815,20 +554,25 @@ code_richcompare(PyObject *self, PyObject *other, int op) if ((op != Py_EQ && op != Py_NE) || !PyCode_Check(self) || !PyCode_Check(other)) { - Py_RETURN_NOTIMPLEMENTED; + + /* Py3K warning if types are not equal and comparison + isn't == or != */ + if (PyErr_WarnPy3k("code inequality comparisons not supported " + "in 3.x", 1) < 0) { + return NULL; + } + + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; } co = (PyCodeObject *)self; cp = (PyCodeObject *)other; eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ); - if (!eq) goto unequal; + if (eq <= 0) goto unequal; eq = co->co_argcount == cp->co_argcount; if (!eq) goto unequal; - eq = co->co_posonlyargcount == cp->co_posonlyargcount; - if (!eq) goto unequal; - eq = co->co_kwonlyargcount == cp->co_kwonlyargcount; - if (!eq) goto unequal; eq = co->co_nlocals == cp->co_nlocals; if (!eq) goto unequal; eq = co->co_flags == cp->co_flags; @@ -880,10 +624,10 @@ code_richcompare(PyObject *self, PyObject *other, int op) return res; } -static Py_hash_t +static long code_hash(PyCodeObject *co) { - Py_hash_t h, h0, h1, h2, h3, h4, h5, h6; + long h, h0, h1, h2, h3, h4, h5, h6; h0 = PyObject_Hash(co->co_name); if (h0 == -1) return -1; h1 = PyObject_Hash(co->co_code); @@ -899,30 +643,23 @@ code_hash(PyCodeObject *co) h6 = PyObject_Hash(co->co_cellvars); if (h6 == -1) return -1; h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^ - co->co_argcount ^ co->co_posonlyargcount ^ co->co_kwonlyargcount ^ - co->co_nlocals ^ co->co_flags; + co->co_argcount ^ co->co_nlocals ^ co->co_flags; if (h == -1) h = -2; return h; } /* XXX code objects need to participate in GC? */ -static struct PyMethodDef code_methods[] = { - {"__sizeof__", (PyCFunction)code_sizeof, METH_NOARGS}, - CODE_REPLACE_METHODDEF - {NULL, NULL} /* sentinel */ -}; - PyTypeObject PyCode_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "code", sizeof(PyCodeObject), 0, (destructor)code_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ + 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_as_async */ + (cmpfunc)code_compare, /* tp_compare */ (reprfunc)code_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -938,10 +675,10 @@ PyTypeObject PyCode_Type = { 0, /* tp_traverse */ 0, /* tp_clear */ code_richcompare, /* tp_richcompare */ - offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */ + offsetof(PyCodeObject, co_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - code_methods, /* tp_methods */ + 0, /* tp_methods */ code_memberlist, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -961,16 +698,15 @@ PyTypeObject PyCode_Type = { 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 size = PyString_Size(co->co_lnotab) / 2; + unsigned char *p = (unsigned char*)PyString_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++; + line += *p++; } return line; } @@ -980,12 +716,11 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq) int _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) { - Py_ssize_t size; - int addr, line; + int size, addr, line; unsigned char* p; - p = (unsigned char*)PyBytes_AS_STRING(co->co_lnotab); - size = PyBytes_GET_SIZE(co->co_lnotab) / 2; + p = (unsigned char*)PyString_AS_STRING(co->co_lnotab); + size = PyString_GET_SIZE(co->co_lnotab) / 2; addr = 0; line = co->co_firstlineno; @@ -1005,19 +740,17 @@ _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) if (addr + *p > lasti) break; addr += *p++; - if ((signed char)*p) + if (*p) bounds->ap_lower = addr; - line += (signed char)*p; - p++; + line += *p++; --size; } if (size > 0) { while (--size >= 0) { addr += *p++; - if ((signed char)*p) + if (*p++) break; - p++; } bounds->ap_upper = addr; } @@ -1027,66 +760,3 @@ _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) return line; } - - -int -_PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra) -{ - if (!PyCode_Check(code)) { - PyErr_BadInternalCall(); - return -1; - } - - PyCodeObject *o = (PyCodeObject*) code; - _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra; - - if (co_extra == NULL || co_extra->ce_size <= index) { - *extra = NULL; - return 0; - } - - *extra = co_extra->ce_extras[index]; - return 0; -} - - -int -_PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra) -{ - PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); - - if (!PyCode_Check(code) || index < 0 || - index >= interp->co_extra_user_count) { - PyErr_BadInternalCall(); - return -1; - } - - PyCodeObject *o = (PyCodeObject*) code; - _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra *) o->co_extra; - - if (co_extra == NULL || co_extra->ce_size <= index) { - Py_ssize_t i = (co_extra == NULL ? 0 : co_extra->ce_size); - co_extra = PyMem_Realloc( - co_extra, - sizeof(_PyCodeObjectExtra) + - (interp->co_extra_user_count-1) * sizeof(void*)); - if (co_extra == NULL) { - return -1; - } - for (; i < interp->co_extra_user_count; i++) { - co_extra->ce_extras[i] = NULL; - } - co_extra->ce_size = interp->co_extra_user_count; - o->co_extra = co_extra; - } - - if (co_extra->ce_extras[index] != NULL) { - freefunc free = interp->co_extra_freefuncs[index]; - if (free != NULL) { - free(co_extra->ce_extras[index]); - } - } - - co_extra->ce_extras[index] = extra; - return 0; -} |