blob: 6441855d266eb4df5745ecf5061e66dbe1d67f3c [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
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum3f5da241990-12-20 15:06:42 +000025/* Frame object implementation */
26
27#include "allobjects.h"
28
29#include "compile.h"
30#include "frameobject.h"
31#include "opcode.h"
32#include "structmember.h"
Guido van Rossumc1134821995-01-10 10:39:16 +000033#include "bltinmodule.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +000034
35#define OFF(x) offsetof(frameobject, x)
36
37static struct memberlist frame_memberlist[] = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +000038 {"f_back", T_OBJECT, OFF(f_back), RO},
39 {"f_code", T_OBJECT, OFF(f_code), RO},
Guido van Rossumc1134821995-01-10 10:39:16 +000040 {"f_builtins", T_OBJECT, OFF(f_builtins),RO},
Guido van Rossum1d5735e1994-08-30 08:27:36 +000041 {"f_globals", T_OBJECT, OFF(f_globals), RO},
42 {"f_locals", T_OBJECT, OFF(f_locals), RO},
43 {"f_owner", T_OBJECT, OFF(f_owner), RO},
Guido van Rossumd7047b31995-01-02 19:07:15 +000044#if 0
45 {"f_fastlocals",T_OBJECT, OFF(f_fastlocals),RO}, /* XXX Unsafe */
46#endif
Guido van Rossum1d5735e1994-08-30 08:27:36 +000047 {"f_lasti", T_INT, OFF(f_lasti), RO},
48 {"f_lineno", T_INT, OFF(f_lineno), RO},
Guido van Rossumc1134821995-01-10 10:39:16 +000049 {"f_restricted",T_INT, OFF(f_restricted),RO},
Guido van Rossum1d5735e1994-08-30 08:27:36 +000050 {"f_trace", T_OBJECT, OFF(f_trace)},
Guido van Rossum3f5da241990-12-20 15:06:42 +000051 {NULL} /* Sentinel */
52};
53
54static object *
55frame_getattr(f, name)
56 frameobject *f;
57 char *name;
58{
Guido van Rossum1d5735e1994-08-30 08:27:36 +000059 if (strcmp(name, "f_locals") == 0)
60 fast_2_locals(f);
Guido van Rossum3f5da241990-12-20 15:06:42 +000061 return getmember((char *)f, frame_memberlist, name);
62}
63
Guido van Rossum1d5735e1994-08-30 08:27:36 +000064static int
65frame_setattr(f, name, value)
66 frameobject *f;
67 char *name;
68 object *value;
69{
70 return setmember((char *)f, frame_memberlist, name, value);
71}
72
Guido van Rossuma9e7dc11992-10-18 18:53:57 +000073/* Stack frames are allocated and deallocated at a considerable rate.
74 In an attempt to improve the speed of function calls, we maintain a
75 separate free list of stack frames (just like integers are
76 allocated in a special way -- see intobject.c). When a stack frame
77 is on the free list, only the following members have a meaning:
78 ob_type == &Frametype
79 f_back next item on free list, or NULL
80 f_nvalues size of f_valuestack
81 f_valuestack array of (f_nvalues+1) object pointers, or NULL
82 f_nblocks size of f_blockstack
83 f_blockstack array of (f_nblocks+1) blocks, or NULL
84 Note that the value and block stacks are preserved -- this can save
85 another malloc() call or two (and two free() calls as well!).
86 Also note that, unlike for integers, each frame object is a
87 malloc'ed object in its own right -- it is only the actual calls to
88 malloc() that we are trying to save here, not the administration.
89 After all, while a typical program may make millions of calls, a
90 call depth of more than 20 or 30 is probably already exceptional
91 unless the program contains run-away recursion. I hope.
92*/
93
94static frameobject *free_list = NULL;
95
Guido van Rossum3f5da241990-12-20 15:06:42 +000096static void
97frame_dealloc(f)
98 frameobject *f;
99{
100 XDECREF(f->f_back);
101 XDECREF(f->f_code);
Guido van Rossumc1134821995-01-10 10:39:16 +0000102 XDECREF(f->f_builtins);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000103 XDECREF(f->f_globals);
104 XDECREF(f->f_locals);
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000105 XDECREF(f->f_owner);
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000106 XDECREF(f->f_fastlocals);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000107 XDECREF(f->f_trace);
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000108 f->f_back = free_list;
109 free_list = f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000110}
111
112typeobject Frametype = {
113 OB_HEAD_INIT(&Typetype)
114 0,
115 "frame",
116 sizeof(frameobject),
117 0,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000118 (destructor)frame_dealloc, /*tp_dealloc*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000119 0, /*tp_print*/
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000120 (getattrfunc)frame_getattr, /*tp_getattr*/
121 (setattrfunc)frame_setattr, /*tp_setattr*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000122 0, /*tp_compare*/
123 0, /*tp_repr*/
124 0, /*tp_as_number*/
125 0, /*tp_as_sequence*/
126 0, /*tp_as_mapping*/
127};
128
129frameobject *
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000130newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000131 frameobject *back;
132 codeobject *code;
133 object *globals;
134 object *locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000135 object *owner;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000136 int nvalues;
137 int nblocks;
138{
Sjoerd Mullender5b7f3cd1995-04-04 11:47:41 +0000139 static object *builtin_object;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000140 frameobject *f;
Guido van Rossumc1134821995-01-10 10:39:16 +0000141 object *builtins;
Sjoerd Mullender5b7f3cd1995-04-04 11:47:41 +0000142 if (builtin_object == NULL) {
143 builtin_object = newstringobject("__builtins__");
144 if (builtin_object == NULL)
145 return NULL;
146 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000147 if ((back != NULL && !is_frameobject(back)) ||
148 code == NULL || !is_codeobject(code) ||
149 globals == NULL || !is_dictobject(globals) ||
Guido van Rossum2271bf71995-07-18 14:30:34 +0000150 locals != NULL && !is_dictobject(locals) ||
Guido van Rossum3f5da241990-12-20 15:06:42 +0000151 nvalues < 0 || nblocks < 0) {
152 err_badcall();
153 return NULL;
154 }
Sjoerd Mullender5b7f3cd1995-04-04 11:47:41 +0000155 builtins = mappinglookup(globals, builtin_object);
Guido van Rossumb4e7e251995-01-17 16:27:25 +0000156 if (builtins != NULL && is_moduleobject(builtins))
157 builtins = getmoduledict(builtins);
Guido van Rossumc1134821995-01-10 10:39:16 +0000158 if (builtins == NULL || !is_mappingobject(builtins)) {
159 err_setstr(TypeError, "bad __builtins__ dictionary");
160 return NULL;
161 }
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000162 if (free_list == NULL) {
163 f = NEWOBJ(frameobject, &Frametype);
Guido van Rossum2271bf71995-07-18 14:30:34 +0000164 if (f == NULL)
165 return NULL;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000166 f->f_nvalues = f->f_nblocks = 0;
167 f->f_valuestack = NULL;
168 f->f_blockstack = NULL;
169 }
170 else {
171 f = free_list;
172 free_list = free_list->f_back;
Sjoerd Mullenderf64992e1993-08-03 15:11:36 +0000173 f->ob_type = &Frametype;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000174 NEWREF(f);
175 }
Guido van Rossum2271bf71995-07-18 14:30:34 +0000176 XINCREF(back);
177 f->f_back = back;
178 INCREF(code);
179 f->f_code = code;
180 XINCREF(builtins);
181 f->f_builtins = builtins;
182 INCREF(globals);
183 f->f_globals = globals;
Guido van Rossumbdd207a1995-07-26 16:14:30 +0000184 if (code->co_flags & CO_NEWLOCALS) {
185 if (code->co_flags & CO_OPTIMIZED)
186 locals = NULL; /* Let fast_2_locals handle it */
187 else {
188 locals = newdictobject();
189 if (locals == NULL) {
190 DECREF(f);
191 return NULL;
192 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000193 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000194 }
Guido van Rossum2271bf71995-07-18 14:30:34 +0000195 else {
196 if (locals == NULL)
197 locals = globals;
198 INCREF(locals);
199 }
200 f->f_locals = locals;
201 XINCREF(owner);
202 f->f_owner = owner;
203 f->f_fastlocals = NULL;
204 if (code->co_nlocals > 0) {
205 f->f_fastlocals = newlistobject(code->co_nlocals);
206 if (f->f_fastlocals == NULL) {
207 DECREF(f);
208 return NULL;
209 }
210 }
211 if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
212 XDEL(f->f_valuestack);
213 f->f_valuestack = NEW(object *, nvalues+1);
214 f->f_nvalues = nvalues;
215 }
216 if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
217 XDEL(f->f_blockstack);
218 f->f_blockstack = NEW(block, nblocks+1);
219 f->f_nblocks = nblocks;
220 }
221 f->f_iblock = 0;
222 f->f_lasti = 0;
223 f->f_lineno = -1;
224 f->f_restricted = (builtins != getbuiltindict());
225 f->f_trace = NULL;
226 if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
227 err_nomem();
228 DECREF(f);
229 return NULL;
230 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000231 return f;
232}
233
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000234object **
235extend_stack(f, level, incr)
236 frameobject *f;
237 int level;
238 int incr;
239{
240 f->f_nvalues = level + incr + 10;
241 f->f_valuestack =
242 (object **) realloc((ANY *)f->f_valuestack,
243 sizeof(object *) * (f->f_nvalues + 1));
244 if (f->f_valuestack == NULL) {
245 err_nomem();
246 return NULL;
247 }
248 return f->f_valuestack + level;
249}
250
Guido van Rossum3f5da241990-12-20 15:06:42 +0000251/* Block management */
252
253void
254setup_block(f, type, handler, level)
255 frameobject *f;
256 int type;
257 int handler;
258 int level;
259{
260 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000261 if (f->f_iblock >= f->f_nblocks)
262 fatal("XXX block stack overflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000263 b = &f->f_blockstack[f->f_iblock++];
264 b->b_type = type;
265 b->b_level = level;
266 b->b_handler = handler;
267}
268
269block *
270pop_block(f)
271 frameobject *f;
272{
273 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000274 if (f->f_iblock <= 0)
275 fatal("XXX block stack underflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000276 b = &f->f_blockstack[--f->f_iblock];
277 return b;
278}
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000279
280/* Convert between "fast" version of locals and dictionary version */
281
282void
283fast_2_locals(f)
284 frameobject *f;
285{
286 /* Merge f->f_fastlocals into f->f_locals */
287 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000288 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000289 int j;
290 if (f == NULL)
291 return;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000292 locals = f->f_locals;
293 if (locals == NULL) {
294 locals = f->f_locals = newdictobject();
295 if (locals == NULL) {
296 err_clear(); /* Can't report it :-( */
297 return;
298 }
299 }
Guido van Rossumbdd207a1995-07-26 16:14:30 +0000300 fast = f->f_fastlocals;
301 if (fast == NULL || f->f_code->co_nlocals == 0)
302 return;
303 map = f->f_code->co_varnames;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000304 if (!is_dictobject(locals) || !is_listobject(fast) ||
305 !is_tupleobject(map))
306 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000307 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000308 for (j = gettuplesize(map); --j >= 0; ) {
309 object *key = gettupleitem(map, j);
310 object *value = getlistitem(fast, j);
311 if (value == NULL) {
312 err_clear();
313 if (dict2remove(locals, key) != 0)
314 err_clear();
315 }
316 else {
317 if (dict2insert(locals, key, value) != 0)
318 err_clear();
319 }
320 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000321 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000322}
323
324void
325locals_2_fast(f, clear)
326 frameobject *f;
327 int clear;
328{
329 /* Merge f->f_locals into f->f_fastlocals */
330 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000331 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000332 int j;
333 if (f == NULL)
334 return;
335 locals = f->f_locals;
336 fast = f->f_fastlocals;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000337 map = f->f_code->co_varnames;
338 if (locals == NULL || fast == NULL || f->f_code->co_nlocals == 0)
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000339 return;
340 if (!is_dictobject(locals) || !is_listobject(fast) ||
341 !is_tupleobject(map))
342 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000343 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000344 for (j = gettuplesize(map); --j >= 0; ) {
345 object *key = gettupleitem(map, j);
346 object *value = dict2lookup(locals, key);
347 if (value == NULL)
348 err_clear();
349 else
350 INCREF(value);
351 if (value != NULL || clear)
352 if (setlistitem(fast, j, value) != 0)
353 err_clear();
354 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000355 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000356}