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
;
72 Py_TRASHCAN_SAFE_BEGIN(f
)
74 /* Kill all local variables */
75 slots
= f
->f_nlocals
+ f
->f_ncells
+ f
->f_nfreevars
;
76 fastlocals
= f
->f_localsplus
;
77 for (i
= slots
; --i
>= 0; ++fastlocals
) {
78 Py_XDECREF(*fastlocals
);
82 if (f
->f_stacktop
!= NULL
) {
83 for (p
= f
->f_valuestack
; p
< f
->f_stacktop
; p
++)
87 Py_XDECREF(f
->f_back
);
88 Py_XDECREF(f
->f_code
);
89 Py_XDECREF(f
->f_builtins
);
90 Py_XDECREF(f
->f_globals
);
91 Py_XDECREF(f
->f_locals
);
92 Py_XDECREF(f
->f_trace
);
93 Py_XDECREF(f
->f_exc_type
);
94 Py_XDECREF(f
->f_exc_value
);
95 Py_XDECREF(f
->f_exc_traceback
);
96 f
->f_back
= free_list
;
98 Py_TRASHCAN_SAFE_END(f
)
102 frame_traverse(PyFrameObject
*f
, visitproc visit
, void *arg
)
104 PyObject
**fastlocals
, **p
;
106 #define VISIT(o) if (o) {if ((err = visit((PyObject *)(o), arg))) return err;}
110 VISIT(f
->f_builtins
);
114 VISIT(f
->f_exc_type
);
115 VISIT(f
->f_exc_value
);
116 VISIT(f
->f_exc_traceback
);
119 slots
= f
->f_nlocals
+ f
->f_ncells
+ f
->f_nfreevars
;
120 fastlocals
= f
->f_localsplus
;
121 for (i
= slots
; --i
>= 0; ++fastlocals
) {
126 if (f
->f_stacktop
!= NULL
) {
127 for (p
= f
->f_valuestack
; p
< f
->f_stacktop
; p
++)
135 frame_clear(PyFrameObject
*f
)
137 PyObject
**fastlocals
, **p
;
140 Py_XDECREF(f
->f_exc_type
);
141 f
->f_exc_type
= NULL
;
143 Py_XDECREF(f
->f_exc_value
);
144 f
->f_exc_value
= NULL
;
146 Py_XDECREF(f
->f_exc_traceback
);
147 f
->f_exc_traceback
= NULL
;
149 Py_XDECREF(f
->f_trace
);
153 slots
= f
->f_nlocals
+ f
->f_ncells
+ f
->f_nfreevars
;
154 fastlocals
= f
->f_localsplus
;
155 for (i
= slots
; --i
>= 0; ++fastlocals
) {
156 if (*fastlocals
!= NULL
) {
157 Py_XDECREF(*fastlocals
);
163 if (f
->f_stacktop
!= NULL
) {
164 for (p
= f
->f_valuestack
; p
< f
->f_stacktop
; p
++) {
172 PyTypeObject PyFrame_Type
= {
173 PyObject_HEAD_INIT(&PyType_Type
)
176 sizeof(PyFrameObject
) + PyGC_HEAD_SIZE
,
178 (destructor
)frame_dealloc
, /* tp_dealloc */
180 (getattrfunc
)frame_getattr
, /* tp_getattr */
181 (setattrfunc
)frame_setattr
, /* tp_setattr */
184 0, /* tp_as_number */
185 0, /* tp_as_sequence */
186 0, /* tp_as_mapping */
192 0, /* tp_as_buffer */
193 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_GC
, /* tp_flags */
195 (traverseproc
)frame_traverse
, /* tp_traverse */
196 (inquiry
)frame_clear
, /* tp_clear */
200 PyFrame_New(PyThreadState
*tstate
, PyCodeObject
*code
, PyObject
*globals
,
203 PyFrameObject
*back
= tstate
->frame
;
204 static PyObject
*builtin_object
;
207 int extras
, ncells
, nfrees
;
209 if (builtin_object
== NULL
) {
210 builtin_object
= PyString_InternFromString("__builtins__");
211 if (builtin_object
== NULL
)
214 if ((back
!= NULL
&& !PyFrame_Check(back
)) ||
215 code
== NULL
|| !PyCode_Check(code
) ||
216 globals
== NULL
|| !PyDict_Check(globals
) ||
217 (locals
!= NULL
&& !PyDict_Check(locals
))) {
218 PyErr_BadInternalCall();
221 ncells
= PyTuple_GET_SIZE(code
->co_cellvars
);
222 nfrees
= PyTuple_GET_SIZE(code
->co_freevars
);
223 extras
= code
->co_stacksize
+ code
->co_nlocals
+ ncells
+ nfrees
;
224 if (back
== NULL
|| back
->f_globals
!= globals
) {
225 builtins
= PyDict_GetItem(globals
, builtin_object
);
226 if (builtins
!= NULL
&& PyModule_Check(builtins
))
227 builtins
= PyModule_GetDict(builtins
);
230 /* If we share the globals, we share the builtins.
231 Save a lookup and a call. */
232 builtins
= back
->f_builtins
;
234 if (builtins
!= NULL
&& !PyDict_Check(builtins
))
236 if (free_list
== NULL
) {
237 /* PyObject_New is inlined */
238 f
= (PyFrameObject
*)
239 PyObject_MALLOC(sizeof(PyFrameObject
) +
240 extras
*sizeof(PyObject
*) +
243 return (PyFrameObject
*)PyErr_NoMemory();
244 f
= (PyFrameObject
*) PyObject_FROM_GC(f
);
245 PyObject_INIT(f
, &PyFrame_Type
);
250 free_list
= free_list
->f_back
;
251 if (f
->f_size
< extras
) {
252 f
= (PyFrameObject
*) PyObject_AS_GC(f
);
253 f
= (PyFrameObject
*)
254 PyObject_REALLOC(f
, sizeof(PyFrameObject
) +
255 extras
*sizeof(PyObject
*) +
258 return (PyFrameObject
*)PyErr_NoMemory();
259 f
= (PyFrameObject
*) PyObject_FROM_GC(f
);
264 PyObject_INIT(f
, &PyFrame_Type
);
266 if (builtins
== NULL
) {
267 /* No builtins! Make up a minimal one. */
268 builtins
= PyDict_New();
269 if (builtins
== NULL
|| /* Give them 'None', at least. */
270 PyDict_SetItemString(builtins
, "None", Py_None
) < 0) {
276 Py_XINCREF(builtins
);
277 f
->f_builtins
= builtins
;
283 f
->f_globals
= globals
;
284 if (code
->co_flags
& CO_NEWLOCALS
) {
285 if (code
->co_flags
& CO_OPTIMIZED
)
286 locals
= NULL
; /* Let fast_2_locals handle it */
288 locals
= PyDict_New();
289 if (locals
== NULL
) {
300 f
->f_locals
= locals
;
302 f
->f_exc_type
= f
->f_exc_value
= f
->f_exc_traceback
= NULL
;
303 f
->f_tstate
= tstate
;
306 f
->f_lineno
= code
->co_firstlineno
;
307 f
->f_restricted
= (builtins
!= tstate
->interp
->builtins
);
309 f
->f_nlocals
= code
->co_nlocals
;
310 f
->f_stacksize
= code
->co_stacksize
;
311 f
->f_ncells
= ncells
;
312 f
->f_nfreevars
= nfrees
;
314 while (--extras
>= 0)
315 f
->f_localsplus
[extras
] = NULL
;
317 f
->f_valuestack
= f
->f_localsplus
+ (f
->f_nlocals
+ ncells
+ nfrees
);
318 f
->f_stacktop
= f
->f_valuestack
;
324 /* Block management */
327 PyFrame_BlockSetup(PyFrameObject
*f
, int type
, int handler
, int level
)
330 if (f
->f_iblock
>= CO_MAXBLOCKS
)
331 Py_FatalError("XXX block stack overflow");
332 b
= &f
->f_blockstack
[f
->f_iblock
++];
335 b
->b_handler
= handler
;
339 PyFrame_BlockPop(PyFrameObject
*f
)
342 if (f
->f_iblock
<= 0)
343 Py_FatalError("XXX block stack underflow");
344 b
= &f
->f_blockstack
[--f
->f_iblock
];
348 /* Convert between "fast" version of locals and dictionary version */
351 map_to_dict(PyObject
*map
, int nmap
, PyObject
*dict
, PyObject
**values
,
355 for (j
= nmap
; --j
>= 0; ) {
356 PyObject
*key
= PyTuple_GetItem(map
, j
);
357 PyObject
*value
= values
[j
];
359 value
= PyCell_GET(value
);
362 if (PyDict_DelItem(dict
, key
) != 0)
366 if (PyDict_SetItem(dict
, key
, value
) != 0)
373 dict_to_map(PyObject
*map
, int nmap
, PyObject
*dict
, PyObject
**values
,
374 int deref
, int clear
)
377 for (j
= nmap
; --j
>= 0; ) {
378 PyObject
*key
= PyTuple_GetItem(map
, j
);
379 PyObject
*value
= PyDict_GetItem(dict
, key
);
382 if (value
|| clear
) {
383 if (PyCell_Set(values
[j
], value
) < 0)
386 } else if (value
!= NULL
|| clear
) {
387 Py_XDECREF(values
[j
]);
394 PyFrame_FastToLocals(PyFrameObject
*f
)
396 /* Merge fast locals into f->f_locals */
397 PyObject
*locals
, *map
;
399 PyObject
*error_type
, *error_value
, *error_traceback
;
403 locals
= f
->f_locals
;
404 if (locals
== NULL
) {
405 locals
= f
->f_locals
= PyDict_New();
406 if (locals
== NULL
) {
407 PyErr_Clear(); /* Can't report it :-( */
411 if (f
->f_nlocals
== 0)
413 map
= f
->f_code
->co_varnames
;
414 if (!PyDict_Check(locals
) || !PyTuple_Check(map
))
416 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
417 fast
= f
->f_localsplus
;
418 j
= PyTuple_Size(map
);
419 if (j
> f
->f_nlocals
)
421 map_to_dict(map
, j
, locals
, fast
, 0);
422 if (f
->f_ncells
|| f
->f_nfreevars
) {
423 if (!(PyTuple_Check(f
->f_code
->co_cellvars
)
424 && PyTuple_Check(f
->f_code
->co_freevars
))) {
428 map_to_dict(f
->f_code
->co_cellvars
,
429 PyTuple_GET_SIZE(f
->f_code
->co_cellvars
),
430 locals
, fast
+ f
->f_nlocals
, 1);
431 map_to_dict(f
->f_code
->co_freevars
,
432 PyTuple_GET_SIZE(f
->f_code
->co_freevars
),
433 locals
, fast
+ f
->f_nlocals
+ f
->f_ncells
, 1);
435 PyErr_Restore(error_type
, error_value
, error_traceback
);
439 PyFrame_LocalsToFast(PyFrameObject
*f
, int clear
)
441 /* Merge f->f_locals into fast locals */
442 PyObject
*locals
, *map
;
444 PyObject
*error_type
, *error_value
, *error_traceback
;
448 locals
= f
->f_locals
;
449 map
= f
->f_code
->co_varnames
;
450 if (locals
== NULL
|| f
->f_code
->co_nlocals
== 0)
452 if (!PyDict_Check(locals
) || !PyTuple_Check(map
))
454 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
455 fast
= f
->f_localsplus
;
456 j
= PyTuple_Size(map
);
457 if (j
> f
->f_nlocals
)
459 dict_to_map(f
->f_code
->co_varnames
, j
, locals
, fast
, 0, clear
);
460 if (f
->f_ncells
|| f
->f_nfreevars
) {
461 if (!(PyTuple_Check(f
->f_code
->co_cellvars
)
462 && PyTuple_Check(f
->f_code
->co_freevars
)))
464 dict_to_map(f
->f_code
->co_cellvars
,
465 PyTuple_GET_SIZE(f
->f_code
->co_cellvars
),
466 locals
, fast
+ f
->f_nlocals
, 1, clear
);
467 dict_to_map(f
->f_code
->co_freevars
,
468 PyTuple_GET_SIZE(f
->f_code
->co_freevars
),
469 locals
, fast
+ f
->f_nlocals
+ f
->f_ncells
, 1, clear
);
471 PyErr_Restore(error_type
, error_value
, error_traceback
);
474 /* Clear out the free list */
479 while (free_list
!= NULL
) {
480 PyFrameObject
*f
= free_list
;
481 free_list
= free_list
->f_back
;
482 f
= (PyFrameObject
*) PyObject_AS_GC(f
);