frameobject.c revision f64992e95d3b87799d4a423d2d0c0047b177c56b
1/***********************************************************
2Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
4
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
25/* 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)},
41	{"f_owner",	T_OBJECT,	OFF(f_owner)},
42/*	{"f_fastlocals",T_OBJECT,	OFF(f_fastlocals)}, /* XXX Unsafe */
43	{"f_localmap",	T_OBJECT,	OFF(f_localmap)},
44	{"f_lasti",	T_INT,		OFF(f_lasti)},
45	{"f_lineno",	T_INT,		OFF(f_lineno)},
46	{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
57/* 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
80static 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);
88	XDECREF(f->f_owner);
89	XDECREF(f->f_fastlocals);
90	XDECREF(f->f_localmap);
91	f->f_back = free_list;
92	free_list = f;
93}
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 *
113newframeobject(back, code, globals, locals, owner, nvalues, nblocks)
114	frameobject *back;
115	codeobject *code;
116	object *globals;
117	object *locals;
118	object *owner;
119	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	}
131	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		f->ob_type = &Frametype;
141		NEWREF(f);
142	}
143	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;
153		XINCREF(owner);
154		f->f_owner = owner;
155		f->f_fastlocals = NULL;
156		f->f_localmap = NULL;
157		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		}
167		f->f_iblock = 0;
168		f->f_lasti = 0;
169		f->f_lineno = -1;
170		if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
171			err_nomem();
172			DECREF(f);
173			f = NULL;
174		}
175	}
176	return f;
177}
178
179object **
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
196/* 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}
228