1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Frame object implementation */
37 #include "frameobject.h"
39 #include "structmember.h"
41 #define OFF(x) offsetof(PyFrameObject, x)
43 static struct memberlist frame_memberlist
[] = {
44 {"f_back", T_OBJECT
, OFF(f_back
), RO
},
45 {"f_code", T_OBJECT
, OFF(f_code
), RO
},
46 {"f_builtins", T_OBJECT
, OFF(f_builtins
),RO
},
47 {"f_globals", T_OBJECT
, OFF(f_globals
), RO
},
48 {"f_locals", T_OBJECT
, OFF(f_locals
), RO
},
49 {"f_lasti", T_INT
, OFF(f_lasti
), RO
},
50 {"f_lineno", T_INT
, OFF(f_lineno
), RO
},
51 {"f_restricted",T_INT
, OFF(f_restricted
),RO
},
52 {"f_trace", T_OBJECT
, OFF(f_trace
)},
53 {"f_exc_type", T_OBJECT
, OFF(f_exc_type
)},
54 {"f_exc_value", T_OBJECT
, OFF(f_exc_value
)},
55 {"f_exc_traceback", T_OBJECT
, OFF(f_exc_traceback
)},
60 frame_getattr(f
, name
)
64 if (strcmp(name
, "f_locals") == 0)
65 PyFrame_FastToLocals(f
);
66 return PyMember_Get((char *)f
, frame_memberlist
, name
);
70 frame_setattr(f
, name
, value
)
75 return PyMember_Set((char *)f
, frame_memberlist
, name
, value
);
78 /* Stack frames are allocated and deallocated at a considerable rate.
79 In an attempt to improve the speed of function calls, we maintain a
80 separate free list of stack frames (just like integers are
81 allocated in a special way -- see intobject.c). When a stack frame
82 is on the free list, only the following members have a meaning:
84 f_back next item on free list, or NULL
85 f_nlocals number of locals
86 f_stacksize size of value stack
87 Note that the value and block stacks are preserved -- this can save
88 another malloc() call or two (and two free() calls as well!).
89 Also note that, unlike for integers, each frame object is a
90 malloc'ed object in its own right -- it is only the actual calls to
91 malloc() that we are trying to save here, not the administration.
92 After all, while a typical program may make millions of calls, a
93 call depth of more than 20 or 30 is probably already exceptional
94 unless the program contains run-away recursion. I hope.
97 static PyFrameObject
*free_list
= NULL
;
104 PyObject
**fastlocals
;
106 /* Kill all local variables */
107 fastlocals
= f
->f_localsplus
;
108 for (i
= f
->f_nlocals
; --i
>= 0; ++fastlocals
) {
109 Py_XDECREF(*fastlocals
);
112 Py_XDECREF(f
->f_back
);
113 Py_XDECREF(f
->f_code
);
114 Py_XDECREF(f
->f_builtins
);
115 Py_XDECREF(f
->f_globals
);
116 Py_XDECREF(f
->f_locals
);
117 Py_XDECREF(f
->f_trace
);
118 Py_XDECREF(f
->f_exc_type
);
119 Py_XDECREF(f
->f_exc_value
);
120 Py_XDECREF(f
->f_exc_traceback
);
121 f
->f_back
= free_list
;
125 PyTypeObject PyFrame_Type
= {
126 PyObject_HEAD_INIT(&PyType_Type
)
129 sizeof(PyFrameObject
),
131 (destructor
)frame_dealloc
, /*tp_dealloc*/
133 (getattrfunc
)frame_getattr
, /*tp_getattr*/
134 (setattrfunc
)frame_setattr
, /*tp_setattr*/
138 0, /*tp_as_sequence*/
143 PyFrame_New(tstate
, code
, globals
, locals
)
144 PyThreadState
*tstate
;
149 PyFrameObject
*back
= tstate
->frame
;
150 static PyObject
*builtin_object
;
155 if (builtin_object
== NULL
) {
156 builtin_object
= PyString_InternFromString("__builtins__");
157 if (builtin_object
== NULL
)
160 if ((back
!= NULL
&& !PyFrame_Check(back
)) ||
161 code
== NULL
|| !PyCode_Check(code
) ||
162 globals
== NULL
|| !PyDict_Check(globals
) ||
163 (locals
!= NULL
&& !PyDict_Check(locals
))) {
164 PyErr_BadInternalCall();
167 extras
= code
->co_stacksize
+ code
->co_nlocals
;
168 if (back
== NULL
|| back
->f_globals
!= globals
) {
169 builtins
= PyDict_GetItem(globals
, builtin_object
);
170 if (builtins
!= NULL
&& PyModule_Check(builtins
))
171 builtins
= PyModule_GetDict(builtins
);
174 /* If we share the globals, we share the builtins.
175 Save a lookup and a call. */
176 builtins
= back
->f_builtins
;
178 if (builtins
!= NULL
&& !PyDict_Check(builtins
))
180 if (free_list
== NULL
) {
181 f
= (PyFrameObject
*)
182 malloc(sizeof(PyFrameObject
) +
183 extras
*sizeof(PyObject
*));
185 return (PyFrameObject
*)PyErr_NoMemory();
186 f
->ob_type
= &PyFrame_Type
;
191 free_list
= free_list
->f_back
;
192 if (f
->f_nlocals
+ f
->f_stacksize
< extras
) {
193 f
= (PyFrameObject
*)
194 realloc(f
, sizeof(PyFrameObject
) +
195 extras
*sizeof(PyObject
*));
197 return (PyFrameObject
*)PyErr_NoMemory();
200 extras
= f
->f_nlocals
+ f
->f_stacksize
;
201 f
->ob_type
= &PyFrame_Type
;
204 if (builtins
== NULL
) {
205 /* No builtins! Make up a minimal one. */
206 builtins
= PyDict_New();
207 if (builtins
== NULL
|| /* Give them 'None', at least. */
208 PyDict_SetItemString(builtins
, "None", Py_None
) < 0) {
214 Py_XINCREF(builtins
);
215 f
->f_builtins
= builtins
;
221 f
->f_globals
= globals
;
222 if (code
->co_flags
& CO_NEWLOCALS
) {
223 if (code
->co_flags
& CO_OPTIMIZED
)
224 locals
= NULL
; /* Let fast_2_locals handle it */
226 locals
= PyDict_New();
227 if (locals
== NULL
) {
238 f
->f_locals
= locals
;
240 f
->f_exc_type
= f
->f_exc_value
= f
->f_exc_traceback
= NULL
;
241 f
->f_tstate
= tstate
;
244 f
->f_lineno
= code
->co_firstlineno
;
245 f
->f_restricted
= (builtins
!= tstate
->interp
->builtins
);
247 f
->f_nlocals
= code
->co_nlocals
;
248 f
->f_stacksize
= extras
- code
->co_nlocals
;
250 while (--extras
>= 0)
251 f
->f_localsplus
[extras
] = NULL
;
253 f
->f_valuestack
= f
->f_localsplus
+ f
->f_nlocals
;
258 /* Block management */
261 PyFrame_BlockSetup(f
, type
, handler
, level
)
268 if (f
->f_iblock
>= CO_MAXBLOCKS
)
269 Py_FatalError("XXX block stack overflow");
270 b
= &f
->f_blockstack
[f
->f_iblock
++];
273 b
->b_handler
= handler
;
281 if (f
->f_iblock
<= 0)
282 Py_FatalError("XXX block stack underflow");
283 b
= &f
->f_blockstack
[--f
->f_iblock
];
287 /* Convert between "fast" version of locals and dictionary version */
290 PyFrame_FastToLocals(f
)
293 /* Merge fast locals into f->f_locals */
294 PyObject
*locals
, *map
;
296 PyObject
*error_type
, *error_value
, *error_traceback
;
300 locals
= f
->f_locals
;
301 if (locals
== NULL
) {
302 locals
= f
->f_locals
= PyDict_New();
303 if (locals
== NULL
) {
304 PyErr_Clear(); /* Can't report it :-( */
308 if (f
->f_nlocals
== 0)
310 map
= f
->f_code
->co_varnames
;
311 if (!PyDict_Check(locals
) || !PyTuple_Check(map
))
313 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
314 fast
= f
->f_localsplus
;
315 j
= PyTuple_Size(map
);
316 if (j
> f
->f_nlocals
)
319 PyObject
*key
= PyTuple_GetItem(map
, j
);
320 PyObject
*value
= fast
[j
];
323 if (PyDict_DelItem(locals
, key
) != 0)
327 if (PyDict_SetItem(locals
, key
, value
) != 0)
331 PyErr_Restore(error_type
, error_value
, error_traceback
);
335 PyFrame_LocalsToFast(f
, clear
)
339 /* Merge f->f_locals into fast locals */
340 PyObject
*locals
, *map
;
342 PyObject
*error_type
, *error_value
, *error_traceback
;
346 locals
= f
->f_locals
;
347 map
= f
->f_code
->co_varnames
;
348 if (locals
== NULL
|| f
->f_code
->co_nlocals
== 0)
350 if (!PyDict_Check(locals
) || !PyTuple_Check(map
))
352 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
353 fast
= f
->f_localsplus
;
354 j
= PyTuple_Size(map
);
355 if (j
> f
->f_nlocals
)
358 PyObject
*key
= PyTuple_GetItem(map
, j
);
359 PyObject
*value
= PyDict_GetItem(locals
, key
);
361 if (value
!= NULL
|| clear
) {
366 PyErr_Restore(error_type
, error_value
, error_traceback
);
369 /* Clear out the free list */
374 while (free_list
!= NULL
) {
375 PyFrameObject
*f
= free_list
;
376 free_list
= free_list
->f_back
;