summaryrefslogtreecommitdiffstats
path: root/Objects/frameobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r--Objects/frameobject.c88
1 files changed, 68 insertions, 20 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index a5300d1..74e7012 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -251,7 +251,51 @@ PyFrame_BlockPop(PyFrameObject *f)
/* Convert between "fast" version of locals and dictionary version */
-/* XXX should also copy free variables and cell variables */
+void
+map_to_dict(PyObject *map, int nmap, PyObject *dict, PyObject **values,
+ int deref)
+{
+ int j;
+ for (j = nmap; --j >= 0; ) {
+ PyObject *key = PyTuple_GetItem(map, j);
+ PyObject *value = values[j];
+ if (deref)
+ value = PyCell_GET(value);
+ if (value == NULL) {
+ PyErr_Clear();
+ if (PyDict_DelItem(dict, key) != 0)
+ PyErr_Clear();
+ }
+ else {
+ if (PyDict_SetItem(dict, key, value) != 0)
+ PyErr_Clear();
+ }
+ }
+}
+
+void
+dict_to_map(PyObject *map, int nmap, PyObject *dict, PyObject **values,
+ int deref, int clear)
+{
+ int j;
+ for (j = nmap; --j >= 0; ) {
+ PyObject *key = PyTuple_GetItem(map, j);
+ PyObject *value = PyDict_GetItem(dict, key);
+ Py_XINCREF(value);
+ if (deref) {
+ if (value) {
+ if (PyCell_Set(values[j], value) < 0)
+ PyErr_Clear();
+ } else if (clear) {
+ Py_XDECREF(values[j]);
+ values[j] = value;
+ }
+ } else if (value != NULL || clear) {
+ Py_XDECREF(values[j]);
+ values[j] = value;
+ }
+ }
+}
void
PyFrame_FastToLocals(PyFrameObject *f)
@@ -281,18 +325,19 @@ PyFrame_FastToLocals(PyFrameObject *f)
j = PyTuple_Size(map);
if (j > f->f_nlocals)
j = f->f_nlocals;
- for (; --j >= 0; ) {
- PyObject *key = PyTuple_GetItem(map, j);
- PyObject *value = fast[j];
- if (value == NULL) {
- PyErr_Clear();
- if (PyDict_DelItem(locals, key) != 0)
- PyErr_Clear();
- }
- else {
- if (PyDict_SetItem(locals, key, value) != 0)
- PyErr_Clear();
+ map_to_dict(map, j, locals, fast, 0);
+ if (f->f_ncells || f->f_nfreevars) {
+ if (!(PyTuple_Check(f->f_code->co_cellvars)
+ && PyTuple_Check(f->f_code->co_freevars))) {
+ Py_DECREF(locals);
+ return;
}
+ map_to_dict(f->f_code->co_cellvars,
+ PyTuple_GET_SIZE(f->f_code->co_cellvars),
+ locals, fast + f->f_nlocals, 1);
+ map_to_dict(f->f_code->co_freevars,
+ PyTuple_GET_SIZE(f->f_code->co_freevars),
+ locals, fast + f->f_nlocals + f->f_ncells, 1);
}
PyErr_Restore(error_type, error_value, error_traceback);
}
@@ -318,14 +363,17 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
j = PyTuple_Size(map);
if (j > f->f_nlocals)
j = f->f_nlocals;
- for (; --j >= 0; ) {
- PyObject *key = PyTuple_GetItem(map, j);
- PyObject *value = PyDict_GetItem(locals, key);
- Py_XINCREF(value);
- if (value != NULL || clear) {
- Py_XDECREF(fast[j]);
- fast[j] = value;
- }
+ dict_to_map(f->f_code->co_varnames, j, locals, fast, 0, clear);
+ if (f->f_ncells || f->f_nfreevars) {
+ if (!(PyTuple_Check(f->f_code->co_cellvars)
+ && PyTuple_Check(f->f_code->co_freevars)))
+ return;
+ dict_to_map(f->f_code->co_cellvars,
+ PyTuple_GET_SIZE(f->f_code->co_cellvars),
+ locals, fast, 1, clear);
+ dict_to_map(f->f_code->co_freevars,
+ PyTuple_GET_SIZE(f->f_code->co_freevars),
+ locals, fast, 1, clear);
}
PyErr_Restore(error_type, error_value, error_traceback);
}