blob: aa2979577e718f2299c77f53eec0e984de162556 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum9bfef441993-03-29 10:43:31 +00002Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The 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[] = {
37 {"f_back", T_OBJECT, OFF(f_back)},
38 {"f_code", T_OBJECT, OFF(f_code)},
39 {"f_globals", T_OBJECT, OFF(f_globals)},
40 {"f_locals", T_OBJECT, OFF(f_locals)},
Guido van Rossum5b722181993-03-30 17:46:03 +000041/* {"f_fastlocals",T_OBJECT, OFF(f_fastlocals)}, /* XXX Unsafe */
Guido van Rossum8b17d6b1993-03-30 13:18:41 +000042 {"f_localmap", T_OBJECT, OFF(f_localmap)},
Guido van Rossum088bc2a1992-01-14 18:32:11 +000043 {"f_lasti", T_INT, OFF(f_lasti)},
44 {"f_lineno", T_INT, OFF(f_lineno)},
Guido van Rossum3f5da241990-12-20 15:06:42 +000045 {NULL} /* Sentinel */
46};
47
48static object *
49frame_getattr(f, name)
50 frameobject *f;
51 char *name;
52{
53 return getmember((char *)f, frame_memberlist, name);
54}
55
Guido van Rossuma9e7dc11992-10-18 18:53:57 +000056/* Stack frames are allocated and deallocated at a considerable rate.
57 In an attempt to improve the speed of function calls, we maintain a
58 separate free list of stack frames (just like integers are
59 allocated in a special way -- see intobject.c). When a stack frame
60 is on the free list, only the following members have a meaning:
61 ob_type == &Frametype
62 f_back next item on free list, or NULL
63 f_nvalues size of f_valuestack
64 f_valuestack array of (f_nvalues+1) object pointers, or NULL
65 f_nblocks size of f_blockstack
66 f_blockstack array of (f_nblocks+1) blocks, or NULL
67 Note that the value and block stacks are preserved -- this can save
68 another malloc() call or two (and two free() calls as well!).
69 Also note that, unlike for integers, each frame object is a
70 malloc'ed object in its own right -- it is only the actual calls to
71 malloc() that we are trying to save here, not the administration.
72 After all, while a typical program may make millions of calls, a
73 call depth of more than 20 or 30 is probably already exceptional
74 unless the program contains run-away recursion. I hope.
75*/
76
77static frameobject *free_list = NULL;
78
Guido van Rossum3f5da241990-12-20 15:06:42 +000079static void
80frame_dealloc(f)
81 frameobject *f;
82{
83 XDECREF(f->f_back);
84 XDECREF(f->f_code);
85 XDECREF(f->f_globals);
86 XDECREF(f->f_locals);
Guido van Rossum8b17d6b1993-03-30 13:18:41 +000087 XDECREF(f->f_fastlocals);
88 XDECREF(f->f_localmap);
Guido van Rossuma9e7dc11992-10-18 18:53:57 +000089 f->f_back = free_list;
90 free_list = f;
Guido van Rossum3f5da241990-12-20 15:06:42 +000091}
92
93typeobject Frametype = {
94 OB_HEAD_INIT(&Typetype)
95 0,
96 "frame",
97 sizeof(frameobject),
98 0,
99 frame_dealloc, /*tp_dealloc*/
100 0, /*tp_print*/
101 frame_getattr, /*tp_getattr*/
102 0, /*tp_setattr*/
103 0, /*tp_compare*/
104 0, /*tp_repr*/
105 0, /*tp_as_number*/
106 0, /*tp_as_sequence*/
107 0, /*tp_as_mapping*/
108};
109
110frameobject *
111newframeobject(back, code, globals, locals, nvalues, nblocks)
112 frameobject *back;
113 codeobject *code;
114 object *globals;
115 object *locals;
116 int nvalues;
117 int nblocks;
118{
119 frameobject *f;
120 if ((back != NULL && !is_frameobject(back)) ||
121 code == NULL || !is_codeobject(code) ||
122 globals == NULL || !is_dictobject(globals) ||
123 locals == NULL || !is_dictobject(locals) ||
124 nvalues < 0 || nblocks < 0) {
125 err_badcall();
126 return NULL;
127 }
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000128 if (free_list == NULL) {
129 f = NEWOBJ(frameobject, &Frametype);
130 f->f_nvalues = f->f_nblocks = 0;
131 f->f_valuestack = NULL;
132 f->f_blockstack = NULL;
133 }
134 else {
135 f = free_list;
136 free_list = free_list->f_back;
137 NEWREF(f);
138 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000139 if (f != NULL) {
140 if (back)
141 INCREF(back);
142 f->f_back = back;
143 INCREF(code);
144 f->f_code = code;
145 INCREF(globals);
146 f->f_globals = globals;
147 INCREF(locals);
148 f->f_locals = locals;
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000149 f->f_fastlocals = NULL;
150 f->f_localmap = NULL;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000151 if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
152 XDEL(f->f_valuestack);
153 f->f_valuestack = NEW(object *, nvalues+1);
154 f->f_nvalues = nvalues;
155 }
156 if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
157 XDEL(f->f_blockstack);
158 f->f_blockstack = NEW(block, nblocks+1);
159 f->f_nblocks = nblocks;
160 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000161 f->f_iblock = 0;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000162 f->f_lasti = 0;
163 f->f_lineno = -1;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000164 if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
165 err_nomem();
166 DECREF(f);
167 f = NULL;
168 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000169 }
170 return f;
171}
172
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000173object **
174extend_stack(f, level, incr)
175 frameobject *f;
176 int level;
177 int incr;
178{
179 f->f_nvalues = level + incr + 10;
180 f->f_valuestack =
181 (object **) realloc((ANY *)f->f_valuestack,
182 sizeof(object *) * (f->f_nvalues + 1));
183 if (f->f_valuestack == NULL) {
184 err_nomem();
185 return NULL;
186 }
187 return f->f_valuestack + level;
188}
189
Guido van Rossum3f5da241990-12-20 15:06:42 +0000190/* Block management */
191
192void
193setup_block(f, type, handler, level)
194 frameobject *f;
195 int type;
196 int handler;
197 int level;
198{
199 block *b;
200 if (f->f_iblock >= f->f_nblocks) {
201 fprintf(stderr, "XXX block stack overflow\n");
202 abort();
203 }
204 b = &f->f_blockstack[f->f_iblock++];
205 b->b_type = type;
206 b->b_level = level;
207 b->b_handler = handler;
208}
209
210block *
211pop_block(f)
212 frameobject *f;
213{
214 block *b;
215 if (f->f_iblock <= 0) {
216 fprintf(stderr, "XXX block stack underflow\n");
217 abort();
218 }
219 b = &f->f_blockstack[--f->f_iblock];
220 return b;
221}