summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/frameobject.h4
-rw-r--r--Objects/frameobject.c37
-rw-r--r--Python/ceval.c20
3 files changed, 33 insertions, 28 deletions
diff --git a/Include/frameobject.h b/Include/frameobject.h
index c19f1d8..d1a310a 100644
--- a/Include/frameobject.h
+++ b/Include/frameobject.h
@@ -20,7 +20,6 @@ typedef struct _frame {
PyObject *f_builtins; /* builtin symbol table (PyDictObject) */
PyObject *f_globals; /* global symbol table (PyDictObject) */
PyObject *f_locals; /* local symbol table (PyDictObject) */
- PyObject *f_closure; /* environment for free variables */
PyObject **f_valuestack; /* points after the last local */
PyObject *f_trace; /* Trace function */
PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
@@ -31,7 +30,10 @@ typedef struct _frame {
in this scope */
int f_iblock; /* index in f_blockstack */
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
+ int f_size; /* size of localsplus */
int f_nlocals; /* number of locals */
+ int f_ncells;
+ int f_nfreevars;
int f_stacksize; /* size of value stack */
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
} PyFrameObject;
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 0f6372b..18fb0b0 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -49,6 +49,7 @@ frame_setattr(PyFrameObject *f, char *name, PyObject *value)
f_back next item on free list, or NULL
f_nlocals number of locals
f_stacksize size of value stack
+ f_size size of localsplus
Note that the value and block stacks are preserved -- this can save
another malloc() call or two (and two free() calls as well!).
Also note that, unlike for integers, each frame object is a
@@ -79,7 +80,6 @@ frame_dealloc(PyFrameObject *f)
Py_XDECREF(f->f_builtins);
Py_XDECREF(f->f_globals);
Py_XDECREF(f->f_locals);
- Py_XDECREF(f->f_closure);
Py_XDECREF(f->f_trace);
Py_XDECREF(f->f_exc_type);
Py_XDECREF(f->f_exc_value);
@@ -114,7 +114,7 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
static PyObject *builtin_object;
PyFrameObject *f;
PyObject *builtins;
- int extras, ncells;
+ int extras, ncells, nfrees;
if (builtin_object == NULL) {
builtin_object = PyString_InternFromString("__builtins__");
@@ -128,8 +128,9 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
PyErr_BadInternalCall();
return NULL;
}
- extras = code->co_stacksize + code->co_nlocals;
ncells = PyTuple_GET_SIZE(code->co_cellvars);
+ nfrees = PyTuple_GET_SIZE(code->co_freevars);
+ extras = code->co_stacksize + code->co_nlocals + ncells + nfrees;
if (back == NULL || back->f_globals != globals) {
builtins = PyDict_GetItem(globals, builtin_object);
if (builtins != NULL && PyModule_Check(builtins))
@@ -150,19 +151,21 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
if (f == NULL)
return (PyFrameObject *)PyErr_NoMemory();
PyObject_INIT(f, &PyFrame_Type);
+ f->f_size = extras;
}
else {
f = free_list;
free_list = free_list->f_back;
- if (f->f_nlocals + f->f_stacksize < extras) {
+ if (f->f_size < extras) {
f = (PyFrameObject *)
PyObject_REALLOC(f, sizeof(PyFrameObject) +
extras*sizeof(PyObject *));
if (f == NULL)
return (PyFrameObject *)PyErr_NoMemory();
+ f->f_size = extras;
}
else
- extras = f->f_nlocals + f->f_stacksize;
+ extras = f->f_size;
PyObject_INIT(f, &PyFrame_Type);
}
if (builtins == NULL) {
@@ -199,22 +202,6 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
locals = globals;
Py_INCREF(locals);
}
- if (closure || ncells) {
- int i, size;
- size = ncells;
- if (closure)
- size += PyTuple_GET_SIZE(closure);
- f->f_closure = PyTuple_New(size);
- for (i = 0; i < ncells; ++i)
- PyTuple_SET_ITEM(f->f_closure, i, PyCell_New(NULL));
- for (i = ncells; i < size; ++i) {
- PyObject *o = PyTuple_GET_ITEM(closure, i - ncells);
- Py_INCREF(o);
- PyTuple_SET_ITEM(f->f_closure, i, o);
- }
- }
- else
- f->f_closure = NULL;
f->f_locals = locals;
f->f_trace = NULL;
f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL;
@@ -225,12 +212,14 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
f->f_restricted = (builtins != tstate->interp->builtins);
f->f_iblock = 0;
f->f_nlocals = code->co_nlocals;
- f->f_stacksize = extras - code->co_nlocals;
+ f->f_stacksize = code->co_stacksize;
+ f->f_ncells = ncells;
+ f->f_nfreevars = nfrees;
while (--extras >= 0)
f->f_localsplus[extras] = NULL;
- f->f_valuestack = f->f_localsplus + f->f_nlocals;
+ f->f_valuestack = f->f_localsplus + (f->f_nlocals + ncells + nfrees);
return f;
}
@@ -261,6 +250,8 @@ PyFrame_BlockPop(PyFrameObject *f)
/* Convert between "fast" version of locals and dictionary version */
+/* XXX should also copy free variables and cell variables */
+
void
PyFrame_FastToLocals(PyFrameObject *f)
{
diff --git a/Python/ceval.c b/Python/ceval.c
index c7b5696..5d593f2 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -368,7 +368,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
register PyObject *t;
register PyObject *stream = NULL; /* for PRINT opcodes */
register PyFrameObject *f; /* Current frame */
- register PyObject **fastlocals;
+ register PyObject **fastlocals, **freevars;
PyObject *retval = NULL; /* Return value */
PyThreadState *tstate = PyThreadState_GET();
unsigned char *first_instr;
@@ -439,6 +439,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
tstate->frame = f;
fastlocals = f->f_localsplus;
+ freevars = f->f_localsplus + f->f_nlocals;
if (co->co_argcount > 0 ||
co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
@@ -572,6 +573,17 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
goto fail;
}
}
+ /* Allocate storage for cell vars and copy free vars into frame */
+ if (f->f_ncells) {
+ int i;
+ for (i = 0; i < f->f_ncells; ++i)
+ freevars[i] = PyCell_New(NULL);
+ }
+ if (f->f_nfreevars) {
+ int i;
+ for (i = 0; i < f->f_nfreevars; ++i)
+ freevars[f->f_ncells + i] = PyTuple_GET_ITEM(closure, i);
+ }
if (tstate->sys_tracefunc != NULL) {
/* tstate->sys_tracefunc, if defined, is a function that
@@ -1623,13 +1635,13 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
continue;
case LOAD_CLOSURE:
- x = PyTuple_GET_ITEM(f->f_closure, oparg);
+ x = freevars[oparg];
Py_INCREF(x);
PUSH(x);
break;
case LOAD_DEREF:
- x = PyTuple_GET_ITEM(f->f_closure, oparg);
+ x = freevars[oparg];
w = PyCell_Get(x);
Py_INCREF(w);
PUSH(w);
@@ -1637,7 +1649,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
case STORE_DEREF:
w = POP();
- x = PyTuple_GET_ITEM(f->f_closure, oparg);
+ x = freevars[oparg];
PyCell_Set(x, w);
continue;