blob: b2884080bcd96c2018b2c80aae47aeec68813b14 [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;
184 if ((code->co_flags & (CO_NEWLOCALS|CO_OPTIMIZED)) == CO_NEWLOCALS) {
185 locals = newdictobject();
186 if (locals == NULL) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000187 DECREF(f);
Guido van Rossum2271bf71995-07-18 14:30:34 +0000188 return NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000189 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000190 }
Guido van Rossum2271bf71995-07-18 14:30:34 +0000191 else {
192 if (locals == NULL)
193 locals = globals;
194 INCREF(locals);
195 }
196 f->f_locals = locals;
197 XINCREF(owner);
198 f->f_owner = owner;
199 f->f_fastlocals = NULL;
200 if (code->co_nlocals > 0) {
201 f->f_fastlocals = newlistobject(code->co_nlocals);
202 if (f->f_fastlocals == NULL) {
203 DECREF(f);
204 return NULL;
205 }
206 }
207 if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
208 XDEL(f->f_valuestack);
209 f->f_valuestack = NEW(object *, nvalues+1);
210 f->f_nvalues = nvalues;
211 }
212 if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
213 XDEL(f->f_blockstack);
214 f->f_blockstack = NEW(block, nblocks+1);
215 f->f_nblocks = nblocks;
216 }
217 f->f_iblock = 0;
218 f->f_lasti = 0;
219 f->f_lineno = -1;
220 f->f_restricted = (builtins != getbuiltindict());
221 f->f_trace = NULL;
222 if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
223 err_nomem();
224 DECREF(f);
225 return NULL;
226 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000227 return f;
228}
229
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000230object **
231extend_stack(f, level, incr)
232 frameobject *f;
233 int level;
234 int incr;
235{
236 f->f_nvalues = level + incr + 10;
237 f->f_valuestack =
238 (object **) realloc((ANY *)f->f_valuestack,
239 sizeof(object *) * (f->f_nvalues + 1));
240 if (f->f_valuestack == NULL) {
241 err_nomem();
242 return NULL;
243 }
244 return f->f_valuestack + level;
245}
246
Guido van Rossum3f5da241990-12-20 15:06:42 +0000247/* Block management */
248
249void
250setup_block(f, type, handler, level)
251 frameobject *f;
252 int type;
253 int handler;
254 int level;
255{
256 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000257 if (f->f_iblock >= f->f_nblocks)
258 fatal("XXX block stack overflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000259 b = &f->f_blockstack[f->f_iblock++];
260 b->b_type = type;
261 b->b_level = level;
262 b->b_handler = handler;
263}
264
265block *
266pop_block(f)
267 frameobject *f;
268{
269 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000270 if (f->f_iblock <= 0)
271 fatal("XXX block stack underflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000272 b = &f->f_blockstack[--f->f_iblock];
273 return b;
274}
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000275
276/* Convert between "fast" version of locals and dictionary version */
277
278void
279fast_2_locals(f)
280 frameobject *f;
281{
282 /* Merge f->f_fastlocals into f->f_locals */
283 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000284 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000285 int j;
286 if (f == NULL)
287 return;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000288 fast = f->f_fastlocals;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000289 if (fast == NULL || f->f_code->co_nlocals == 0)
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000290 return;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000291 map = f->f_code->co_varnames;
292 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 Rossum1d5735e1994-08-30 08:27:36 +0000300 if (!is_dictobject(locals) || !is_listobject(fast) ||
301 !is_tupleobject(map))
302 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000303 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000304 for (j = gettuplesize(map); --j >= 0; ) {
305 object *key = gettupleitem(map, j);
306 object *value = getlistitem(fast, j);
307 if (value == NULL) {
308 err_clear();
309 if (dict2remove(locals, key) != 0)
310 err_clear();
311 }
312 else {
313 if (dict2insert(locals, key, value) != 0)
314 err_clear();
315 }
316 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000317 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000318}
319
320void
321locals_2_fast(f, clear)
322 frameobject *f;
323 int clear;
324{
325 /* Merge f->f_locals into f->f_fastlocals */
326 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000327 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000328 int j;
329 if (f == NULL)
330 return;
331 locals = f->f_locals;
332 fast = f->f_fastlocals;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000333 map = f->f_code->co_varnames;
334 if (locals == NULL || fast == NULL || f->f_code->co_nlocals == 0)
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000335 return;
336 if (!is_dictobject(locals) || !is_listobject(fast) ||
337 !is_tupleobject(map))
338 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000339 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000340 for (j = gettuplesize(map); --j >= 0; ) {
341 object *key = gettupleitem(map, j);
342 object *value = dict2lookup(locals, key);
343 if (value == NULL)
344 err_clear();
345 else
346 INCREF(value);
347 if (value != NULL || clear)
348 if (setlistitem(fast, j, value) != 0)
349 err_clear();
350 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000351 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000352}