Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f3e85a0

Browse files
committed
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.
1 parent cdf578e commit f3e85a0

1 file changed

Lines changed: 55 additions & 87 deletions

File tree

Objects/frameobject.c

Lines changed: 55 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ static struct memberlist frame_memberlist[] = {
4747
{"f_builtins", T_OBJECT, OFF(f_builtins),RO},
4848
{"f_globals", T_OBJECT, OFF(f_globals), RO},
4949
{"f_locals", T_OBJECT, OFF(f_locals), RO},
50-
{"f_owner", T_OBJECT, OFF(f_owner), RO},
51-
#if 0
52-
{"f_fastlocals",T_OBJECT, OFF(f_fastlocals),RO}, /* XXX Unsafe */
53-
#endif
5450
{"f_lasti", T_INT, OFF(f_lasti), RO},
5551
{"f_lineno", T_INT, OFF(f_lineno), RO},
5652
{"f_restricted",T_INT, OFF(f_restricted),RO},
@@ -84,10 +80,8 @@ frame_setattr(f, name, value)
8480
is on the free list, only the following members have a meaning:
8581
ob_type == &Frametype
8682
f_back next item on free list, or NULL
87-
f_nvalues size of f_valuestack
88-
f_valuestack array of (f_nvalues+1) object pointers, or NULL
89-
f_nblocks size of f_blockstack
90-
f_blockstack array of (f_nblocks+1) blocks, or NULL
83+
f_nlocals number of locals
84+
f_stacksize size of value stack
9185
Note that the value and block stacks are preserved -- this can save
9286
another malloc() call or two (and two free() calls as well!).
9387
Also note that, unlike for integers, each frame object is a
@@ -109,8 +103,6 @@ frame_dealloc(f)
109103
XDECREF(f->f_builtins);
110104
XDECREF(f->f_globals);
111105
XDECREF(f->f_locals);
112-
XDECREF(f->f_owner);
113-
XDECREF(f->f_fastlocals);
114106
XDECREF(f->f_trace);
115107
f->f_back = free_list;
116108
free_list = f;
@@ -134,28 +126,26 @@ typeobject Frametype = {
134126
};
135127

136128
frameobject *
137-
newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
129+
newframeobject(back, code, globals, locals)
138130
frameobject *back;
139131
codeobject *code;
140132
object *globals;
141133
object *locals;
142-
object *owner;
143-
int nvalues;
144-
int nblocks;
145134
{
146135
static object *builtin_object;
147136
frameobject *f;
148137
object *builtins;
138+
int extras = code->co_stacksize + code->co_nlocals;
139+
149140
if (builtin_object == NULL) {
150141
builtin_object = PyString_InternFromString("__builtins__");
151142
if (builtin_object == NULL)
152143
return NULL;
153144
}
154145
if ((back != NULL && !is_frameobject(back)) ||
155-
code == NULL || !is_codeobject(code) ||
156-
globals == NULL || !is_dictobject(globals) ||
157-
(locals != NULL && !is_dictobject(locals)) ||
158-
nvalues < 0 || nblocks < 0) {
146+
code == NULL || !is_codeobject(code) ||
147+
globals == NULL || !is_dictobject(globals) ||
148+
(locals != NULL && !is_dictobject(locals))) {
159149
err_badcall();
160150
return NULL;
161151
}
@@ -167,16 +157,21 @@ newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
167157
return NULL;
168158
}
169159
if (free_list == NULL) {
170-
f = NEWOBJ(frameobject, &Frametype);
160+
f = (frameobject *)
161+
malloc(sizeof(frameobject) + extras*sizeof(object *));
171162
if (f == NULL)
172-
return NULL;
173-
f->f_nvalues = f->f_nblocks = 0;
174-
f->f_valuestack = NULL;
175-
f->f_blockstack = NULL;
163+
return (PyFrameObject *)err_nomem();
164+
f->ob_type = &Frametype;
165+
NEWREF(f);
176166
}
177167
else {
178168
f = free_list;
179169
free_list = free_list->f_back;
170+
if (f->f_nlocals + f->f_stacksize < extras) {
171+
f = realloc(f, sizeof(frameobject) + extras*sizeof(object *));
172+
if (f == NULL)
173+
return (PyFrameObject *)err_nomem();
174+
}
180175
f->ob_type = &Frametype;
181176
NEWREF(f);
182177
}
@@ -205,57 +200,22 @@ newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
205200
INCREF(locals);
206201
}
207202
f->f_locals = locals;
208-
XINCREF(owner);
209-
f->f_owner = owner;
210-
f->f_fastlocals = NULL;
211-
if (code->co_nlocals > 0) {
212-
f->f_fastlocals = newlistobject(code->co_nlocals);
213-
if (f->f_fastlocals == NULL) {
214-
DECREF(f);
215-
return NULL;
216-
}
217-
}
218-
if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
219-
XDEL(f->f_valuestack);
220-
f->f_valuestack = NEW(object *, nvalues+1);
221-
f->f_nvalues = nvalues;
222-
}
223-
if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
224-
XDEL(f->f_blockstack);
225-
f->f_blockstack = NEW(block, nblocks+1);
226-
f->f_nblocks = nblocks;
227-
}
228-
f->f_iblock = 0;
203+
f->f_trace = NULL;
204+
229205
f->f_lasti = 0;
230206
f->f_lineno = -1;
231207
f->f_restricted = (builtins != getbuiltindict());
232-
f->f_trace = NULL;
233-
if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
234-
err_nomem();
235-
DECREF(f);
236-
return NULL;
237-
}
238-
return f;
239-
}
208+
f->f_iblock = 0;
209+
f->f_nlocals = code->co_nlocals;
210+
f->f_stacksize = code->co_stacksize;
240211

241-
#if 0
242-
object **
243-
extend_stack(f, level, incr)
244-
frameobject *f;
245-
int level;
246-
int incr;
247-
{
248-
f->f_nvalues = level + incr + 10;
249-
f->f_valuestack =
250-
(object **) realloc((ANY *)f->f_valuestack,
251-
sizeof(object *) * (f->f_nvalues + 1));
252-
if (f->f_valuestack == NULL) {
253-
err_nomem();
254-
return NULL;
255-
}
256-
return f->f_valuestack + level;
212+
while (--extras >= 0)
213+
f->f_localsplus[extras] = NULL;
214+
215+
f->f_valuestack = f->f_localsplus + f->f_nlocals;
216+
217+
return f;
257218
}
258-
#endif
259219

260220
/* Block management */
261221

@@ -267,7 +227,7 @@ setup_block(f, type, handler, level)
267227
int level;
268228
{
269229
block *b;
270-
if (f->f_iblock >= f->f_nblocks)
230+
if (f->f_iblock >= CO_MAXBLOCKS)
271231
fatal("XXX block stack overflow");
272232
b = &f->f_blockstack[f->f_iblock++];
273233
b->b_type = type;
@@ -292,8 +252,9 @@ void
292252
fast_2_locals(f)
293253
frameobject *f;
294254
{
295-
/* Merge f->f_fastlocals into f->f_locals */
296-
object *locals, *fast, *map;
255+
/* Merge fast locals into f->f_locals */
256+
object *locals, *map;
257+
object **fast;
297258
object *error_type, *error_value, *error_traceback;
298259
int j;
299260
if (f == NULL)
@@ -306,17 +267,19 @@ fast_2_locals(f)
306267
return;
307268
}
308269
}
309-
fast = f->f_fastlocals;
310-
if (fast == NULL || f->f_code->co_nlocals == 0)
270+
if (f->f_nlocals == 0)
311271
return;
312272
map = f->f_code->co_varnames;
313-
if (!is_dictobject(locals) || !is_listobject(fast) ||
314-
!is_tupleobject(map))
273+
if (!is_dictobject(locals) || !is_tupleobject(map))
315274
return;
316275
err_fetch(&error_type, &error_value, &error_traceback);
317-
for (j = gettuplesize(map); --j >= 0; ) {
276+
fast = f->f_localsplus;
277+
j = gettuplesize(map);
278+
if (j > f->f_nlocals)
279+
j = f->f_nlocals;
280+
for (; --j >= 0; ) {
318281
object *key = gettupleitem(map, j);
319-
object *value = getlistitem(fast, j);
282+
object *value = fast[j];
320283
if (value == NULL) {
321284
err_clear();
322285
if (dict2remove(locals, key) != 0)
@@ -335,31 +298,36 @@ locals_2_fast(f, clear)
335298
frameobject *f;
336299
int clear;
337300
{
338-
/* Merge f->f_locals into f->f_fastlocals */
339-
object *locals, *fast, *map;
301+
/* Merge f->f_locals into fast locals */
302+
object *locals, *map;
303+
object **fast;
340304
object *error_type, *error_value, *error_traceback;
341305
int j;
342306
if (f == NULL)
343307
return;
344308
locals = f->f_locals;
345-
fast = f->f_fastlocals;
346309
map = f->f_code->co_varnames;
347310
if (locals == NULL || fast == NULL || f->f_code->co_nlocals == 0)
348311
return;
349-
if (!is_dictobject(locals) || !is_listobject(fast) ||
350-
!is_tupleobject(map))
312+
if (!is_dictobject(locals) || !is_tupleobject(map))
351313
return;
352314
err_fetch(&error_type, &error_value, &error_traceback);
353-
for (j = gettuplesize(map); --j >= 0; ) {
315+
fast = f->f_localsplus;
316+
j = gettuplesize(map);
317+
if (j > f->f_nlocals)
318+
j = f->f_nlocals;
319+
for (; --j >= 0; ) {
354320
object *key = gettupleitem(map, j);
355321
object *value = dict2lookup(locals, key);
356322
if (value == NULL)
357323
err_clear();
358324
else
359325
INCREF(value);
360-
if (value != NULL || clear)
361-
if (setlistitem(fast, j, value) != 0)
362-
err_clear();
326+
if (value != NULL || clear) {
327+
XDECREF(fast[j]);
328+
XINCREF(value);
329+
fast[j] = value;
330+
}
363331
}
364332
err_restore(error_type, error_value, error_traceback);
365333
}

0 commit comments

Comments
 (0)