blob: 62a18e20b6a4c7ee8322974cb4765f91151a9f41 [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;
140 NEWREF(f);
141 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000142 if (f != NULL) {
143 if (back)
144 INCREF(back);
145 f->f_back = back;
146 INCREF(code);
147 f->f_code = code;
148 INCREF(globals);
149 f->f_globals = globals;
150 INCREF(locals);
151 f->f_locals = locals;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000152 XINCREF(owner);
153 f->f_owner = owner;
Guido van Rossum8b17d6b1993-03-30 13:18:41 +0000154 f->f_fastlocals = NULL;
155 f->f_localmap = NULL;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000156 if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
157 XDEL(f->f_valuestack);
158 f->f_valuestack = NEW(object *, nvalues+1);
159 f->f_nvalues = nvalues;
160 }
161 if (nblocks > f->f_nblocks || f->f_blockstack == NULL) {
162 XDEL(f->f_blockstack);
163 f->f_blockstack = NEW(block, nblocks+1);
164 f->f_nblocks = nblocks;
165 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000166 f->f_iblock = 0;
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000167 f->f_lasti = 0;
168 f->f_lineno = -1;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000169 if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
170 err_nomem();
171 DECREF(f);
172 f = NULL;
173 }
Guido van Rossum3f5da241990-12-20 15:06:42 +0000174 }
175 return f;
176}
177
Guido van Rossuma9e7dc11992-10-18 18:53:57 +0000178object **
179extend_stack(f, level, incr)
180 frameobject *f;
181 int level;
182 int incr;
183{
184 f->f_nvalues = level + incr + 10;
185 f->f_valuestack =
186 (object **) realloc((ANY *)f->f_valuestack,
187 sizeof(object *) * (f->f_nvalues + 1));
188 if (f->f_valuestack == NULL) {
189 err_nomem();
190 return NULL;
191 }
192 return f->f_valuestack + level;
193}
194
Guido van Rossum3f5da241990-12-20 15:06:42 +0000195/* Block management */
196
197void
198setup_block(f, type, handler, level)
199 frameobject *f;
200 int type;
201 int handler;
202 int level;
203{
204 block *b;
205 if (f->f_iblock >= f->f_nblocks) {
206 fprintf(stderr, "XXX block stack overflow\n");
207 abort();
208 }
209 b = &f->f_blockstack[f->f_iblock++];
210 b->b_type = type;
211 b->b_level = level;
212 b->b_handler = handler;
213}
214
215block *
216pop_block(f)
217 frameobject *f;
218{
219 block *b;
220 if (f->f_iblock <= 0) {
221 fprintf(stderr, "XXX block stack underflow\n");
222 abort();
223 }
224 b = &f->f_blockstack[--f->f_iblock];
225 return b;
226}