2 /* Frame object implementation */
7 #include "frameobject.h"
9 #include "structmember.h"
11 #define OFF(x) offsetof(PyFrameObject, x)
13 static struct memberlist frame_memberlist
[] = {
14 {"f_back", T_OBJECT
, OFF(f_back
), RO
},
15 {"f_code", T_OBJECT
, OFF(f_code
), RO
},
16 {"f_builtins", T_OBJECT
, OFF(f_builtins
),RO
},
17 {"f_globals", T_OBJECT
, OFF(f_globals
), RO
},
18 {"f_locals", T_OBJECT
, OFF(f_locals
), RO
},
19 {"f_lasti", T_INT
, OFF(f_lasti
), RO
},
20 {"f_lineno", T_INT
, OFF(f_lineno
), RO
},
21 {"f_restricted",T_INT
, OFF(f_restricted
),RO
},
22 {"f_trace", T_OBJECT
, OFF(f_trace
)},
23 {"f_exc_type", T_OBJECT
, OFF(f_exc_type
)},
24 {"f_exc_value", T_OBJECT
, OFF(f_exc_value
)},
25 {"f_exc_traceback", T_OBJECT
, OFF(f_exc_traceback
)},
30 frame_getattr(PyFrameObject
*f
, char *name
)
32 if (strcmp(name
, "f_locals") == 0)
33 PyFrame_FastToLocals(f
);
34 return PyMember_Get((char *)f
, frame_memberlist
, name
);
38 frame_setattr(PyFrameObject
*f
, char *name
, PyObject
*value
)
40 return PyMember_Set((char *)f
, frame_memberlist
, name
, value
);
43 /* Stack frames are allocated and deallocated at a considerable rate.
44 In an attempt to improve the speed of function calls, we maintain a
45 separate free list of stack frames (just like integers are
46 allocated in a special way -- see intobject.c). When a stack frame
47 is on the free list, only the following members have a meaning:
49 f_back next item on free list, or NULL
50 f_nlocals number of locals
51 f_stacksize size of value stack
52 f_size size of localsplus
53 Note that the value and block stacks are preserved -- this can save
54 another malloc() call or two (and two free() calls as well!).
55 Also note that, unlike for integers, each frame object is a
56 malloc'ed object in its own right -- it is only the actual calls to
57 malloc() that we are trying to save here, not the administration.
58 After all, while a typical program may make millions of calls, a
59 call depth of more than 20 or 30 is probably already exceptional
60 unless the program contains run-away recursion. I hope.
63 static PyFrameObject
*free_list
= NULL
;
66 frame_dealloc(PyFrameObject
*f
)
69 PyObject
**fastlocals
;
71 Py_TRASHCAN_SAFE_BEGIN(f
)
72 /* Kill all local variables */
73 slots
= f
->f_nlocals
+ f
->f_ncells
+ f
->f_nfreevars
;
74 fastlocals
= f
->f_localsplus
;
75 for (i
= slots
; --i
>= 0; ++fastlocals
) {
76 Py_XDECREF(*fastlocals
);
79 Py_XDECREF(f
->f_back
);
80 Py_XDECREF(f
->f_code
);
81 Py_XDECREF(f
->f_builtins
);
82 Py_XDECREF(f
->f_globals
);
83 Py_XDECREF(f
->f_locals
);
84 Py_XDECREF(f
->f_trace
);
85 Py_XDECREF(f
->f_exc_type
);
86 Py_XDECREF(f
->f_exc_value
);
87 Py_XDECREF(f
->f_exc_traceback
);
88 f
->f_back
= free_list
;
90 Py_TRASHCAN_SAFE_END(f
)
93 PyTypeObject PyFrame_Type
= {
94 PyObject_HEAD_INIT(&PyType_Type
)
97 sizeof(PyFrameObject
),
99 (destructor
)frame_dealloc
, /*tp_dealloc*/
101 (getattrfunc
)frame_getattr
, /*tp_getattr*/
102 (setattrfunc
)frame_setattr
, /*tp_setattr*/
106 0, /*tp_as_sequence*/
111 PyFrame_New(PyThreadState
*tstate
, PyCodeObject
*code
, PyObject
*globals
,
114 PyFrameObject
*back
= tstate
->frame
;
115 static PyObject
*builtin_object
;
118 int extras
, ncells
, nfrees
;
120 if (builtin_object
== NULL
) {
121 builtin_object
= PyString_InternFromString("__builtins__");
122 if (builtin_object
== NULL
)
125 if ((back
!= NULL
&& !PyFrame_Check(back
)) ||
126 code
== NULL
|| !PyCode_Check(code
) ||
127 globals
== NULL
|| !PyDict_Check(globals
) ||
128 (locals
!= NULL
&& !PyDict_Check(locals
))) {
129 PyErr_BadInternalCall();
132 ncells
= PyTuple_GET_SIZE(code
->co_cellvars
);
133 nfrees
= PyTuple_GET_SIZE(code
->co_freevars
);
134 extras
= code
->co_stacksize
+ code
->co_nlocals
+ ncells
+ nfrees
;
135 if (back
== NULL
|| back
->f_globals
!= globals
) {
136 builtins
= PyDict_GetItem(globals
, builtin_object
);
137 if (builtins
!= NULL
&& PyModule_Check(builtins
))
138 builtins
= PyModule_GetDict(builtins
);
141 /* If we share the globals, we share the builtins.
142 Save a lookup and a call. */
143 builtins
= back
->f_builtins
;
145 if (builtins
!= NULL
&& !PyDict_Check(builtins
))
147 if (free_list
== NULL
) {
148 /* PyObject_New is inlined */
149 f
= (PyFrameObject
*)
150 PyObject_MALLOC(sizeof(PyFrameObject
) +
151 extras
*sizeof(PyObject
*));
153 return (PyFrameObject
*)PyErr_NoMemory();
154 PyObject_INIT(f
, &PyFrame_Type
);
159 free_list
= free_list
->f_back
;
160 if (f
->f_size
< extras
) {
161 f
= (PyFrameObject
*)
162 PyObject_REALLOC(f
, sizeof(PyFrameObject
) +
163 extras
*sizeof(PyObject
*));
165 return (PyFrameObject
*)PyErr_NoMemory();
170 PyObject_INIT(f
, &PyFrame_Type
);
172 if (builtins
== NULL
) {
173 /* No builtins! Make up a minimal one. */
174 builtins
= PyDict_New();
175 if (builtins
== NULL
|| /* Give them 'None', at least. */
176 PyDict_SetItemString(builtins
, "None", Py_None
) < 0) {
182 Py_XINCREF(builtins
);
183 f
->f_builtins
= builtins
;
189 f
->f_globals
= globals
;
190 if (code
->co_flags
& CO_NEWLOCALS
) {
191 if (code
->co_flags
& CO_OPTIMIZED
)
192 locals
= NULL
; /* Let fast_2_locals handle it */
194 locals
= PyDict_New();
195 if (locals
== NULL
) {
206 f
->f_locals
= locals
;
208 f
->f_exc_type
= f
->f_exc_value
= f
->f_exc_traceback
= NULL
;
209 f
->f_tstate
= tstate
;
212 f
->f_lineno
= code
->co_firstlineno
;
213 f
->f_restricted
= (builtins
!= tstate
->interp
->builtins
);
215 f
->f_nlocals
= code
->co_nlocals
;
216 f
->f_stacksize
= code
->co_stacksize
;
217 f
->f_ncells
= ncells
;
218 f
->f_nfreevars
= nfrees
;
220 while (--extras
>= 0)
221 f
->f_localsplus
[extras
] = NULL
;
223 f
->f_valuestack
= f
->f_localsplus
+ (f
->f_nlocals
+ ncells
+ nfrees
);
228 /* Block management */
231 PyFrame_BlockSetup(PyFrameObject
*f
, int type
, int handler
, int level
)
234 if (f
->f_iblock
>= CO_MAXBLOCKS
)
235 Py_FatalError("XXX block stack overflow");
236 b
= &f
->f_blockstack
[f
->f_iblock
++];
239 b
->b_handler
= handler
;
243 PyFrame_BlockPop(PyFrameObject
*f
)
246 if (f
->f_iblock
<= 0)
247 Py_FatalError("XXX block stack underflow");
248 b
= &f
->f_blockstack
[--f
->f_iblock
];
252 /* Convert between "fast" version of locals and dictionary version */
255 map_to_dict(PyObject
*map
, int nmap
, PyObject
*dict
, PyObject
**values
,
259 for (j
= nmap
; --j
>= 0; ) {
260 PyObject
*key
= PyTuple_GetItem(map
, j
);
261 PyObject
*value
= values
[j
];
263 value
= PyCell_GET(value
);
266 if (PyDict_DelItem(dict
, key
) != 0)
270 if (PyDict_SetItem(dict
, key
, value
) != 0)
277 dict_to_map(PyObject
*map
, int nmap
, PyObject
*dict
, PyObject
**values
,
278 int deref
, int clear
)
281 for (j
= nmap
; --j
>= 0; ) {
282 PyObject
*key
= PyTuple_GetItem(map
, j
);
283 PyObject
*value
= PyDict_GetItem(dict
, key
);
287 if (PyCell_Set(values
[j
], value
) < 0)
290 Py_XDECREF(values
[j
]);
293 } else if (value
!= NULL
|| clear
) {
294 Py_XDECREF(values
[j
]);
301 PyFrame_FastToLocals(PyFrameObject
*f
)
303 /* Merge fast locals into f->f_locals */
304 PyObject
*locals
, *map
;
306 PyObject
*error_type
, *error_value
, *error_traceback
;
310 locals
= f
->f_locals
;
311 if (locals
== NULL
) {
312 locals
= f
->f_locals
= PyDict_New();
313 if (locals
== NULL
) {
314 PyErr_Clear(); /* Can't report it :-( */
318 if (f
->f_nlocals
== 0)
320 map
= f
->f_code
->co_varnames
;
321 if (!PyDict_Check(locals
) || !PyTuple_Check(map
))
323 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
324 fast
= f
->f_localsplus
;
325 j
= PyTuple_Size(map
);
326 if (j
> f
->f_nlocals
)
328 map_to_dict(map
, j
, locals
, fast
, 0);
329 if (f
->f_ncells
|| f
->f_nfreevars
) {
330 if (!(PyTuple_Check(f
->f_code
->co_cellvars
)
331 && PyTuple_Check(f
->f_code
->co_freevars
))) {
335 map_to_dict(f
->f_code
->co_cellvars
,
336 PyTuple_GET_SIZE(f
->f_code
->co_cellvars
),
337 locals
, fast
+ f
->f_nlocals
, 1);
338 map_to_dict(f
->f_code
->co_freevars
,
339 PyTuple_GET_SIZE(f
->f_code
->co_freevars
),
340 locals
, fast
+ f
->f_nlocals
+ f
->f_ncells
, 1);
342 PyErr_Restore(error_type
, error_value
, error_traceback
);
346 PyFrame_LocalsToFast(PyFrameObject
*f
, int clear
)
348 /* Merge f->f_locals into fast locals */
349 PyObject
*locals
, *map
;
351 PyObject
*error_type
, *error_value
, *error_traceback
;
355 locals
= f
->f_locals
;
356 map
= f
->f_code
->co_varnames
;
357 if (locals
== NULL
|| f
->f_code
->co_nlocals
== 0)
359 if (!PyDict_Check(locals
) || !PyTuple_Check(map
))
361 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
362 fast
= f
->f_localsplus
;
363 j
= PyTuple_Size(map
);
364 if (j
> f
->f_nlocals
)
366 dict_to_map(f
->f_code
->co_varnames
, j
, locals
, fast
, 0, clear
);
367 if (f
->f_ncells
|| f
->f_nfreevars
) {
368 if (!(PyTuple_Check(f
->f_code
->co_cellvars
)
369 && PyTuple_Check(f
->f_code
->co_freevars
)))
371 dict_to_map(f
->f_code
->co_cellvars
,
372 PyTuple_GET_SIZE(f
->f_code
->co_cellvars
),
373 locals
, fast
, 1, clear
);
374 dict_to_map(f
->f_code
->co_freevars
,
375 PyTuple_GET_SIZE(f
->f_code
->co_freevars
),
376 locals
, fast
, 1, clear
);
378 PyErr_Restore(error_type
, error_value
, error_traceback
);
381 /* Clear out the free list */
386 while (free_list
!= NULL
) {
387 PyFrameObject
*f
= free_list
;
388 free_list
= free_list
->f_back
;