blob: 52b4e52455dbe5ba6e3db18b10f2f05ca8869634 [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_localmap", T_OBJECT, OFF(f_localmap),RO},
48 {"f_lasti", T_INT, OFF(f_lasti), RO},
49 {"f_lineno", T_INT, OFF(f_lineno), RO},
Guido van Rossumc1134821995-01-10 10:39:16 +000050 {"f_restricted",T_INT, OFF(f_restricted),RO},
Guido van Rossum1d5735e1994-08-30 08:27:36 +000051 {"f_trace", T_OBJECT, OFF(f_trace)},
Guido van Rossum3f5da241990-12-20 15:06:42 +000052 {NULL} /* Sentinel */
53};
54
55static object *
56frame_getattr(f, name)
57 frameobject *f;
58 char *name;
59{
Guido van Rossum1d5735e1994-08-30 08:27:36 +000060 if (strcmp(name, "f_locals") == 0)
61 fast_2_locals(f);
Guido van Rossum3f5da241990-12-20 15:06:42 +000062 return getmember((char *)f, frame_memberlist, name);
63}
64
Guido van Rossum1d5735e1994-08-30 08:27:36 +000065static int
66frame_setattr(f, name, value)
67 frameobject *f;
68 char *name;
69 object *value;
70{
71 return setmember((char *)f, frame_memberlist, name, value);
72}
73
Guido van Rossuma9e7dc11992-10-18 18:53:57 +000074/* Stack frames are allocated and deallocated at a considerable rate.
75 In an attempt to improve the speed of function calls, we maintain a
76 separate free list of stack frames (just like integers are
77 allocated in a special way -- see intobject.c). When a stack frame
78 is on the free list, only the following members have a meaning:
79 ob_type == &Frametype
80 f_back next item on free list, or NULL
81 f_nvalues size of f_valuestack
82 f_valuestack array of (f_nvalues+1) object pointers, or NULL
83 f_nblocks size of f_blockstack
84 f_blockstack array of (f_nblocks+1) blocks, or NULL
85 Note that the value and block stacks are preserved -- this can save
86 another malloc() call or two (and two free() calls as well!).
87 Also note that, unlike for integers, each frame object is a
88 malloc'ed object in its own right -- it is only the actual calls to
89 malloc() that we are trying to save here, not the administration.
90 After all, while a typical program may make millions of calls, a
91 call depth of more than 20 or 30 is probably already exceptional
92 unless the program contains run-away recursion. I hope.
93*/
94
95static frameobject *free_list = NULL;
96
Guido van Rossum3f5da241990-12-20 15:06:42 +000097static void
98frame_dealloc(f)
99 frameobject *f;
100{
101 XDECREF(f->f_back);
102 XDECREF(f->f_code);
Guido van Rossumc1134821995-01-10 10:39:16 +0000103 XDECREF(f->f_builtins);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000104 XDECREF(f->f_globals);
105 XDECREF(f->f_locals);
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000106 XDECREF(f->f_owner);
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000107 XDECREF(f->f_fastlocals);
108 XDECREF(f->f_localmap);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000109 XDECREF(f->f_trace);
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000110 f->f_back = free_list;
111 free_list = f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000112}
113
114typeobject Frametype = {
115 OB_HEAD_INIT(&Typetype)
116 0,
117 "frame",
118 sizeof(frameobject),
119 0,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000120 (destructor)frame_dealloc, /*tp_dealloc*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000121 0, /*tp_print*/
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000122 (getattrfunc)frame_getattr, /*tp_getattr*/
123 (setattrfunc)frame_setattr, /*tp_setattr*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000124 0, /*tp_compare*/
125 0, /*tp_repr*/
126 0, /*tp_as_number*/
127 0, /*tp_as_sequence*/
128 0, /*tp_as_mapping*/
129};
130
131frameobject *
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000132newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000133 frameobject *back;
134 codeobject *code;
135 object *globals;
136 object *locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000137 object *owner;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000138 int nvalues;
139 int nblocks;
140{
141 frameobject *f;
Guido van Rossumc1134821995-01-10 10:39:16 +0000142 object *builtins;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000143 if ((back != NULL && !is_frameobject(back)) ||
144 code == NULL || !is_codeobject(code) ||
145 globals == NULL || !is_dictobject(globals) ||
146 locals == NULL || !is_dictobject(locals) ||
147 nvalues < 0 || nblocks < 0) {
148 err_badcall();
149 return NULL;
150 }
Guido van Rossumc1134821995-01-10 10:39:16 +0000151 builtins = dictlookup(globals, "__builtins__");
152 if (builtins == NULL || !is_mappingobject(builtins)) {
153 err_setstr(TypeError, "bad __builtins__ dictionary");
154 return NULL;
155 }
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000156 if (free_list == NULL) {
157 f = NEWOBJ(frameobject, &Frametype);
158 f->f_nvalues = f->f_nblocks = 0;
159 f->f_valuestack = NULL;
160 f->f_blockstack = NULL;
161 }
162 else {
163 f = free_list;
164 free_list = free_list->f_back;
Sjoerd Mullenderf64992e1993-08-03 15:11:36 +0000165 f->ob_type = &Frametype;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000166 NEWREF(f);
167 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000168 if (f != NULL) {
Guido van Rossumc1134821995-01-10 10:39:16 +0000169 XINCREF(back);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000170 f->f_back = back;
171 INCREF(code);
172 f->f_code = code;
Guido van Rossumc1134821995-01-10 10:39:16 +0000173 XINCREF(builtins);
174 f->f_builtins = builtins;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000175 INCREF(globals);
176 f->f_globals = globals;
177 INCREF(locals);
178 f->f_locals = locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000179 XINCREF(owner);
180 f->f_owner = owner;
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000181 f->f_fastlocals = NULL;
182 f->f_localmap = NULL;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000183 if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
184 XDEL(f->f_valuestack);
185 f->f_valuestack = NEW(object *, nvalues+1);
186 f->f_nvalues = nvalues;
187 }
188 if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
189 XDEL(f->f_blockstack);
190 f->f_blockstack = NEW(block, nblocks+1);
191 f->f_nblocks = nblocks;
192 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000193 f->f_iblock = 0;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000194 f->f_lasti = 0;
195 f->f_lineno = -1;
Guido van Rossumc1134821995-01-10 10:39:16 +0000196 f->f_restricted = (builtins != getbuiltindict());
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000197 f->f_trace = NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000198 if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
199 err_nomem();
200 DECREF(f);
201 f = NULL;
202 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000203 }
204 return f;
205}
206
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000207object **
208extend_stack(f, level, incr)
209 frameobject *f;
210 int level;
211 int incr;
212{
213 f->f_nvalues = level + incr + 10;
214 f->f_valuestack =
215 (object **) realloc((ANY *)f->f_valuestack,
216 sizeof(object *) * (f->f_nvalues + 1));
217 if (f->f_valuestack == NULL) {
218 err_nomem();
219 return NULL;
220 }
221 return f->f_valuestack + level;
222}
223
Guido van Rossum3f5da241990-12-20 15:06:42 +0000224/* Block management */
225
226void
227setup_block(f, type, handler, level)
228 frameobject *f;
229 int type;
230 int handler;
231 int level;
232{
233 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000234 if (f->f_iblock >= f->f_nblocks)
235 fatal("XXX block stack overflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000236 b = &f->f_blockstack[f->f_iblock++];
237 b->b_type = type;
238 b->b_level = level;
239 b->b_handler = handler;
240}
241
242block *
243pop_block(f)
244 frameobject *f;
245{
246 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000247 if (f->f_iblock <= 0)
248 fatal("XXX block stack underflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000249 b = &f->f_blockstack[--f->f_iblock];
250 return b;
251}
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000252
253/* Convert between "fast" version of locals and dictionary version */
254
255void
256fast_2_locals(f)
257 frameobject *f;
258{
259 /* Merge f->f_fastlocals into f->f_locals */
260 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000261 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000262 int j;
263 if (f == NULL)
264 return;
265 locals = f->f_locals;
266 fast = f->f_fastlocals;
267 map = f->f_localmap;
268 if (locals == NULL || fast == NULL || map == NULL)
269 return;
270 if (!is_dictobject(locals) || !is_listobject(fast) ||
271 !is_tupleobject(map))
272 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000273 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000274 for (j = gettuplesize(map); --j >= 0; ) {
275 object *key = gettupleitem(map, j);
276 object *value = getlistitem(fast, j);
277 if (value == NULL) {
278 err_clear();
279 if (dict2remove(locals, key) != 0)
280 err_clear();
281 }
282 else {
283 if (dict2insert(locals, key, value) != 0)
284 err_clear();
285 }
286 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000287 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000288}
289
290void
291locals_2_fast(f, clear)
292 frameobject *f;
293 int clear;
294{
295 /* Merge f->f_locals into f->f_fastlocals */
296 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000297 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000298 int j;
299 if (f == NULL)
300 return;
301 locals = f->f_locals;
302 fast = f->f_fastlocals;
303 map = f->f_localmap;
304 if (locals == NULL || fast == NULL || map == NULL)
305 return;
306 if (!is_dictobject(locals) || !is_listobject(fast) ||
307 !is_tupleobject(map))
308 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000309 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000310 for (j = gettuplesize(map); --j >= 0; ) {
311 object *key = gettupleitem(map, j);
312 object *value = dict2lookup(locals, key);
313 if (value == NULL)
314 err_clear();
315 else
316 INCREF(value);
317 if (value != NULL || clear)
318 if (setlistitem(fast, j, value) != 0)
319 err_clear();
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}