blob: ae183311ff4e0579381c2b10d596bf05d8783248 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum6610ad91995-01-04 19:07:38 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossumf70e43a1991-02-19 12:39:46 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossumf70e43a1991-02-19 12:39:46 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossumf70e43a1991-02-19 12:39:46 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossumf70e43a1991-02-19 12:39:46 +000029
30******************************************************************/
31
Guido van Rossum3f5da241990-12-20 15:06:42 +000032/* Frame object implementation */
33
34#include "allobjects.h"
35
36#include "compile.h"
37#include "frameobject.h"
38#include "opcode.h"
39#include "structmember.h"
Guido van Rossumc1134821995-01-10 10:39:16 +000040#include "bltinmodule.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000041
42#define OFF(x) offsetof(frameobject, x)
43
44static struct memberlist frame_memberlist[] = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +000045 {"f_back", T_OBJECT, OFF(f_back), RO},
46 {"f_code", T_OBJECT, OFF(f_code), RO},
Guido van Rossumc1134821995-01-10 10:39:16 +000047 {"f_builtins", T_OBJECT, OFF(f_builtins),RO},
Guido van Rossum1d5735e1994-08-30 08:27:36 +000048 {"f_globals", T_OBJECT, OFF(f_globals), RO},
49 {"f_locals", T_OBJECT, OFF(f_locals), RO},
50 {"f_owner", T_OBJECT, OFF(f_owner), RO},
Guido van Rossumd7047b31995-01-02 19:07:15 +000051#if 0
52 {"f_fastlocals",T_OBJECT, OFF(f_fastlocals),RO}, /* XXX Unsafe */
53#endif
Guido van Rossum1d5735e1994-08-30 08:27:36 +000054 {"f_lasti", T_INT, OFF(f_lasti), RO},
55 {"f_lineno", T_INT, OFF(f_lineno), RO},
Guido van Rossumc1134821995-01-10 10:39:16 +000056 {"f_restricted",T_INT, OFF(f_restricted),RO},
Guido van Rossum1d5735e1994-08-30 08:27:36 +000057 {"f_trace", T_OBJECT, OFF(f_trace)},
Guido van Rossum3f5da241990-12-20 15:06:42 +000058 {NULL} /* Sentinel */
59};
60
61static object *
62frame_getattr(f, name)
63 frameobject *f;
64 char *name;
65{
Guido van Rossum1d5735e1994-08-30 08:27:36 +000066 if (strcmp(name, "f_locals") == 0)
67 fast_2_locals(f);
Guido van Rossum3f5da241990-12-20 15:06:42 +000068 return getmember((char *)f, frame_memberlist, name);
69}
70
Guido van Rossum1d5735e1994-08-30 08:27:36 +000071static int
72frame_setattr(f, name, value)
73 frameobject *f;
74 char *name;
75 object *value;
76{
77 return setmember((char *)f, frame_memberlist, name, value);
78}
79
Guido van Rossuma9e7dc11992-10-18 18:53:57 +000080/* Stack frames are allocated and deallocated at a considerable rate.
81 In an attempt to improve the speed of function calls, we maintain a
82 separate free list of stack frames (just like integers are
83 allocated in a special way -- see intobject.c). When a stack frame
84 is on the free list, only the following members have a meaning:
85 ob_type == &Frametype
86 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
91 Note that the value and block stacks are preserved -- this can save
92 another malloc() call or two (and two free() calls as well!).
93 Also note that, unlike for integers, each frame object is a
94 malloc'ed object in its own right -- it is only the actual calls to
95 malloc() that we are trying to save here, not the administration.
96 After all, while a typical program may make millions of calls, a
97 call depth of more than 20 or 30 is probably already exceptional
98 unless the program contains run-away recursion. I hope.
99*/
100
101static frameobject *free_list = NULL;
102
Guido van Rossum3f5da241990-12-20 15:06:42 +0000103static void
104frame_dealloc(f)
105 frameobject *f;
106{
107 XDECREF(f->f_back);
108 XDECREF(f->f_code);
Guido van Rossumc1134821995-01-10 10:39:16 +0000109 XDECREF(f->f_builtins);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000110 XDECREF(f->f_globals);
111 XDECREF(f->f_locals);
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000112 XDECREF(f->f_owner);
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000113 XDECREF(f->f_fastlocals);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000114 XDECREF(f->f_trace);
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000115 f->f_back = free_list;
116 free_list = f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000117}
118
119typeobject Frametype = {
120 OB_HEAD_INIT(&Typetype)
121 0,
122 "frame",
123 sizeof(frameobject),
124 0,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000125 (destructor)frame_dealloc, /*tp_dealloc*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000126 0, /*tp_print*/
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000127 (getattrfunc)frame_getattr, /*tp_getattr*/
128 (setattrfunc)frame_setattr, /*tp_setattr*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000129 0, /*tp_compare*/
130 0, /*tp_repr*/
131 0, /*tp_as_number*/
132 0, /*tp_as_sequence*/
133 0, /*tp_as_mapping*/
134};
135
136frameobject *
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000137newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000138 frameobject *back;
139 codeobject *code;
140 object *globals;
141 object *locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000142 object *owner;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000143 int nvalues;
144 int nblocks;
145{
Sjoerd Mullender5b7f3cd1995-04-04 11:47:41 +0000146 static object *builtin_object;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000147 frameobject *f;
Guido van Rossumc1134821995-01-10 10:39:16 +0000148 object *builtins;
Sjoerd Mullender5b7f3cd1995-04-04 11:47:41 +0000149 if (builtin_object == NULL) {
150 builtin_object = newstringobject("__builtins__");
151 if (builtin_object == NULL)
152 return NULL;
153 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000154 if ((back != NULL && !is_frameobject(back)) ||
155 code == NULL || !is_codeobject(code) ||
156 globals == NULL || !is_dictobject(globals) ||
Guido van Rossum2271bf71995-07-18 14:30:34 +0000157 locals != NULL && !is_dictobject(locals) ||
Guido van Rossum3f5da241990-12-20 15:06:42 +0000158 nvalues < 0 || nblocks < 0) {
159 err_badcall();
160 return NULL;
161 }
Sjoerd Mullender5b7f3cd1995-04-04 11:47:41 +0000162 builtins = mappinglookup(globals, builtin_object);
Guido van Rossumb4e7e251995-01-17 16:27:25 +0000163 if (builtins != NULL && is_moduleobject(builtins))
164 builtins = getmoduledict(builtins);
Guido van Rossumc1134821995-01-10 10:39:16 +0000165 if (builtins == NULL || !is_mappingobject(builtins)) {
166 err_setstr(TypeError, "bad __builtins__ dictionary");
167 return NULL;
168 }
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000169 if (free_list == NULL) {
170 f = NEWOBJ(frameobject, &Frametype);
Guido van Rossum2271bf71995-07-18 14:30:34 +0000171 if (f == NULL)
172 return NULL;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000173 f->f_nvalues = f->f_nblocks = 0;
174 f->f_valuestack = NULL;
175 f->f_blockstack = NULL;
176 }
177 else {
178 f = free_list;
179 free_list = free_list->f_back;
Sjoerd Mullenderf64992e1993-08-03 15:11:36 +0000180 f->ob_type = &Frametype;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000181 NEWREF(f);
182 }
Guido van Rossum2271bf71995-07-18 14:30:34 +0000183 XINCREF(back);
184 f->f_back = back;
185 INCREF(code);
186 f->f_code = code;
187 XINCREF(builtins);
188 f->f_builtins = builtins;
189 INCREF(globals);
190 f->f_globals = globals;
Guido van Rossumbdd207a1995-07-26 16:14:30 +0000191 if (code->co_flags & CO_NEWLOCALS) {
192 if (code->co_flags & CO_OPTIMIZED)
193 locals = NULL; /* Let fast_2_locals handle it */
194 else {
195 locals = newdictobject();
196 if (locals == NULL) {
197 DECREF(f);
198 return NULL;
199 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000200 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000201 }
Guido van Rossum2271bf71995-07-18 14:30:34 +0000202 else {
203 if (locals == NULL)
204 locals = globals;
205 INCREF(locals);
206 }
207 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;
229 f->f_lasti = 0;
230 f->f_lineno = -1;
231 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 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000238 return f;
239}
240
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000241object **
242extend_stack(f, level, incr)
243 frameobject *f;
244 int level;
245 int incr;
246{
247 f->f_nvalues = level + incr + 10;
248 f->f_valuestack =
249 (object **) realloc((ANY *)f->f_valuestack,
250 sizeof(object *) * (f->f_nvalues + 1));
251 if (f->f_valuestack == NULL) {
252 err_nomem();
253 return NULL;
254 }
255 return f->f_valuestack + level;
256}
257
Guido van Rossum3f5da241990-12-20 15:06:42 +0000258/* Block management */
259
260void
261setup_block(f, type, handler, level)
262 frameobject *f;
263 int type;
264 int handler;
265 int level;
266{
267 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000268 if (f->f_iblock >= f->f_nblocks)
269 fatal("XXX block stack overflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000270 b = &f->f_blockstack[f->f_iblock++];
271 b->b_type = type;
272 b->b_level = level;
273 b->b_handler = handler;
274}
275
276block *
277pop_block(f)
278 frameobject *f;
279{
280 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000281 if (f->f_iblock <= 0)
282 fatal("XXX block stack underflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000283 b = &f->f_blockstack[--f->f_iblock];
284 return b;
285}
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000286
287/* Convert between "fast" version of locals and dictionary version */
288
289void
290fast_2_locals(f)
291 frameobject *f;
292{
293 /* Merge f->f_fastlocals into f->f_locals */
294 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000295 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000296 int j;
297 if (f == NULL)
298 return;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000299 locals = f->f_locals;
300 if (locals == NULL) {
301 locals = f->f_locals = newdictobject();
302 if (locals == NULL) {
303 err_clear(); /* Can't report it :-( */
304 return;
305 }
306 }
Guido van Rossumbdd207a1995-07-26 16:14:30 +0000307 fast = f->f_fastlocals;
308 if (fast == NULL || f->f_code->co_nlocals == 0)
309 return;
310 map = f->f_code->co_varnames;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000311 if (!is_dictobject(locals) || !is_listobject(fast) ||
312 !is_tupleobject(map))
313 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000314 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000315 for (j = gettuplesize(map); --j >= 0; ) {
316 object *key = gettupleitem(map, j);
317 object *value = getlistitem(fast, j);
318 if (value == NULL) {
319 err_clear();
320 if (dict2remove(locals, key) != 0)
321 err_clear();
322 }
323 else {
324 if (dict2insert(locals, key, value) != 0)
325 err_clear();
326 }
327 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000328 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000329}
330
331void
332locals_2_fast(f, clear)
333 frameobject *f;
334 int clear;
335{
336 /* Merge f->f_locals into f->f_fastlocals */
337 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000338 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000339 int j;
340 if (f == NULL)
341 return;
342 locals = f->f_locals;
343 fast = f->f_fastlocals;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000344 map = f->f_code->co_varnames;
345 if (locals == NULL || fast == NULL || f->f_code->co_nlocals == 0)
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000346 return;
347 if (!is_dictobject(locals) || !is_listobject(fast) ||
348 !is_tupleobject(map))
349 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000350 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000351 for (j = gettuplesize(map); --j >= 0; ) {
352 object *key = gettupleitem(map, j);
353 object *value = dict2lookup(locals, key);
354 if (value == NULL)
355 err_clear();
356 else
357 INCREF(value);
358 if (value != NULL || clear)
359 if (setlistitem(fast, j, value) != 0)
360 err_clear();
361 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000362 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000363}