Skip to content

Commit cebbefc

Browse files
author
Richard Jones
committed
Applied patch 1337051 by Neal Norwitz, saving 4 ints on frame objects.
1 parent 69c3476 commit cebbefc

4 files changed

Lines changed: 54 additions & 55 deletions

File tree

Include/frameobject.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ typedef struct _frame {
3636
in this scope */
3737
int f_iblock; /* index in f_blockstack */
3838
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
39-
int f_nlocals; /* number of locals */
40-
int f_ncells;
41-
int f_nfreevars;
42-
int f_stacksize; /* size of value stack */
4339
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
4440
} PyFrameObject;
4541

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ What's New in Python 2.5 alpha 3?
1212
Core and builtins
1313
-----------------
1414

15+
- Patch #1337051: reduced size of frame objects.
16+
17+
- PyErr_NewException now accepts a tuple of base classes as its
18+
"base" parameter.
19+
1520
- PyErr_NewException now accepts a tuple of base classes as its
1621
"base" parameter.
1722

Objects/frameobject.c

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,6 @@ static PyGetSetDef frame_getsetlist[] = {
377377
a meaning:
378378
ob_type == &Frametype
379379
f_back next item on free list, or NULL
380-
f_nlocals number of locals
381380
f_stacksize size of value stack
382381
ob_size size of localsplus
383382
Note that the value and block stacks are preserved -- this can save
@@ -458,7 +457,7 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
458457
Py_VISIT(f->f_exc_traceback);
459458

460459
/* locals */
461-
slots = f->f_nlocals + f->f_ncells + f->f_nfreevars;
460+
slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
462461
fastlocals = f->f_localsplus;
463462
for (i = slots; --i >= 0; ++fastlocals)
464463
Py_VISIT(*fastlocals);
@@ -491,7 +490,7 @@ frame_clear(PyFrameObject *f)
491490
Py_CLEAR(f->f_trace);
492491

493492
/* locals */
494-
slots = f->f_nlocals + f->f_ncells + f->f_nfreevars;
493+
slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
495494
fastlocals = f->f_localsplus;
496495
for (i = slots; --i >= 0; ++fastlocals)
497496
Py_CLEAR(*fastlocals);
@@ -760,7 +759,9 @@ PyFrame_FastToLocals(PyFrameObject *f)
760759
PyObject *locals, *map;
761760
PyObject **fast;
762761
PyObject *error_type, *error_value, *error_traceback;
762+
PyCodeObject *co;
763763
Py_ssize_t j;
764+
int ncells, nfreevars;
764765
if (f == NULL)
765766
return;
766767
locals = f->f_locals;
@@ -771,27 +772,24 @@ PyFrame_FastToLocals(PyFrameObject *f)
771772
return;
772773
}
773774
}
774-
map = f->f_code->co_varnames;
775+
co = f->f_code;
776+
map = co->co_varnames;
775777
if (!PyTuple_Check(map))
776778
return;
777779
PyErr_Fetch(&error_type, &error_value, &error_traceback);
778780
fast = f->f_localsplus;
779781
j = PyTuple_GET_SIZE(map);
780-
if (j > f->f_nlocals)
781-
j = f->f_nlocals;
782-
if (f->f_nlocals)
782+
if (j > co->co_nlocals)
783+
j = co->co_nlocals;
784+
if (co->co_nlocals)
783785
map_to_dict(map, j, locals, fast, 0);
784-
if (f->f_ncells || f->f_nfreevars) {
785-
if (!(PyTuple_Check(f->f_code->co_cellvars)
786-
&& PyTuple_Check(f->f_code->co_freevars))) {
787-
return;
788-
}
789-
map_to_dict(f->f_code->co_cellvars,
790-
PyTuple_GET_SIZE(f->f_code->co_cellvars),
791-
locals, fast + f->f_nlocals, 1);
792-
map_to_dict(f->f_code->co_freevars,
793-
PyTuple_GET_SIZE(f->f_code->co_freevars),
794-
locals, fast + f->f_nlocals + f->f_ncells, 1);
786+
ncells = PyTuple_GET_SIZE(co->co_cellvars);
787+
nfreevars = PyTuple_GET_SIZE(co->co_freevars);
788+
if (ncells || nfreevars) {
789+
map_to_dict(co->co_cellvars, ncells,
790+
locals, fast + co->co_nlocals, 1);
791+
map_to_dict(co->co_freevars, nfreevars,
792+
locals, fast + co->co_nlocals + ncells, 1);
795793
}
796794
PyErr_Restore(error_type, error_value, error_traceback);
797795
}
@@ -803,33 +801,33 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
803801
PyObject *locals, *map;
804802
PyObject **fast;
805803
PyObject *error_type, *error_value, *error_traceback;
804+
PyCodeObject *co;
806805
Py_ssize_t j;
806+
int ncells, nfreevars;
807807
if (f == NULL)
808808
return;
809809
locals = f->f_locals;
810-
map = f->f_code->co_varnames;
810+
co = f->f_code;
811+
map = co->co_varnames;
811812
if (locals == NULL)
812813
return;
813814
if (!PyTuple_Check(map))
814815
return;
815816
PyErr_Fetch(&error_type, &error_value, &error_traceback);
816817
fast = f->f_localsplus;
817818
j = PyTuple_GET_SIZE(map);
818-
if (j > f->f_nlocals)
819-
j = f->f_nlocals;
820-
if (f->f_nlocals)
821-
dict_to_map(f->f_code->co_varnames, j, locals, fast, 0, clear);
822-
if (f->f_ncells || f->f_nfreevars) {
823-
if (!(PyTuple_Check(f->f_code->co_cellvars)
824-
&& PyTuple_Check(f->f_code->co_freevars)))
825-
return;
826-
dict_to_map(f->f_code->co_cellvars,
827-
PyTuple_GET_SIZE(f->f_code->co_cellvars),
828-
locals, fast + f->f_nlocals, 1, clear);
829-
dict_to_map(f->f_code->co_freevars,
830-
PyTuple_GET_SIZE(f->f_code->co_freevars),
831-
locals, fast + f->f_nlocals + f->f_ncells, 1,
832-
clear);
819+
if (j > co->co_nlocals)
820+
j = co->co_nlocals;
821+
if (co->co_nlocals)
822+
dict_to_map(co->co_varnames, j, locals, fast, 0, clear);
823+
ncells = PyTuple_GET_SIZE(co->co_cellvars);
824+
nfreevars = PyTuple_GET_SIZE(co->co_freevars);
825+
if (ncells || nfreevars) {
826+
dict_to_map(co->co_cellvars, ncells,
827+
locals, fast + co->co_nlocals, 1, clear);
828+
dict_to_map(co->co_freevars, nfreevars,
829+
locals, fast + co->co_nlocals + ncells, 1,
830+
clear);
833831
}
834832
PyErr_Restore(error_type, error_value, error_traceback);
835833
}

Python/ceval.c

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -654,11 +654,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
654654
#ifdef LLTRACE
655655
#define PUSH(v) { (void)(BASIC_PUSH(v), \
656656
lltrace && prtrace(TOP(), "push")); \
657-
assert(STACK_LEVEL() <= f->f_stacksize); }
657+
assert(STACK_LEVEL() <= co->co_stacksize); }
658658
#define POP() ((void)(lltrace && prtrace(TOP(), "pop")), BASIC_POP())
659659
#define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \
660660
lltrace && prtrace(TOP(), "stackadj")); \
661-
assert(STACK_LEVEL() <= f->f_stacksize); }
661+
assert(STACK_LEVEL() <= co->co_stacksize); }
662662
#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER))
663663
#else
664664
#define PUSH(v) BASIC_PUSH(v)
@@ -729,7 +729,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
729729
names = co->co_names;
730730
consts = co->co_consts;
731731
fastlocals = f->f_localsplus;
732-
freevars = f->f_localsplus + f->f_nlocals;
732+
freevars = f->f_localsplus + co->co_nlocals;
733733
first_instr = (unsigned char*) PyString_AS_STRING(co->co_code);
734734
/* An explanation is in order for the next line.
735735
@@ -780,7 +780,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
780780
READ_TIMESTAMP(loop0);
781781
#endif
782782
assert(stack_pointer >= f->f_valuestack); /* else underflow */
783-
assert(STACK_LEVEL() <= f->f_stacksize); /* else overflow */
783+
assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */
784784

785785
/* Do periodic things. Doing this every time through
786786
the loop would add too much overhead, so we do it
@@ -1916,17 +1916,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
19161916
/* Don't stomp existing exception */
19171917
if (PyErr_Occurred())
19181918
break;
1919-
if (oparg < f->f_ncells) {
1920-
v = PyTuple_GetItem(co->co_cellvars,
1919+
if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) {
1920+
v = PyTuple_GET_ITEM(co->co_cellvars,
19211921
oparg);
19221922
format_exc_check_arg(
19231923
PyExc_UnboundLocalError,
19241924
UNBOUNDLOCAL_ERROR_MSG,
19251925
v);
19261926
} else {
1927-
v = PyTuple_GetItem(
1927+
v = PyTuple_GET_ITEM(
19281928
co->co_freevars,
1929-
oparg - f->f_ncells);
1929+
oparg - PyTuple_GET_SIZE(co->co_cellvars));
19301930
format_exc_check_arg(
19311931
PyExc_NameError,
19321932
UNBOUNDFREE_ERROR_MSG,
@@ -2610,7 +2610,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
26102610
return NULL;
26112611

26122612
fastlocals = f->f_localsplus;
2613-
freevars = f->f_localsplus + f->f_nlocals;
2613+
freevars = f->f_localsplus + co->co_nlocals;
26142614

26152615
if (co->co_argcount > 0 ||
26162616
co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
@@ -2746,7 +2746,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
27462746
}
27472747
/* Allocate and initialize storage for cell vars, and copy free
27482748
vars into frame. This isn't too efficient right now. */
2749-
if (f->f_ncells) {
2749+
if (PyTuple_GET_SIZE(co->co_cellvars)) {
27502750
int i = 0, j = 0, nargs, found;
27512751
char *cellname, *argname;
27522752
PyObject *c;
@@ -2764,7 +2764,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
27642764
that are arguments at the beginning of the cellvars
27652765
list so that we can march over it more efficiently?
27662766
*/
2767-
for (i = 0; i < f->f_ncells; ++i) {
2767+
for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {
27682768
cellname = PyString_AS_STRING(
27692769
PyTuple_GET_ITEM(co->co_cellvars, i));
27702770
found = 0;
@@ -2775,7 +2775,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
27752775
c = PyCell_New(GETLOCAL(j));
27762776
if (c == NULL)
27772777
goto fail;
2778-
GETLOCAL(f->f_nlocals + i) = c;
2778+
GETLOCAL(co->co_nlocals + i) = c;
27792779
found = 1;
27802780
break;
27812781
}
@@ -2784,16 +2784,16 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
27842784
c = PyCell_New(NULL);
27852785
if (c == NULL)
27862786
goto fail;
2787-
SETLOCAL(f->f_nlocals + i, c);
2787+
SETLOCAL(co->co_nlocals + i, c);
27882788
}
27892789
}
27902790
}
2791-
if (f->f_nfreevars) {
2791+
if (PyTuple_GET_SIZE(co->co_freevars)) {
27922792
int i;
2793-
for (i = 0; i < f->f_nfreevars; ++i) {
2793+
for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
27942794
PyObject *o = PyTuple_GET_ITEM(closure, i);
27952795
Py_INCREF(o);
2796-
freevars[f->f_ncells + i] = o;
2796+
freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
27972797
}
27982798
}
27992799

@@ -4214,7 +4214,7 @@ string_concatenate(PyObject *v, PyObject *w,
42144214
}
42154215
case STORE_DEREF:
42164216
{
4217-
PyObject **freevars = f->f_localsplus + f->f_nlocals;
4217+
PyObject **freevars = f->f_localsplus + f->f_code->co_nlocals;
42184218
PyObject *c = freevars[PEEKARG()];
42194219
if (PyCell_GET(c) == v)
42204220
PyCell_Set(c, NULL);

0 commit comments

Comments
 (0)