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