diff options
Diffstat (limited to 'Objects/codeobject.c')
-rw-r--r-- | Objects/codeobject.c | 270 |
1 files changed, 149 insertions, 121 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c index 9879df5392..9713f61b24 100644 --- a/Objects/codeobject.c +++ b/Objects/codeobject.c @@ -8,16 +8,23 @@ /* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */ static int -all_name_chars(unsigned char *s) +all_name_chars(PyObject *o) { static char ok_name_char[256]; static unsigned char *name_chars = (unsigned char *)NAME_CHARS; + PyUnicodeObject *u = (PyUnicodeObject *)o; + const unsigned char *s; + + if (!PyUnicode_Check(o) || PyUnicode_READY(u) == -1 || + PyUnicode_MAX_CHAR_VALUE(u) >= 128) + return 0; if (ok_name_char[*name_chars] == 0) { unsigned char *p; for (p = name_chars; *p; p++) ok_name_char[*p] = 1; } + s = PyUnicode_1BYTE_DATA(u); while (*s) { if (ok_name_char[*s++] == 0) return 0; @@ -32,79 +39,114 @@ intern_strings(PyObject *tuple) for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) { PyObject *v = PyTuple_GET_ITEM(tuple, i); - if (v == NULL || !PyString_CheckExact(v)) { + if (v == NULL || !PyUnicode_CheckExact(v)) { Py_FatalError("non-string found in code slot"); } - PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i)); + PyUnicode_InternInPlace(&PyTuple_GET_ITEM(tuple, i)); } } PyCodeObject * -PyCode_New(int argcount, int nlocals, int stacksize, int flags, +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) { PyCodeObject *co; - Py_ssize_t i; + unsigned char *cell2arg = NULL; + Py_ssize_t i, n_cellvars; + /* Check argument types */ - if (argcount < 0 || nlocals < 0 || + if (argcount < 0 || kwonlyargcount < 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 || !PyString_Check(name) || - filename == NULL || !PyString_Check(filename) || - lnotab == NULL || !PyString_Check(lnotab) || + name == NULL || !PyUnicode_Check(name) || + filename == NULL || !PyUnicode_Check(filename) || + lnotab == NULL || !PyBytes_Check(lnotab) || !PyObject_CheckReadBuffer(code)) { PyErr_BadInternalCall(); return NULL; } + n_cellvars = PyTuple_GET_SIZE(cellvars); intern_strings(names); intern_strings(varnames); intern_strings(freevars); intern_strings(cellvars); /* Intern selected string constants */ - for (i = PyTuple_Size(consts); --i >= 0; ) { + for (i = PyTuple_GET_SIZE(consts); --i >= 0; ) { PyObject *v = PyTuple_GetItem(consts, i); - if (!PyString_Check(v)) + if (!all_name_chars(v)) continue; - if (!all_name_chars((unsigned char *)PyString_AS_STRING(v))) - continue; - PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i)); + PyUnicode_InternInPlace(&PyTuple_GET_ITEM(consts, i)); + } + /* Create mapping between cells and arguments if needed. */ + if (n_cellvars) { + Py_ssize_t total_args = argcount + kwonlyargcount + + ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0); + Py_ssize_t alloc_size = sizeof(unsigned char) * n_cellvars; + int used_cell2arg = 0; + cell2arg = PyMem_MALLOC(alloc_size); + if (cell2arg == NULL) + return NULL; + memset(cell2arg, CO_CELL_NOT_AN_ARG, alloc_size); + /* Find cells which are also arguments. */ + for (i = 0; i < n_cellvars; i++) { + Py_ssize_t j; + PyObject *cell = PyTuple_GET_ITEM(cellvars, i); + for (j = 0; j < total_args; j++) { + PyObject *arg = PyTuple_GET_ITEM(varnames, j); + if (!PyUnicode_Compare(cell, arg)) { + cell2arg[i] = j; + used_cell2arg = 1; + break; + } + } + } + if (!used_cell2arg) { + PyMem_FREE(cell2arg); + cell2arg = NULL; + } } co = PyObject_NEW(PyCodeObject, &PyCode_Type); - 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; + if (co == NULL) { + if (cell2arg) + PyMem_FREE(cell2arg); + return NULL; } + co->co_argcount = argcount; + 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; return co; } @@ -117,7 +159,7 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) PyObject *funcname_ob = NULL; PyCodeObject *result = NULL; if (emptystring == NULL) { - emptystring = PyString_FromString(""); + emptystring = PyBytes_FromString(""); if (emptystring == NULL) goto failed; } @@ -126,14 +168,15 @@ PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno) if (nulltuple == NULL) goto failed; } - funcname_ob = PyString_FromString(funcname); + funcname_ob = PyUnicode_FromString(funcname); if (funcname_ob == NULL) goto failed; - filename_ob = PyString_FromString(filename); + filename_ob = PyUnicode_DecodeFSDefault(filename); if (filename_ob == NULL) goto failed; result = PyCode_New(0, /* argcount */ + 0, /* kwonlyargcount */ 0, /* nlocals */ 0, /* stacksize */ 0, /* flags */ @@ -159,6 +202,7 @@ failed: static PyMemberDef code_memberlist[] = { {"co_argcount", T_INT, OFF(co_argcount), 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}, @@ -192,10 +236,10 @@ validate_and_copy_tuple(PyObject *tup) for (i = 0; i < len; i++) { item = PyTuple_GET_ITEM(tup, i); - if (PyString_CheckExact(item)) { + if (PyUnicode_CheckExact(item)) { Py_INCREF(item); } - else if (!PyString_Check(item)) { + else if (!PyUnicode_Check(item)) { PyErr_Format( PyExc_TypeError, "name tuples must contain only " @@ -205,9 +249,7 @@ validate_and_copy_tuple(PyObject *tup) return NULL; } else { - item = PyString_FromStringAndSize( - PyString_AS_STRING(item), - PyString_GET_SIZE(item)); + item = _PyUnicode_Copy(item); if (item == NULL) { Py_DECREF(newtuple); return NULL; @@ -220,8 +262,9 @@ validate_and_copy_tuple(PyObject *tup) } PyDoc_STRVAR(code_doc, -"code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\ - varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\ +"code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring,\n\ + constants, names, varnames, filename, name, firstlineno,\n\ + lnotab[, freevars[, cellvars]])\n\ \n\ Create a code object. Not for the faint of heart."); @@ -229,6 +272,7 @@ static PyObject * code_new(PyTypeObject *type, PyObject *args, PyObject *kw) { int argcount; + int kwonlyargcount; int nlocals; int stacksize; int flags; @@ -244,8 +288,9 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) int firstlineno; PyObject *lnotab; - if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code", - &argcount, &nlocals, &stacksize, &flags, + if (!PyArg_ParseTuple(args, "iiiiiSO!O!O!UUiS|O!O!:code", + &argcount, &kwonlyargcount, + &nlocals, &stacksize, &flags, &code, &PyTuple_Type, &consts, &PyTuple_Type, &names, @@ -263,6 +308,12 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) goto cleanup; } + if (kwonlyargcount < 0) { + PyErr_SetString( + PyExc_ValueError, + "code: kwonlyargcount must not be negative"); + goto cleanup; + } if (nlocals < 0) { PyErr_SetString( PyExc_ValueError, @@ -289,7 +340,8 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw) if (ourcellvars == NULL) goto cleanup; - co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags, + co = (PyObject *)PyCode_New(argcount, kwonlyargcount, + nlocals, stacksize, flags, code, consts, ournames, ourvarnames, ourfreevars, ourcellvars, filename, name, firstlineno, lnotab); @@ -313,6 +365,8 @@ 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) @@ -321,59 +375,33 @@ code_dealloc(PyCodeObject *co) } static PyObject * -code_repr(PyCodeObject *co) +code_sizeof(PyCodeObject *co, void *unused) { - char buf[500]; - int lineno = -1; - char *filename = "???"; - char *name = "???"; + Py_ssize_t res; - 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); + res = sizeof(PyCodeObject); + if (co->co_cell2arg != NULL && co->co_cellvars != NULL) + res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(unsigned char); + return PyLong_FromSsize_t(res); } -static int -code_compare(PyCodeObject *co, PyCodeObject *cp) +static PyObject * +code_repr(PyCodeObject *co) { - 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; + int lineno; + if (co->co_firstlineno != 0) + lineno = co->co_firstlineno; else - return 0; + 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); + } } static PyObject * @@ -386,16 +414,7 @@ code_richcompare(PyObject *self, PyObject *other, int op) if ((op != Py_EQ && op != Py_NE) || !PyCode_Check(self) || !PyCode_Check(other)) { - - /* 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; + Py_RETURN_NOTIMPLEMENTED; } co = (PyCodeObject *)self; @@ -405,6 +424,8 @@ code_richcompare(PyObject *self, PyObject *other, int op) if (eq <= 0) goto unequal; eq = co->co_argcount == cp->co_argcount; 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; @@ -443,10 +464,10 @@ code_richcompare(PyObject *self, PyObject *other, int op) return res; } -static long +static Py_hash_t code_hash(PyCodeObject *co) { - long h, h0, h1, h2, h3, h4, h5, h6; + Py_hash_t 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); @@ -462,13 +483,19 @@ 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_nlocals ^ co->co_flags; + co->co_argcount ^ co->co_kwonlyargcount ^ + 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}, + {NULL, NULL} /* sentinel */ +}; + PyTypeObject PyCode_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "code", @@ -478,7 +505,7 @@ PyTypeObject PyCode_Type = { 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - (cmpfunc)code_compare, /* tp_compare */ + 0, /* tp_reserved */ (reprfunc)code_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -494,10 +521,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 */ - 0, /* tp_methods */ + code_methods, /* tp_methods */ code_memberlist, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -517,8 +544,8 @@ PyTypeObject PyCode_Type = { int PyCode_Addr2Line(PyCodeObject *co, int addrq) { - int size = PyString_Size(co->co_lnotab) / 2; - unsigned char *p = (unsigned char*)PyString_AsString(co->co_lnotab); + 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) { @@ -535,11 +562,12 @@ PyCode_Addr2Line(PyCodeObject *co, int addrq) int _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) { - int size, addr, line; + Py_ssize_t size; + int addr, line; unsigned char* p; - p = (unsigned char*)PyString_AS_STRING(co->co_lnotab); - size = PyString_GET_SIZE(co->co_lnotab) / 2; + p = (unsigned char*)PyBytes_AS_STRING(co->co_lnotab); + size = PyBytes_GET_SIZE(co->co_lnotab) / 2; addr = 0; line = co->co_firstlineno; |