mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
Changes that appear to give another 12% speedup.
Rather than allocating a list object for the fast locals and another (extensible one) for the value stack and allocating the block stack dynamically, allocate the block stack with a fixed size (CO_MAXBLOCKS from compile.h), and stick the locals and value stack at the end of the object (this is now possible since the stack size is known beforehand). Get rid of the owner field and the nvalues argument -- it is available in the code object, like nlocals. This requires small changes in ceval.c only.
This commit is contained in:
parent
cdf578ebaf
commit
f3e85a0356
1 changed files with 55 additions and 87 deletions
|
@ -47,10 +47,6 @@ static struct memberlist frame_memberlist[] = {
|
|||
{"f_builtins", T_OBJECT, OFF(f_builtins),RO},
|
||||
{"f_globals", T_OBJECT, OFF(f_globals), RO},
|
||||
{"f_locals", T_OBJECT, OFF(f_locals), RO},
|
||||
{"f_owner", T_OBJECT, OFF(f_owner), RO},
|
||||
#if 0
|
||||
{"f_fastlocals",T_OBJECT, OFF(f_fastlocals),RO}, /* XXX Unsafe */
|
||||
#endif
|
||||
{"f_lasti", T_INT, OFF(f_lasti), RO},
|
||||
{"f_lineno", T_INT, OFF(f_lineno), RO},
|
||||
{"f_restricted",T_INT, OFF(f_restricted),RO},
|
||||
|
@ -84,10 +80,8 @@ frame_setattr(f, name, value)
|
|||
is on the free list, only the following members have a meaning:
|
||||
ob_type == &Frametype
|
||||
f_back next item on free list, or NULL
|
||||
f_nvalues size of f_valuestack
|
||||
f_valuestack array of (f_nvalues+1) object pointers, or NULL
|
||||
f_nblocks size of f_blockstack
|
||||
f_blockstack array of (f_nblocks+1) blocks, or NULL
|
||||
f_nlocals number of locals
|
||||
f_stacksize size of value stack
|
||||
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
|
||||
|
@ -109,8 +103,6 @@ frame_dealloc(f)
|
|||
XDECREF(f->f_builtins);
|
||||
XDECREF(f->f_globals);
|
||||
XDECREF(f->f_locals);
|
||||
XDECREF(f->f_owner);
|
||||
XDECREF(f->f_fastlocals);
|
||||
XDECREF(f->f_trace);
|
||||
f->f_back = free_list;
|
||||
free_list = f;
|
||||
|
@ -134,28 +126,26 @@ typeobject Frametype = {
|
|||
};
|
||||
|
||||
frameobject *
|
||||
newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
|
||||
newframeobject(back, code, globals, locals)
|
||||
frameobject *back;
|
||||
codeobject *code;
|
||||
object *globals;
|
||||
object *locals;
|
||||
object *owner;
|
||||
int nvalues;
|
||||
int nblocks;
|
||||
{
|
||||
static object *builtin_object;
|
||||
frameobject *f;
|
||||
object *builtins;
|
||||
int extras = code->co_stacksize + code->co_nlocals;
|
||||
|
||||
if (builtin_object == NULL) {
|
||||
builtin_object = PyString_InternFromString("__builtins__");
|
||||
if (builtin_object == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if ((back != NULL && !is_frameobject(back)) ||
|
||||
code == NULL || !is_codeobject(code) ||
|
||||
globals == NULL || !is_dictobject(globals) ||
|
||||
(locals != NULL && !is_dictobject(locals)) ||
|
||||
nvalues < 0 || nblocks < 0) {
|
||||
code == NULL || !is_codeobject(code) ||
|
||||
globals == NULL || !is_dictobject(globals) ||
|
||||
(locals != NULL && !is_dictobject(locals))) {
|
||||
err_badcall();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -167,16 +157,21 @@ newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
|
|||
return NULL;
|
||||
}
|
||||
if (free_list == NULL) {
|
||||
f = NEWOBJ(frameobject, &Frametype);
|
||||
f = (frameobject *)
|
||||
malloc(sizeof(frameobject) + extras*sizeof(object *));
|
||||
if (f == NULL)
|
||||
return NULL;
|
||||
f->f_nvalues = f->f_nblocks = 0;
|
||||
f->f_valuestack = NULL;
|
||||
f->f_blockstack = NULL;
|
||||
return (PyFrameObject *)err_nomem();
|
||||
f->ob_type = &Frametype;
|
||||
NEWREF(f);
|
||||
}
|
||||
else {
|
||||
f = free_list;
|
||||
free_list = free_list->f_back;
|
||||
if (f->f_nlocals + f->f_stacksize < extras) {
|
||||
f = realloc(f, sizeof(frameobject) + extras*sizeof(object *));
|
||||
if (f == NULL)
|
||||
return (PyFrameObject *)err_nomem();
|
||||
}
|
||||
f->ob_type = &Frametype;
|
||||
NEWREF(f);
|
||||
}
|
||||
|
@ -205,58 +200,23 @@ newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
|
|||
INCREF(locals);
|
||||
}
|
||||
f->f_locals = locals;
|
||||
XINCREF(owner);
|
||||
f->f_owner = owner;
|
||||
f->f_fastlocals = NULL;
|
||||
if (code->co_nlocals > 0) {
|
||||
f->f_fastlocals = newlistobject(code->co_nlocals);
|
||||
if (f->f_fastlocals == NULL) {
|
||||
DECREF(f);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
|
||||
XDEL(f->f_valuestack);
|
||||
f->f_valuestack = NEW(object *, nvalues+1);
|
||||
f->f_nvalues = nvalues;
|
||||
}
|
||||
if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
|
||||
XDEL(f->f_blockstack);
|
||||
f->f_blockstack = NEW(block, nblocks+1);
|
||||
f->f_nblocks = nblocks;
|
||||
}
|
||||
f->f_iblock = 0;
|
||||
f->f_trace = NULL;
|
||||
|
||||
f->f_lasti = 0;
|
||||
f->f_lineno = -1;
|
||||
f->f_restricted = (builtins != getbuiltindict());
|
||||
f->f_trace = NULL;
|
||||
if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
|
||||
err_nomem();
|
||||
DECREF(f);
|
||||
return NULL;
|
||||
}
|
||||
f->f_iblock = 0;
|
||||
f->f_nlocals = code->co_nlocals;
|
||||
f->f_stacksize = code->co_stacksize;
|
||||
|
||||
while (--extras >= 0)
|
||||
f->f_localsplus[extras] = NULL;
|
||||
|
||||
f->f_valuestack = f->f_localsplus + f->f_nlocals;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
#if 0
|
||||
object **
|
||||
extend_stack(f, level, incr)
|
||||
frameobject *f;
|
||||
int level;
|
||||
int incr;
|
||||
{
|
||||
f->f_nvalues = level + incr + 10;
|
||||
f->f_valuestack =
|
||||
(object **) realloc((ANY *)f->f_valuestack,
|
||||
sizeof(object *) * (f->f_nvalues + 1));
|
||||
if (f->f_valuestack == NULL) {
|
||||
err_nomem();
|
||||
return NULL;
|
||||
}
|
||||
return f->f_valuestack + level;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Block management */
|
||||
|
||||
void
|
||||
|
@ -267,7 +227,7 @@ setup_block(f, type, handler, level)
|
|||
int level;
|
||||
{
|
||||
block *b;
|
||||
if (f->f_iblock >= f->f_nblocks)
|
||||
if (f->f_iblock >= CO_MAXBLOCKS)
|
||||
fatal("XXX block stack overflow");
|
||||
b = &f->f_blockstack[f->f_iblock++];
|
||||
b->b_type = type;
|
||||
|
@ -292,8 +252,9 @@ void
|
|||
fast_2_locals(f)
|
||||
frameobject *f;
|
||||
{
|
||||
/* Merge f->f_fastlocals into f->f_locals */
|
||||
object *locals, *fast, *map;
|
||||
/* Merge fast locals into f->f_locals */
|
||||
object *locals, *map;
|
||||
object **fast;
|
||||
object *error_type, *error_value, *error_traceback;
|
||||
int j;
|
||||
if (f == NULL)
|
||||
|
@ -306,17 +267,19 @@ fast_2_locals(f)
|
|||
return;
|
||||
}
|
||||
}
|
||||
fast = f->f_fastlocals;
|
||||
if (fast == NULL || f->f_code->co_nlocals == 0)
|
||||
if (f->f_nlocals == 0)
|
||||
return;
|
||||
map = f->f_code->co_varnames;
|
||||
if (!is_dictobject(locals) || !is_listobject(fast) ||
|
||||
!is_tupleobject(map))
|
||||
if (!is_dictobject(locals) || !is_tupleobject(map))
|
||||
return;
|
||||
err_fetch(&error_type, &error_value, &error_traceback);
|
||||
for (j = gettuplesize(map); --j >= 0; ) {
|
||||
fast = f->f_localsplus;
|
||||
j = gettuplesize(map);
|
||||
if (j > f->f_nlocals)
|
||||
j = f->f_nlocals;
|
||||
for (; --j >= 0; ) {
|
||||
object *key = gettupleitem(map, j);
|
||||
object *value = getlistitem(fast, j);
|
||||
object *value = fast[j];
|
||||
if (value == NULL) {
|
||||
err_clear();
|
||||
if (dict2remove(locals, key) != 0)
|
||||
|
@ -335,31 +298,36 @@ locals_2_fast(f, clear)
|
|||
frameobject *f;
|
||||
int clear;
|
||||
{
|
||||
/* Merge f->f_locals into f->f_fastlocals */
|
||||
object *locals, *fast, *map;
|
||||
/* Merge f->f_locals into fast locals */
|
||||
object *locals, *map;
|
||||
object **fast;
|
||||
object *error_type, *error_value, *error_traceback;
|
||||
int j;
|
||||
if (f == NULL)
|
||||
return;
|
||||
locals = f->f_locals;
|
||||
fast = f->f_fastlocals;
|
||||
map = f->f_code->co_varnames;
|
||||
if (locals == NULL || fast == NULL || f->f_code->co_nlocals == 0)
|
||||
return;
|
||||
if (!is_dictobject(locals) || !is_listobject(fast) ||
|
||||
!is_tupleobject(map))
|
||||
if (!is_dictobject(locals) || !is_tupleobject(map))
|
||||
return;
|
||||
err_fetch(&error_type, &error_value, &error_traceback);
|
||||
for (j = gettuplesize(map); --j >= 0; ) {
|
||||
fast = f->f_localsplus;
|
||||
j = gettuplesize(map);
|
||||
if (j > f->f_nlocals)
|
||||
j = f->f_nlocals;
|
||||
for (; --j >= 0; ) {
|
||||
object *key = gettupleitem(map, j);
|
||||
object *value = dict2lookup(locals, key);
|
||||
if (value == NULL)
|
||||
err_clear();
|
||||
else
|
||||
INCREF(value);
|
||||
if (value != NULL || clear)
|
||||
if (setlistitem(fast, j, value) != 0)
|
||||
err_clear();
|
||||
if (value != NULL || clear) {
|
||||
XDECREF(fast[j]);
|
||||
XINCREF(value);
|
||||
fast[j] = value;
|
||||
}
|
||||
}
|
||||
err_restore(error_type, error_value, error_traceback);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue