blob: 29cb1718c465083c5e4f992de9be9e549869033f [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"
33
34#define OFF(x) offsetof(frameobject, x)
35
36static struct memberlist frame_memberlist[] = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +000037 {"f_back", T_OBJECT, OFF(f_back), RO},
38 {"f_code", T_OBJECT, OFF(f_code), RO},
39 {"f_globals", T_OBJECT, OFF(f_globals), RO},
40 {"f_locals", T_OBJECT, OFF(f_locals), RO},
41 {"f_owner", T_OBJECT, OFF(f_owner), RO},
Guido van Rossumd7047b31995-01-02 19:07:15 +000042#if 0
43 {"f_fastlocals",T_OBJECT, OFF(f_fastlocals),RO}, /* XXX Unsafe */
44#endif
Guido van Rossum1d5735e1994-08-30 08:27:36 +000045 {"f_localmap", T_OBJECT, OFF(f_localmap),RO},
46 {"f_lasti", T_INT, OFF(f_lasti), RO},
47 {"f_lineno", T_INT, OFF(f_lineno), RO},
48 {"f_trace", T_OBJECT, OFF(f_trace)},
Guido van Rossum3f5da241990-12-20 15:06:42 +000049 {NULL} /* Sentinel */
50};
51
52static object *
53frame_getattr(f, name)
54 frameobject *f;
55 char *name;
56{
Guido van Rossum1d5735e1994-08-30 08:27:36 +000057 if (strcmp(name, "f_locals") == 0)
58 fast_2_locals(f);
Guido van Rossum3f5da241990-12-20 15:06:42 +000059 return getmember((char *)f, frame_memberlist, name);
60}
61
Guido van Rossum1d5735e1994-08-30 08:27:36 +000062static int
63frame_setattr(f, name, value)
64 frameobject *f;
65 char *name;
66 object *value;
67{
68 return setmember((char *)f, frame_memberlist, name, value);
69}
70
Guido van Rossuma9e7dc11992-10-18 18:53:57 +000071/* Stack frames are allocated and deallocated at a considerable rate.
72 In an attempt to improve the speed of function calls, we maintain a
73 separate free list of stack frames (just like integers are
74 allocated in a special way -- see intobject.c). When a stack frame
75 is on the free list, only the following members have a meaning:
76 ob_type == &Frametype
77 f_back next item on free list, or NULL
78 f_nvalues size of f_valuestack
79 f_valuestack array of (f_nvalues+1) object pointers, or NULL
80 f_nblocks size of f_blockstack
81 f_blockstack array of (f_nblocks+1) blocks, or NULL
82 Note that the value and block stacks are preserved -- this can save
83 another malloc() call or two (and two free() calls as well!).
84 Also note that, unlike for integers, each frame object is a
85 malloc'ed object in its own right -- it is only the actual calls to
86 malloc() that we are trying to save here, not the administration.
87 After all, while a typical program may make millions of calls, a
88 call depth of more than 20 or 30 is probably already exceptional
89 unless the program contains run-away recursion. I hope.
90*/
91
92static frameobject *free_list = NULL;
93
Guido van Rossum3f5da241990-12-20 15:06:42 +000094static void
95frame_dealloc(f)
96 frameobject *f;
97{
98 XDECREF(f->f_back);
99 XDECREF(f->f_code);
100 XDECREF(f->f_globals);
101 XDECREF(f->f_locals);
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000102 XDECREF(f->f_owner);
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000103 XDECREF(f->f_fastlocals);
104 XDECREF(f->f_localmap);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000105 XDECREF(f->f_trace);
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000106 f->f_back = free_list;
107 free_list = f;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000108}
109
110typeobject Frametype = {
111 OB_HEAD_INIT(&Typetype)
112 0,
113 "frame",
114 sizeof(frameobject),
115 0,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000116 (destructor)frame_dealloc, /*tp_dealloc*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000117 0, /*tp_print*/
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000118 (getattrfunc)frame_getattr, /*tp_getattr*/
119 (setattrfunc)frame_setattr, /*tp_setattr*/
Guido van Rossum3f5da241990-12-20 15:06:42 +0000120 0, /*tp_compare*/
121 0, /*tp_repr*/
122 0, /*tp_as_number*/
123 0, /*tp_as_sequence*/
124 0, /*tp_as_mapping*/
125};
126
127frameobject *
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000128newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000129 frameobject *back;
130 codeobject *code;
131 object *globals;
132 object *locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000133 object *owner;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000134 int nvalues;
135 int nblocks;
136{
137 frameobject *f;
138 if ((back != NULL && !is_frameobject(back)) ||
139 code == NULL || !is_codeobject(code) ||
140 globals == NULL || !is_dictobject(globals) ||
141 locals == NULL || !is_dictobject(locals) ||
142 nvalues < 0 || nblocks < 0) {
143 err_badcall();
144 return NULL;
145 }
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000146 if (free_list == NULL) {
147 f = NEWOBJ(frameobject, &Frametype);
148 f->f_nvalues = f->f_nblocks = 0;
149 f->f_valuestack = NULL;
150 f->f_blockstack = NULL;
151 }
152 else {
153 f = free_list;
154 free_list = free_list->f_back;
Sjoerd Mullenderf64992e1993-08-03 15:11:36 +0000155 f->ob_type = &Frametype;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000156 NEWREF(f);
157 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000158 if (f != NULL) {
159 if (back)
160 INCREF(back);
161 f->f_back = back;
162 INCREF(code);
163 f->f_code = code;
164 INCREF(globals);
165 f->f_globals = globals;
166 INCREF(locals);
167 f->f_locals = locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000168 XINCREF(owner);
169 f->f_owner = owner;
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000170 f->f_fastlocals = NULL;
171 f->f_localmap = NULL;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000172 if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
173 XDEL(f->f_valuestack);
174 f->f_valuestack = NEW(object *, nvalues+1);
175 f->f_nvalues = nvalues;
176 }
177 if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
178 XDEL(f->f_blockstack);
179 f->f_blockstack = NEW(block, nblocks+1);
180 f->f_nblocks = nblocks;
181 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000182 f->f_iblock = 0;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000183 f->f_lasti = 0;
184 f->f_lineno = -1;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000185 f->f_trace = NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000186 if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
187 err_nomem();
188 DECREF(f);
189 f = NULL;
190 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000191 }
192 return f;
193}
194
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000195object **
196extend_stack(f, level, incr)
197 frameobject *f;
198 int level;
199 int incr;
200{
201 f->f_nvalues = level + incr + 10;
202 f->f_valuestack =
203 (object **) realloc((ANY *)f->f_valuestack,
204 sizeof(object *) * (f->f_nvalues + 1));
205 if (f->f_valuestack == NULL) {
206 err_nomem();
207 return NULL;
208 }
209 return f->f_valuestack + level;
210}
211
Guido van Rossum3f5da241990-12-20 15:06:42 +0000212/* Block management */
213
214void
215setup_block(f, type, handler, level)
216 frameobject *f;
217 int type;
218 int handler;
219 int level;
220{
221 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000222 if (f->f_iblock >= f->f_nblocks)
223 fatal("XXX block stack overflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000224 b = &f->f_blockstack[f->f_iblock++];
225 b->b_type = type;
226 b->b_level = level;
227 b->b_handler = handler;
228}
229
230block *
231pop_block(f)
232 frameobject *f;
233{
234 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000235 if (f->f_iblock <= 0)
236 fatal("XXX block stack underflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000237 b = &f->f_blockstack[--f->f_iblock];
238 return b;
239}
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000240
241/* Convert between "fast" version of locals and dictionary version */
242
243void
244fast_2_locals(f)
245 frameobject *f;
246{
247 /* Merge f->f_fastlocals into f->f_locals */
248 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000249 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000250 int j;
251 if (f == NULL)
252 return;
253 locals = f->f_locals;
254 fast = f->f_fastlocals;
255 map = f->f_localmap;
256 if (locals == NULL || fast == NULL || map == NULL)
257 return;
258 if (!is_dictobject(locals) || !is_listobject(fast) ||
259 !is_tupleobject(map))
260 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000261 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000262 for (j = gettuplesize(map); --j >= 0; ) {
263 object *key = gettupleitem(map, j);
264 object *value = getlistitem(fast, j);
265 if (value == NULL) {
266 err_clear();
267 if (dict2remove(locals, key) != 0)
268 err_clear();
269 }
270 else {
271 if (dict2insert(locals, key, value) != 0)
272 err_clear();
273 }
274 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000275 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000276}
277
278void
279locals_2_fast(f, clear)
280 frameobject *f;
281 int clear;
282{
283 /* Merge f->f_locals into f->f_fastlocals */
284 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000285 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000286 int j;
287 if (f == NULL)
288 return;
289 locals = f->f_locals;
290 fast = f->f_fastlocals;
291 map = f->f_localmap;
292 if (locals == NULL || fast == NULL || map == NULL)
293 return;
294 if (!is_dictobject(locals) || !is_listobject(fast) ||
295 !is_tupleobject(map))
296 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000297 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000298 for (j = gettuplesize(map); --j >= 0; ) {
299 object *key = gettupleitem(map, j);
300 object *value = dict2lookup(locals, key);
301 if (value == NULL)
302 err_clear();
303 else
304 INCREF(value);
305 if (value != NULL || clear)
306 if (setlistitem(fast, j, value) != 0)
307 err_clear();
308 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000309 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000310}