Kaydet (Commit) 2b724da8 authored tarafından Jeremy Hylton's avatar Jeremy Hylton

Remove f_closure slot of frameobject and use f_localsplus instead.

This change eliminates an extra malloc/free when a frame with free
variables is created.  Any cell vars or free vars are stored in
f_localsplus after the locals and before the stack.

eval_code2() fills in the appropriate values after handling
initialization of locals.

To track the size the frame has an f_size member that tracks the total
size of f_localsplus. It used to be implicitly f_nlocals + f_stacksize.
üst 55087f0c
...@@ -20,7 +20,6 @@ typedef struct _frame { ...@@ -20,7 +20,6 @@ typedef struct _frame {
PyObject *f_builtins; /* builtin symbol table (PyDictObject) */ PyObject *f_builtins; /* builtin symbol table (PyDictObject) */
PyObject *f_globals; /* global symbol table (PyDictObject) */ PyObject *f_globals; /* global symbol table (PyDictObject) */
PyObject *f_locals; /* local 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_valuestack; /* points after the last local */
PyObject *f_trace; /* Trace function */ PyObject *f_trace; /* Trace function */
PyObject *f_exc_type, *f_exc_value, *f_exc_traceback; PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
...@@ -31,7 +30,10 @@ typedef struct _frame { ...@@ -31,7 +30,10 @@ typedef struct _frame {
in this scope */ in this scope */
int f_iblock; /* index in f_blockstack */ int f_iblock; /* index in f_blockstack */
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */ PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
int f_size; /* size of localsplus */
int f_nlocals; /* number of locals */ int f_nlocals; /* number of locals */
int f_ncells;
int f_nfreevars;
int f_stacksize; /* size of value stack */ int f_stacksize; /* size of value stack */
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */ PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
} PyFrameObject; } PyFrameObject;
......
...@@ -49,6 +49,7 @@ frame_setattr(PyFrameObject *f, char *name, PyObject *value) ...@@ -49,6 +49,7 @@ frame_setattr(PyFrameObject *f, char *name, PyObject *value)
f_back next item on free list, or NULL f_back next item on free list, or NULL
f_nlocals number of locals f_nlocals number of locals
f_stacksize size of value stack f_stacksize size of value stack
f_size size of localsplus
Note that the value and block stacks are preserved -- this can save Note that the value and block stacks are preserved -- this can save
another malloc() call or two (and two free() calls as well!). another malloc() call or two (and two free() calls as well!).
Also note that, unlike for integers, each frame object is a Also note that, unlike for integers, each frame object is a
...@@ -79,7 +80,6 @@ frame_dealloc(PyFrameObject *f) ...@@ -79,7 +80,6 @@ frame_dealloc(PyFrameObject *f)
Py_XDECREF(f->f_builtins); Py_XDECREF(f->f_builtins);
Py_XDECREF(f->f_globals); Py_XDECREF(f->f_globals);
Py_XDECREF(f->f_locals); Py_XDECREF(f->f_locals);
Py_XDECREF(f->f_closure);
Py_XDECREF(f->f_trace); Py_XDECREF(f->f_trace);
Py_XDECREF(f->f_exc_type); Py_XDECREF(f->f_exc_type);
Py_XDECREF(f->f_exc_value); Py_XDECREF(f->f_exc_value);
...@@ -114,7 +114,7 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, ...@@ -114,7 +114,7 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
static PyObject *builtin_object; static PyObject *builtin_object;
PyFrameObject *f; PyFrameObject *f;
PyObject *builtins; PyObject *builtins;
int extras, ncells; int extras, ncells, nfrees;
if (builtin_object == NULL) { if (builtin_object == NULL) {
builtin_object = PyString_InternFromString("__builtins__"); builtin_object = PyString_InternFromString("__builtins__");
...@@ -128,8 +128,9 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, ...@@ -128,8 +128,9 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return NULL; return NULL;
} }
extras = code->co_stacksize + code->co_nlocals;
ncells = PyTuple_GET_SIZE(code->co_cellvars); 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) { if (back == NULL || back->f_globals != globals) {
builtins = PyDict_GetItem(globals, builtin_object); builtins = PyDict_GetItem(globals, builtin_object);
if (builtins != NULL && PyModule_Check(builtins)) if (builtins != NULL && PyModule_Check(builtins))
...@@ -150,19 +151,21 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, ...@@ -150,19 +151,21 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
if (f == NULL) if (f == NULL)
return (PyFrameObject *)PyErr_NoMemory(); return (PyFrameObject *)PyErr_NoMemory();
PyObject_INIT(f, &PyFrame_Type); PyObject_INIT(f, &PyFrame_Type);
f->f_size = extras;
} }
else { else {
f = free_list; f = free_list;
free_list = free_list->f_back; free_list = free_list->f_back;
if (f->f_nlocals + f->f_stacksize < extras) { if (f->f_size < extras) {
f = (PyFrameObject *) f = (PyFrameObject *)
PyObject_REALLOC(f, sizeof(PyFrameObject) + PyObject_REALLOC(f, sizeof(PyFrameObject) +
extras*sizeof(PyObject *)); extras*sizeof(PyObject *));
if (f == NULL) if (f == NULL)
return (PyFrameObject *)PyErr_NoMemory(); return (PyFrameObject *)PyErr_NoMemory();
f->f_size = extras;
} }
else else
extras = f->f_nlocals + f->f_stacksize; extras = f->f_size;
PyObject_INIT(f, &PyFrame_Type); PyObject_INIT(f, &PyFrame_Type);
} }
if (builtins == NULL) { if (builtins == NULL) {
...@@ -199,22 +202,6 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, ...@@ -199,22 +202,6 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
locals = globals; locals = globals;
Py_INCREF(locals); 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_locals = locals;
f->f_trace = NULL; f->f_trace = NULL;
f->f_exc_type = f->f_exc_value = f->f_exc_traceback = 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, ...@@ -225,12 +212,14 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
f->f_restricted = (builtins != tstate->interp->builtins); f->f_restricted = (builtins != tstate->interp->builtins);
f->f_iblock = 0; f->f_iblock = 0;
f->f_nlocals = code->co_nlocals; 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) while (--extras >= 0)
f->f_localsplus[extras] = NULL; 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; return f;
} }
...@@ -261,6 +250,8 @@ PyFrame_BlockPop(PyFrameObject *f) ...@@ -261,6 +250,8 @@ PyFrame_BlockPop(PyFrameObject *f)
/* Convert between "fast" version of locals and dictionary version */ /* Convert between "fast" version of locals and dictionary version */
/* XXX should also copy free variables and cell variables */
void void
PyFrame_FastToLocals(PyFrameObject *f) PyFrame_FastToLocals(PyFrameObject *f)
{ {
......
...@@ -368,7 +368,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -368,7 +368,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
register PyObject *t; register PyObject *t;
register PyObject *stream = NULL; /* for PRINT opcodes */ register PyObject *stream = NULL; /* for PRINT opcodes */
register PyFrameObject *f; /* Current frame */ register PyFrameObject *f; /* Current frame */
register PyObject **fastlocals; register PyObject **fastlocals, **freevars;
PyObject *retval = NULL; /* Return value */ PyObject *retval = NULL; /* Return value */
PyThreadState *tstate = PyThreadState_GET(); PyThreadState *tstate = PyThreadState_GET();
unsigned char *first_instr; unsigned char *first_instr;
...@@ -439,6 +439,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -439,6 +439,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
tstate->frame = f; tstate->frame = f;
fastlocals = f->f_localsplus; fastlocals = f->f_localsplus;
freevars = f->f_localsplus + f->f_nlocals;
if (co->co_argcount > 0 || if (co->co_argcount > 0 ||
co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
...@@ -572,6 +573,17 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -572,6 +573,17 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
goto fail; 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) { if (tstate->sys_tracefunc != NULL) {
/* tstate->sys_tracefunc, if defined, is a function that /* tstate->sys_tracefunc, if defined, is a function that
...@@ -1623,13 +1635,13 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1623,13 +1635,13 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
continue; continue;
case LOAD_CLOSURE: case LOAD_CLOSURE:
x = PyTuple_GET_ITEM(f->f_closure, oparg); x = freevars[oparg];
Py_INCREF(x); Py_INCREF(x);
PUSH(x); PUSH(x);
break; break;
case LOAD_DEREF: case LOAD_DEREF:
x = PyTuple_GET_ITEM(f->f_closure, oparg); x = freevars[oparg];
w = PyCell_Get(x); w = PyCell_Get(x);
Py_INCREF(w); Py_INCREF(w);
PUSH(w); PUSH(w);
...@@ -1637,7 +1649,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, ...@@ -1637,7 +1649,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
case STORE_DEREF: case STORE_DEREF:
w = POP(); w = POP();
x = PyTuple_GET_ITEM(f->f_closure, oparg); x = freevars[oparg];
PyCell_Set(x, w); PyCell_Set(x, w);
continue; continue;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment