blob: 546f1e8d722bc104e72a563d3a4e0afd6da757b1 [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) {
Guido van Rossumb56933e1997-01-18 07:58:41 +0000150 builtin_object = PyString_InternFromString("__builtins__");
Sjoerd Mullender5b7f3cd1995-04-04 11:47:41 +0000151 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 Rossumda9c2711996-12-05 21:58:58 +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 Rossum792fd431997-01-17 21:07:57 +0000241#if 0
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000242object **
243extend_stack(f, level, incr)
244 frameobject *f;
245 int level;
246 int incr;
247{
248 f->f_nvalues = level + incr + 10;
249 f->f_valuestack =
250 (object **) realloc((ANY *)f->f_valuestack,
251 sizeof(object *) * (f->f_nvalues + 1));
252 if (f->f_valuestack == NULL) {
253 err_nomem();
254 return NULL;
255 }
256 return f->f_valuestack + level;
257}
Guido van Rossum792fd431997-01-17 21:07:57 +0000258#endif
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000259
Guido van Rossum3f5da241990-12-20 15:06:42 +0000260/* Block management */
261
262void
263setup_block(f, type, handler, level)
264 frameobject *f;
265 int type;
266 int handler;
267 int level;
268{
269 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000270 if (f->f_iblock >= f->f_nblocks)
271 fatal("XXX block stack overflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000272 b = &f->f_blockstack[f->f_iblock++];
273 b->b_type = type;
274 b->b_level = level;
275 b->b_handler = handler;
276}
277
278block *
279pop_block(f)
280 frameobject *f;
281{
282 block *b;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000283 if (f->f_iblock <= 0)
284 fatal("XXX block stack underflow");
Guido van Rossum3f5da241990-12-20 15:06:42 +0000285 b = &f->f_blockstack[--f->f_iblock];
286 return b;
287}
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000288
289/* Convert between "fast" version of locals and dictionary version */
290
291void
292fast_2_locals(f)
293 frameobject *f;
294{
295 /* Merge f->f_fastlocals into f->f_locals */
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;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000301 locals = f->f_locals;
302 if (locals == NULL) {
303 locals = f->f_locals = newdictobject();
304 if (locals == NULL) {
305 err_clear(); /* Can't report it :-( */
306 return;
307 }
308 }
Guido van Rossumbdd207a1995-07-26 16:14:30 +0000309 fast = f->f_fastlocals;
310 if (fast == NULL || f->f_code->co_nlocals == 0)
311 return;
312 map = f->f_code->co_varnames;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000313 if (!is_dictobject(locals) || !is_listobject(fast) ||
314 !is_tupleobject(map))
315 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000316 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000317 for (j = gettuplesize(map); --j >= 0; ) {
318 object *key = gettupleitem(map, j);
319 object *value = getlistitem(fast, j);
320 if (value == NULL) {
321 err_clear();
322 if (dict2remove(locals, key) != 0)
323 err_clear();
324 }
325 else {
326 if (dict2insert(locals, key, value) != 0)
327 err_clear();
328 }
329 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000330 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000331}
332
333void
334locals_2_fast(f, clear)
335 frameobject *f;
336 int clear;
337{
338 /* Merge f->f_locals into f->f_fastlocals */
339 object *locals, *fast, *map;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000340 object *error_type, *error_value, *error_traceback;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000341 int j;
342 if (f == NULL)
343 return;
344 locals = f->f_locals;
345 fast = f->f_fastlocals;
Guido van Rossum2271bf71995-07-18 14:30:34 +0000346 map = f->f_code->co_varnames;
347 if (locals == NULL || fast == NULL || f->f_code->co_nlocals == 0)
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000348 return;
349 if (!is_dictobject(locals) || !is_listobject(fast) ||
350 !is_tupleobject(map))
351 return;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000352 err_fetch(&error_type, &error_value, &error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000353 for (j = gettuplesize(map); --j >= 0; ) {
354 object *key = gettupleitem(map, j);
355 object *value = dict2lookup(locals, key);
356 if (value == NULL)
357 err_clear();
358 else
359 INCREF(value);
360 if (value != NULL || clear)
361 if (setlistitem(fast, j, value) != 0)
362 err_clear();
363 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000364 err_restore(error_type, error_value, error_traceback);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000365}