frameobject.c revision 8c96369513ded66146f9cf19678029615e29bcb7
1 2/* Frame object implementation */ 3 4#include "Python.h" 5 6#include "compile.h" 7#include "frameobject.h" 8#include "opcode.h" 9#include "structmember.h" 10 11#define OFF(x) offsetof(PyFrameObject, x) 12 13static struct memberlist frame_memberlist[] = { 14 {"f_back", T_OBJECT, OFF(f_back), RO}, 15 {"f_code", T_OBJECT, OFF(f_code), RO}, 16 {"f_builtins", T_OBJECT, OFF(f_builtins),RO}, 17 {"f_globals", T_OBJECT, OFF(f_globals), RO}, 18 {"f_locals", T_OBJECT, OFF(f_locals), RO}, 19 {"f_lasti", T_INT, OFF(f_lasti), RO}, 20 {"f_lineno", T_INT, OFF(f_lineno), RO}, 21 {"f_restricted",T_INT, OFF(f_restricted),RO}, 22 {"f_trace", T_OBJECT, OFF(f_trace)}, 23 {"f_exc_type", T_OBJECT, OFF(f_exc_type)}, 24 {"f_exc_value", T_OBJECT, OFF(f_exc_value)}, 25 {"f_exc_traceback", T_OBJECT, OFF(f_exc_traceback)}, 26 {NULL} /* Sentinel */ 27}; 28 29static PyObject * 30frame_getattr(PyFrameObject *f, char *name) 31{ 32 if (strcmp(name, "f_locals") == 0) 33 PyFrame_FastToLocals(f); 34 return PyMember_Get((char *)f, frame_memberlist, name); 35} 36 37static int 38frame_setattr(PyFrameObject *f, char *name, PyObject *value) 39{ 40 return PyMember_Set((char *)f, frame_memberlist, name, value); 41} 42 43/* Stack frames are allocated and deallocated at a considerable rate. 44 In an attempt to improve the speed of function calls, we maintain a 45 separate free list of stack frames (just like integers are 46 allocated in a special way -- see intobject.c). When a stack frame 47 is on the free list, only the following members have a meaning: 48 ob_type == &Frametype 49 f_back next item on free list, or NULL 50 f_nlocals number of locals 51 f_stacksize size of value stack 52 f_size size of localsplus 53 Note that the value and block stacks are preserved -- this can save 54 another malloc() call or two (and two free() calls as well!). 55 Also note that, unlike for integers, each frame object is a 56 malloc'ed object in its own right -- it is only the actual calls to 57 malloc() that we are trying to save here, not the administration. 58 After all, while a typical program may make millions of calls, a 59 call depth of more than 20 or 30 is probably already exceptional 60 unless the program contains run-away recursion. I hope. 61*/ 62 63static PyFrameObject *free_list = NULL; 64 65static void 66frame_dealloc(PyFrameObject *f) 67{ 68 int i, slots; 69 PyObject **fastlocals; 70 PyObject **p; 71 72 Py_TRASHCAN_SAFE_BEGIN(f) 73 /* Kill all local variables */ 74 slots = f->f_nlocals + f->f_ncells + f->f_nfreevars; 75 fastlocals = f->f_localsplus; 76 for (i = slots; --i >= 0; ++fastlocals) { 77 Py_XDECREF(*fastlocals); 78 } 79 80 /* Free stack */ 81 if (f->f_stacktop != NULL) { 82 for (p = f->f_valuestack; p < f->f_stacktop; p++) 83 Py_XDECREF(*p); 84 } 85 86 Py_XDECREF(f->f_back); 87 Py_XDECREF(f->f_code); 88 Py_XDECREF(f->f_builtins); 89 Py_XDECREF(f->f_globals); 90 Py_XDECREF(f->f_locals); 91 Py_XDECREF(f->f_trace); 92 Py_XDECREF(f->f_exc_type); 93 Py_XDECREF(f->f_exc_value); 94 Py_XDECREF(f->f_exc_traceback); 95 f->f_back = free_list; 96 free_list = f; 97 Py_TRASHCAN_SAFE_END(f) 98} 99 100PyTypeObject PyFrame_Type = { 101 PyObject_HEAD_INIT(&PyType_Type) 102 0, 103 "frame", 104 sizeof(PyFrameObject), 105 0, 106 (destructor)frame_dealloc, /*tp_dealloc*/ 107 0, /*tp_print*/ 108 (getattrfunc)frame_getattr, /*tp_getattr*/ 109 (setattrfunc)frame_setattr, /*tp_setattr*/ 110 0, /*tp_compare*/ 111 0, /*tp_repr*/ 112 0, /*tp_as_number*/ 113 0, /*tp_as_sequence*/ 114 0, /*tp_as_mapping*/ 115}; 116 117PyFrameObject * 118PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, 119 PyObject *locals) 120{ 121 PyFrameObject *back = tstate->frame; 122 static PyObject *builtin_object; 123 PyFrameObject *f; 124 PyObject *builtins; 125 int extras, ncells, nfrees; 126 127 if (builtin_object == NULL) { 128 builtin_object = PyString_InternFromString("__builtins__"); 129 if (builtin_object == NULL) 130 return NULL; 131 } 132 if ((back != NULL && !PyFrame_Check(back)) || 133 code == NULL || !PyCode_Check(code) || 134 globals == NULL || !PyDict_Check(globals) || 135 (locals != NULL && !PyDict_Check(locals))) { 136 PyErr_BadInternalCall(); 137 return NULL; 138 } 139 ncells = PyTuple_GET_SIZE(code->co_cellvars); 140 nfrees = PyTuple_GET_SIZE(code->co_freevars); 141 extras = code->co_stacksize + code->co_nlocals + ncells + nfrees; 142 if (back == NULL || back->f_globals != globals) { 143 builtins = PyDict_GetItem(globals, builtin_object); 144 if (builtins != NULL && PyModule_Check(builtins)) 145 builtins = PyModule_GetDict(builtins); 146 } 147 else { 148 /* If we share the globals, we share the builtins. 149 Save a lookup and a call. */ 150 builtins = back->f_builtins; 151 } 152 if (builtins != NULL && !PyDict_Check(builtins)) 153 builtins = NULL; 154 if (free_list == NULL) { 155 /* PyObject_New is inlined */ 156 f = (PyFrameObject *) 157 PyObject_MALLOC(sizeof(PyFrameObject) + 158 extras*sizeof(PyObject *)); 159 if (f == NULL) 160 return (PyFrameObject *)PyErr_NoMemory(); 161 PyObject_INIT(f, &PyFrame_Type); 162 f->f_size = extras; 163 } 164 else { 165 f = free_list; 166 free_list = free_list->f_back; 167 if (f->f_size < extras) { 168 f = (PyFrameObject *) 169 PyObject_REALLOC(f, sizeof(PyFrameObject) + 170 extras*sizeof(PyObject *)); 171 if (f == NULL) 172 return (PyFrameObject *)PyErr_NoMemory(); 173 f->f_size = extras; 174 } 175 else 176 extras = f->f_size; 177 PyObject_INIT(f, &PyFrame_Type); 178 } 179 if (builtins == NULL) { 180 /* No builtins! Make up a minimal one. */ 181 builtins = PyDict_New(); 182 if (builtins == NULL || /* Give them 'None', at least. */ 183 PyDict_SetItemString(builtins, "None", Py_None) < 0) { 184 Py_DECREF(f); 185 return NULL; 186 } 187 } 188 else 189 Py_XINCREF(builtins); 190 f->f_builtins = builtins; 191 Py_XINCREF(back); 192 f->f_back = back; 193 Py_INCREF(code); 194 f->f_code = code; 195 Py_INCREF(globals); 196 f->f_globals = globals; 197 if (code->co_flags & CO_NEWLOCALS) { 198 if (code->co_flags & CO_OPTIMIZED) 199 locals = NULL; /* Let fast_2_locals handle it */ 200 else { 201 locals = PyDict_New(); 202 if (locals == NULL) { 203 Py_DECREF(f); 204 return NULL; 205 } 206 } 207 } 208 else { 209 if (locals == NULL) 210 locals = globals; 211 Py_INCREF(locals); 212 } 213 f->f_locals = locals; 214 f->f_trace = NULL; 215 f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL; 216 f->f_tstate = tstate; 217 218 f->f_lasti = 0; 219 f->f_lineno = code->co_firstlineno; 220 f->f_restricted = (builtins != tstate->interp->builtins); 221 f->f_iblock = 0; 222 f->f_nlocals = code->co_nlocals; 223 f->f_stacksize = code->co_stacksize; 224 f->f_ncells = ncells; 225 f->f_nfreevars = nfrees; 226 227 while (--extras >= 0) 228 f->f_localsplus[extras] = NULL; 229 230 f->f_valuestack = f->f_localsplus + (f->f_nlocals + ncells + nfrees); 231 f->f_stacktop = f->f_valuestack; 232 233 return f; 234} 235 236/* Block management */ 237 238void 239PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level) 240{ 241 PyTryBlock *b; 242 if (f->f_iblock >= CO_MAXBLOCKS) 243 Py_FatalError("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 250PyTryBlock * 251PyFrame_BlockPop(PyFrameObject *f) 252{ 253 PyTryBlock *b; 254 if (f->f_iblock <= 0) 255 Py_FatalError("XXX block stack underflow"); 256 b = &f->f_blockstack[--f->f_iblock]; 257 return b; 258} 259 260/* Convert between "fast" version of locals and dictionary version */ 261 262static void 263map_to_dict(PyObject *map, int nmap, PyObject *dict, PyObject **values, 264 int deref) 265{ 266 int j; 267 for (j = nmap; --j >= 0; ) { 268 PyObject *key = PyTuple_GetItem(map, j); 269 PyObject *value = values[j]; 270 if (deref) 271 value = PyCell_GET(value); 272 if (value == NULL) { 273 PyErr_Clear(); 274 if (PyDict_DelItem(dict, key) != 0) 275 PyErr_Clear(); 276 } 277 else { 278 if (PyDict_SetItem(dict, key, value) != 0) 279 PyErr_Clear(); 280 } 281 } 282} 283 284static void 285dict_to_map(PyObject *map, int nmap, PyObject *dict, PyObject **values, 286 int deref, int clear) 287{ 288 int j; 289 for (j = nmap; --j >= 0; ) { 290 PyObject *key = PyTuple_GetItem(map, j); 291 PyObject *value = PyDict_GetItem(dict, key); 292 Py_XINCREF(value); 293 if (deref) { 294 if (value || clear) { 295 if (PyCell_Set(values[j], value) < 0) 296 PyErr_Clear(); 297 } 298 } else if (value != NULL || clear) { 299 Py_XDECREF(values[j]); 300 values[j] = value; 301 } 302 } 303} 304 305void 306PyFrame_FastToLocals(PyFrameObject *f) 307{ 308 /* Merge fast locals into f->f_locals */ 309 PyObject *locals, *map; 310 PyObject **fast; 311 PyObject *error_type, *error_value, *error_traceback; 312 int j; 313 if (f == NULL) 314 return; 315 locals = f->f_locals; 316 if (locals == NULL) { 317 locals = f->f_locals = PyDict_New(); 318 if (locals == NULL) { 319 PyErr_Clear(); /* Can't report it :-( */ 320 return; 321 } 322 } 323 if (f->f_nlocals == 0) 324 return; 325 map = f->f_code->co_varnames; 326 if (!PyDict_Check(locals) || !PyTuple_Check(map)) 327 return; 328 PyErr_Fetch(&error_type, &error_value, &error_traceback); 329 fast = f->f_localsplus; 330 j = PyTuple_Size(map); 331 if (j > f->f_nlocals) 332 j = f->f_nlocals; 333 map_to_dict(map, j, locals, fast, 0); 334 if (f->f_ncells || f->f_nfreevars) { 335 if (!(PyTuple_Check(f->f_code->co_cellvars) 336 && PyTuple_Check(f->f_code->co_freevars))) { 337 Py_DECREF(locals); 338 return; 339 } 340 map_to_dict(f->f_code->co_cellvars, 341 PyTuple_GET_SIZE(f->f_code->co_cellvars), 342 locals, fast + f->f_nlocals, 1); 343 map_to_dict(f->f_code->co_freevars, 344 PyTuple_GET_SIZE(f->f_code->co_freevars), 345 locals, fast + f->f_nlocals + f->f_ncells, 1); 346 } 347 PyErr_Restore(error_type, error_value, error_traceback); 348} 349 350void 351PyFrame_LocalsToFast(PyFrameObject *f, int clear) 352{ 353 /* Merge f->f_locals into fast locals */ 354 PyObject *locals, *map; 355 PyObject **fast; 356 PyObject *error_type, *error_value, *error_traceback; 357 int j; 358 if (f == NULL) 359 return; 360 locals = f->f_locals; 361 map = f->f_code->co_varnames; 362 if (locals == NULL || f->f_code->co_nlocals == 0) 363 return; 364 if (!PyDict_Check(locals) || !PyTuple_Check(map)) 365 return; 366 PyErr_Fetch(&error_type, &error_value, &error_traceback); 367 fast = f->f_localsplus; 368 j = PyTuple_Size(map); 369 if (j > f->f_nlocals) 370 j = f->f_nlocals; 371 dict_to_map(f->f_code->co_varnames, j, locals, fast, 0, clear); 372 if (f->f_ncells || f->f_nfreevars) { 373 if (!(PyTuple_Check(f->f_code->co_cellvars) 374 && PyTuple_Check(f->f_code->co_freevars))) 375 return; 376 dict_to_map(f->f_code->co_cellvars, 377 PyTuple_GET_SIZE(f->f_code->co_cellvars), 378 locals, fast + f->f_nlocals, 1, clear); 379 dict_to_map(f->f_code->co_freevars, 380 PyTuple_GET_SIZE(f->f_code->co_freevars), 381 locals, fast + f->f_nlocals + f->f_ncells, 1, clear); 382 } 383 PyErr_Restore(error_type, error_value, error_traceback); 384} 385 386/* Clear out the free list */ 387 388void 389PyFrame_Fini(void) 390{ 391 while (free_list != NULL) { 392 PyFrameObject *f = free_list; 393 free_list = free_list->f_back; 394 PyObject_DEL(f); 395 } 396} 397