summaryrefslogtreecommitdiff
path: root/Objects/codeobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/codeobject.c')
-rw-r--r--Objects/codeobject.c270
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;