blob: 0b5e75c034591e6890d336e246dcbb5b4bf60828 [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 Rossumeb6b33a1993-05-25 09:38:27 +000041 {"f_owner", T_OBJECT, OFF(f_owner)},
Guido van Rossum5b722181993-03-30 17:46:03 +000042/* {"f_fastlocals",T_OBJECT, OFF(f_fastlocals)}, /* XXX Unsafe */
Guido van Rossum8b17d6b1993-03-30 13:18:41 +000043 {"f_localmap", T_OBJECT, OFF(f_localmap)},
Guido van Rossum088bc2a1992-01-14 18:32:11 +000044 {"f_lasti", T_INT, OFF(f_lasti)},
45 {"f_lineno", T_INT, OFF(f_lineno)},
Guido van Rossum3f5da241990-12-20 15:06:42 +000046 {NULL} /* Sentinel */
47};
48
49static object *
50frame_getattr(f, name)
51 frameobject *f;
52 char *name;
53{
54 return getmember((char *)f, frame_memberlist, name);
55}
56
Guido van Rossuma9e7dc11992-10-18 18:53:57 +000057/* Stack frames are allocated and deallocated at a considerable rate.
58 In an attempt to improve the speed of function calls, we maintain a
59 separate free list of stack frames (just like integers are
60 allocated in a special way -- see intobject.c). When a stack frame
61 is on the free list, only the following members have a meaning:
62 ob_type == &Frametype
63 f_back next item on free list, or NULL
64 f_nvalues size of f_valuestack
65 f_valuestack array of (f_nvalues+1) object pointers, or NULL
66 f_nblocks size of f_blockstack
67 f_blockstack array of (f_nblocks+1) blocks, or NULL
68 Note that the value and block stacks are preserved -- this can save
69 another malloc() call or two (and two free() calls as well!).
70 Also note that, unlike for integers, each frame object is a
71 malloc'ed object in its own right -- it is only the actual calls to
72 malloc() that we are trying to save here, not the administration.
73 After all, while a typical program may make millions of calls, a
74 call depth of more than 20 or 30 is probably already exceptional
75 unless the program contains run-away recursion. I hope.
76*/
77
78static frameobject *free_list = NULL;
79
Guido van Rossum3f5da241990-12-20 15:06:42 +000080static void
81frame_dealloc(f)
82 frameobject *f;
83{
84 XDECREF(f->f_back);
85 XDECREF(f->f_code);
86 XDECREF(f->f_globals);
87 XDECREF(f->f_locals);
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000088 XDECREF(f->f_owner);
Guido van Rossum8b17d6b1993-03-30 13:18:41 +000089 XDECREF(f->f_fastlocals);
90 XDECREF(f->f_localmap);
Guido van Rossuma9e7dc11992-10-18 18:53:57 +000091 f->f_back = free_list;
92 free_list = f;
Guido van Rossum3f5da241990-12-20 15:06:42 +000093}
94
95typeobject Frametype = {
96 OB_HEAD_INIT(&Typetype)
97 0,
98 "frame",
99 sizeof(frameobject),
100 0,
101 frame_dealloc, /*tp_dealloc*/
102 0, /*tp_print*/
103 frame_getattr, /*tp_getattr*/
104 0, /*tp_setattr*/
105 0, /*tp_compare*/
106 0, /*tp_repr*/
107 0, /*tp_as_number*/
108 0, /*tp_as_sequence*/
109 0, /*tp_as_mapping*/
110};
111
112frameobject *
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000113newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000114 frameobject *back;
115 codeobject *code;
116 object *globals;
117 object *locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000118 object *owner;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000119 int nvalues;
120 int nblocks;
121{
122 frameobject *f;
123 if ((back != NULL && !is_frameobject(back)) ||
124 code == NULL || !is_codeobject(code) ||
125 globals == NULL || !is_dictobject(globals) ||
126 locals == NULL || !is_dictobject(locals) ||
127 nvalues < 0 || nblocks < 0) {
128 err_badcall();
129 return NULL;
130 }
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000131 if (free_list == NULL) {
132 f = NEWOBJ(frameobject, &Frametype);
133 f->f_nvalues = f->f_nblocks = 0;
134 f->f_valuestack = NULL;
135 f->f_blockstack = NULL;
136 }
137 else {
138 f = free_list;
139 free_list = free_list->f_back;
Sjoerd Mullenderf64992e1993-08-03 15:11:36 +0000140 f->ob_type = &Frametype;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000141 NEWREF(f);
142 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000143 if (f != NULL) {
144 if (back)
145 INCREF(back);
146 f->f_back = back;
147 INCREF(code);
148 f->f_code = code;
149 INCREF(globals);
150 f->f_globals = globals;
151 INCREF(locals);
152 f->f_locals = locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000153 XINCREF(owner);
154 f->f_owner = owner;
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000155 f->f_fastlocals = NULL;
156 f->f_localmap = NULL;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000157 if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
158 XDEL(f->f_valuestack);
159 f->f_valuestack = NEW(object *, nvalues+1);
160 f->f_nvalues = nvalues;
161 }
162 if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
163 XDEL(f->f_blockstack);
164 f->f_blockstack = NEW(block, nblocks+1);
165 f->f_nblocks = nblocks;
166 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000167 f->f_iblock = 0;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000168 f->f_lasti = 0;
169 f->f_lineno = -1;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000170 if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
171 err_nomem();
172 DECREF(f);
173 f = NULL;
174 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000175 }
176 return f;
177}
178
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000179object **
180extend_stack(f, level, incr)
181 frameobject *f;
182 int level;
183 int incr;
184{
185 f->f_nvalues = level + incr + 10;
186 f->f_valuestack =
187 (object **) realloc((ANY *)f->f_valuestack,
188 sizeof(object *) * (f->f_nvalues + 1));
189 if (f->f_valuestack == NULL) {
190 err_nomem();
191 return NULL;
192 }
193 return f->f_valuestack + level;
194}
195
Guido van Rossum3f5da241990-12-20 15:06:42 +0000196/* Block management */
197
198void
199setup_block(f, type, handler, level)
200 frameobject *f;
201 int type;
202 int handler;
203 int level;
204{
205 block *b;
206 if (f->f_iblock >= f->f_nblocks) {
207 fprintf(stderr, "XXX block stack overflow\n");
208 abort();
209 }
210 b = &f->f_blockstack[f->f_iblock++];
211 b->b_type = type;
212 b->b_level = level;
213 b->b_handler = handler;
214}
215
216block *
217pop_block(f)
218 frameobject *f;
219{
220 block *b;
221 if (f->f_iblock <= 0) {
222 fprintf(stderr, "XXX block stack underflow\n");
223 abort();
224 }
225 b = &f->f_blockstack[--f->f_iblock];
226 return b;
227}