Add the co_extra field and accompanying APIs to code objects.

This completes PEP 523.
This commit is contained in:
Brett Cannon 2016-09-07 11:16:41 -07:00
parent a9296e7f3b
commit 5c4de2863b
8 changed files with 139 additions and 3 deletions

View file

@ -152,6 +152,7 @@ PyCode_New(int argcount, int kwonlyargcount,
co->co_lnotab = lnotab;
co->co_zombieframe = NULL;
co->co_weakreflist = NULL;
co->co_extra = NULL;
return co;
}
@ -361,6 +362,20 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
static void
code_dealloc(PyCodeObject *co)
{
if (co->co_extra != NULL) {
PyThreadState *tstate = PyThreadState_Get();
for (Py_ssize_t i = 0; i < co->co_extra->ce_size; i++) {
freefunc free_extra = tstate->co_extra_freefuncs[i];
if (free_extra != NULL) {
free_extra(co->co_extra->ce_extras[i]);
}
}
PyMem_FREE(co->co_extra);
}
Py_XDECREF(co->co_code);
Py_XDECREF(co->co_consts);
Py_XDECREF(co->co_names);
@ -752,3 +767,79 @@ _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
return line;
}
int
_PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
{
PyCodeObject *o;
assert(*extra == NULL);
if (!PyCode_Check(code)) {
PyErr_BadInternalCall();
return 1;
}
o = (PyCodeObject*) code;
if (o->co_extra == NULL || o->co_extra->ce_size <= index) {
return 0;
}
*extra = o->co_extra->ce_extras[index];
return 0;
}
int
_PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
{
PyCodeObject *o;
PyThreadState *tstate = PyThreadState_Get();
if (!PyCode_Check(code) || index < 0 ||
index >= tstate->co_extra_user_count) {
PyErr_BadInternalCall();
return 1;
}
o = (PyCodeObject*) code;
if (o->co_extra == NULL) {
o->co_extra = (_PyCodeObjectExtra*) PyMem_Malloc(
sizeof(_PyCodeObjectExtra));
if (o->co_extra == NULL) {
return 1;
}
o->co_extra->ce_extras = PyMem_Malloc(
tstate->co_extra_user_count * sizeof(void*));
if (o->co_extra->ce_extras == NULL) {
return 1;
}
o->co_extra->ce_size = tstate->co_extra_user_count;
for (Py_ssize_t i = 0; i < o->co_extra->ce_size; i++) {
o->co_extra->ce_extras[i] = NULL;
}
}
else if (o->co_extra->ce_size <= index) {
o->co_extra->ce_extras = PyMem_Realloc(
o->co_extra->ce_extras, tstate->co_extra_user_count * sizeof(void*));
if (o->co_extra->ce_extras == NULL) {
return 1;
}
o->co_extra->ce_size = tstate->co_extra_user_count;
for (Py_ssize_t i = o->co_extra->ce_size; i < o->co_extra->ce_size; i++) {
o->co_extra->ce_extras[i] = NULL;
}
}
o->co_extra->ce_extras[index] = extra;
return 0;
}