frameobject.c revision 7582bfb60a7027b57d79c44a5e8531a31d1a8f2a
1/*********************************************************** 2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, 3The 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 or Corporation for National Research Initiatives or 13CNRI not be used in advertising or publicity pertaining to 14distribution of the software without specific, written prior 15permission. 16 17While CWI is the initial source for this software, a modified version 18is made available by the Corporation for National Research Initiatives 19(CNRI) at the Internet address ftp://ftp.python.org. 20 21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH 22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH 24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 28PERFORMANCE OF THIS SOFTWARE. 29 30******************************************************************/ 31 32/* Frame object implementation */ 33 34#include "allobjects.h" 35 36#include "compile.h" 37#include "frameobject.h" 38#include "opcode.h" 39#include "structmember.h" 40#include "bltinmodule.h" 41 42#define OFF(x) offsetof(frameobject, x) 43 44static struct memberlist frame_memberlist[] = { 45 {"f_back", T_OBJECT, OFF(f_back), RO}, 46 {"f_code", T_OBJECT, OFF(f_code), RO}, 47 {"f_builtins", T_OBJECT, OFF(f_builtins),RO}, 48 {"f_globals", T_OBJECT, OFF(f_globals), RO}, 49 {"f_locals", T_OBJECT, OFF(f_locals), RO}, 50 {"f_lasti", T_INT, OFF(f_lasti), RO}, 51 {"f_lineno", T_INT, OFF(f_lineno), RO}, 52 {"f_restricted",T_INT, OFF(f_restricted),RO}, 53 {"f_trace", T_OBJECT, OFF(f_trace)}, 54 {NULL} /* Sentinel */ 55}; 56 57static object * 58frame_getattr(f, name) 59 frameobject *f; 60 char *name; 61{ 62 if (strcmp(name, "f_locals") == 0) 63 fast_2_locals(f); 64 return getmember((char *)f, frame_memberlist, name); 65} 66 67static int 68frame_setattr(f, name, value) 69 frameobject *f; 70 char *name; 71 object *value; 72{ 73 return setmember((char *)f, frame_memberlist, name, value); 74} 75 76/* Stack frames are allocated and deallocated at a considerable rate. 77 In an attempt to improve the speed of function calls, we maintain a 78 separate free list of stack frames (just like integers are 79 allocated in a special way -- see intobject.c). When a stack frame 80 is on the free list, only the following members have a meaning: 81 ob_type == &Frametype 82 f_back next item on free list, or NULL 83 f_nlocals number of locals 84 f_stacksize size of value stack 85 Note that the value and block stacks are preserved -- this can save 86 another malloc() call or two (and two free() calls as well!). 87 Also note that, unlike for integers, each frame object is a 88 malloc'ed object in its own right -- it is only the actual calls to 89 malloc() that we are trying to save here, not the administration. 90 After all, while a typical program may make millions of calls, a 91 call depth of more than 20 or 30 is probably already exceptional 92 unless the program contains run-away recursion. I hope. 93*/ 94 95static frameobject *free_list = NULL; 96 97static void 98frame_dealloc(f) 99 frameobject *f; 100{ 101 int i; 102 PyObject **fastlocals; 103 104 /* Kill all local variables */ 105 fastlocals = f->f_localsplus; 106 for (i = f->f_nlocals; --i >= 0; ++fastlocals) { 107 XDECREF(*fastlocals); 108 } 109 110 XDECREF(f->f_back); 111 XDECREF(f->f_code); 112 XDECREF(f->f_builtins); 113 XDECREF(f->f_globals); 114 XDECREF(f->f_locals); 115 XDECREF(f->f_trace); 116 f->f_back = free_list; 117 free_list = f; 118} 119 120typeobject Frametype = { 121 OB_HEAD_INIT(&Typetype) 122 0, 123 "frame", 124 sizeof(frameobject), 125 0, 126 (destructor)frame_dealloc, /*tp_dealloc*/ 127 0, /*tp_print*/ 128 (getattrfunc)frame_getattr, /*tp_getattr*/ 129 (setattrfunc)frame_setattr, /*tp_setattr*/ 130 0, /*tp_compare*/ 131 0, /*tp_repr*/ 132 0, /*tp_as_number*/ 133 0, /*tp_as_sequence*/ 134 0, /*tp_as_mapping*/ 135}; 136 137frameobject * 138newframeobject(back, code, globals, locals) 139 frameobject *back; 140 codeobject *code; 141 object *globals; 142 object *locals; 143{ 144 static object *builtin_object; 145 frameobject *f; 146 object *builtins; 147 int extras = code->co_stacksize + code->co_nlocals; 148 149 if (builtin_object == NULL) { 150 builtin_object = PyString_InternFromString("__builtins__"); 151 if (builtin_object == NULL) 152 return NULL; 153 } 154 if ((back != NULL && !is_frameobject(back)) || 155 code == NULL || !is_codeobject(code) || 156 globals == NULL || !is_dictobject(globals) || 157 (locals != NULL && !is_dictobject(locals))) { 158 err_badcall(); 159 return NULL; 160 } 161 builtins = mappinglookup(globals, builtin_object); 162 if (builtins != NULL && is_moduleobject(builtins)) 163 builtins = getmoduledict(builtins); 164 if (builtins == NULL || !is_mappingobject(builtins)) { 165 err_setstr(TypeError, "bad __builtins__ dictionary"); 166 return NULL; 167 } 168 if (free_list == NULL) { 169 f = (frameobject *) 170 malloc(sizeof(frameobject) + extras*sizeof(object *)); 171 if (f == NULL) 172 return (PyFrameObject *)err_nomem(); 173 f->ob_type = &Frametype; 174 NEWREF(f); 175 } 176 else { 177 f = free_list; 178 free_list = free_list->f_back; 179 if (f->f_nlocals + f->f_stacksize < extras) { 180 f = realloc(f, sizeof(frameobject) + 181 extras*sizeof(object *)); 182 if (f == NULL) 183 return (PyFrameObject *)err_nomem(); 184 } 185 else 186 extras = f->f_nlocals + f->f_stacksize; 187 f->ob_type = &Frametype; 188 NEWREF(f); 189 } 190 XINCREF(back); 191 f->f_back = back; 192 INCREF(code); 193 f->f_code = code; 194 XINCREF(builtins); 195 f->f_builtins = builtins; 196 INCREF(globals); 197 f->f_globals = globals; 198 if (code->co_flags & CO_NEWLOCALS) { 199 if (code->co_flags & CO_OPTIMIZED) 200 locals = NULL; /* Let fast_2_locals handle it */ 201 else { 202 locals = newdictobject(); 203 if (locals == NULL) { 204 DECREF(f); 205 return NULL; 206 } 207 } 208 } 209 else { 210 if (locals == NULL) 211 locals = globals; 212 INCREF(locals); 213 } 214 f->f_locals = locals; 215 f->f_trace = NULL; 216 217 f->f_lasti = 0; 218 f->f_lineno = code->co_firstlineno; 219 f->f_restricted = (builtins != getbuiltindict()); 220 f->f_iblock = 0; 221 f->f_nlocals = code->co_nlocals; 222 f->f_stacksize = extras - code->co_nlocals; 223 224 while (--extras >= 0) 225 f->f_localsplus[extras] = NULL; 226 227 f->f_valuestack = f->f_localsplus + f->f_nlocals; 228 229 return f; 230} 231 232/* Block management */ 233 234void 235setup_block(f, type, handler, level) 236 frameobject *f; 237 int type; 238 int handler; 239 int level; 240{ 241 block *b; 242 if (f->f_iblock >= CO_MAXBLOCKS) 243 fatal("XXX block stack overflow"); 244 b = &f->f_blockstack[f->f_iblock++]; 245 b->b_type = type; 246 b->b_level = level; 247 b->b_handler = handler; 248} 249 250block * 251pop_block(f) 252 frameobject *f; 253{ 254 block *b; 255 if (f->f_iblock <= 0) 256 fatal("XXX block stack underflow"); 257 b = &f->f_blockstack[--f->f_iblock]; 258 return b; 259} 260 261/* Convert between "fast" version of locals and dictionary version */ 262 263void 264fast_2_locals(f) 265 frameobject *f; 266{ 267 /* Merge fast locals into f->f_locals */ 268 object *locals, *map; 269 object **fast; 270 object *error_type, *error_value, *error_traceback; 271 int j; 272 if (f == NULL) 273 return; 274 locals = f->f_locals; 275 if (locals == NULL) { 276 locals = f->f_locals = newdictobject(); 277 if (locals == NULL) { 278 err_clear(); /* Can't report it :-( */ 279 return; 280 } 281 } 282 if (f->f_nlocals == 0) 283 return; 284 map = f->f_code->co_varnames; 285 if (!is_dictobject(locals) || !is_tupleobject(map)) 286 return; 287 err_fetch(&error_type, &error_value, &error_traceback); 288 fast = f->f_localsplus; 289 j = gettuplesize(map); 290 if (j > f->f_nlocals) 291 j = f->f_nlocals; 292 for (; --j >= 0; ) { 293 object *key = gettupleitem(map, j); 294 object *value = fast[j]; 295 if (value == NULL) { 296 err_clear(); 297 if (dict2remove(locals, key) != 0) 298 err_clear(); 299 } 300 else { 301 if (dict2insert(locals, key, value) != 0) 302 err_clear(); 303 } 304 } 305 err_restore(error_type, error_value, error_traceback); 306} 307 308void 309locals_2_fast(f, clear) 310 frameobject *f; 311 int clear; 312{ 313 /* Merge f->f_locals into fast locals */ 314 object *locals, *map; 315 object **fast; 316 object *error_type, *error_value, *error_traceback; 317 int j; 318 if (f == NULL) 319 return; 320 locals = f->f_locals; 321 map = f->f_code->co_varnames; 322 if (locals == NULL || f->f_code->co_nlocals == 0) 323 return; 324 if (!is_dictobject(locals) || !is_tupleobject(map)) 325 return; 326 err_fetch(&error_type, &error_value, &error_traceback); 327 fast = f->f_localsplus; 328 j = gettuplesize(map); 329 if (j > f->f_nlocals) 330 j = f->f_nlocals; 331 for (; --j >= 0; ) { 332 object *key = gettupleitem(map, j); 333 object *value = dict2lookup(locals, key); 334 if (value == NULL) 335 err_clear(); 336 else 337 INCREF(value); 338 if (value != NULL || clear) { 339 XDECREF(fast[j]); 340 XINCREF(value); 341 fast[j] = value; 342 } 343 } 344 err_restore(error_type, error_value, error_traceback); 345} 346