summaryrefslogtreecommitdiffstats
path: root/Objects/frameobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/frameobject.c')
-rw-r--r--Objects/frameobject.c1436
1 files changed, 718 insertions, 718 deletions
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 26abd5f..191c6b6 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -15,39 +15,39 @@
#define OFF(x) offsetof(PyFrameObject, x)
static PyMemberDef frame_memberlist[] = {
- {"f_back", T_OBJECT, OFF(f_back), READONLY},
- {"f_code", T_OBJECT, OFF(f_code), READONLY},
- {"f_builtins", T_OBJECT, OFF(f_builtins),READONLY},
- {"f_globals", T_OBJECT, OFF(f_globals), READONLY},
- {"f_lasti", T_INT, OFF(f_lasti), READONLY},
- {NULL} /* Sentinel */
+ {"f_back", T_OBJECT, OFF(f_back), READONLY},
+ {"f_code", T_OBJECT, OFF(f_code), READONLY},
+ {"f_builtins", T_OBJECT, OFF(f_builtins),READONLY},
+ {"f_globals", T_OBJECT, OFF(f_globals), READONLY},
+ {"f_lasti", T_INT, OFF(f_lasti), READONLY},
+ {NULL} /* Sentinel */
};
static PyObject *
frame_getlocals(PyFrameObject *f, void *closure)
{
- PyFrame_FastToLocals(f);
- Py_INCREF(f->f_locals);
- return f->f_locals;
+ PyFrame_FastToLocals(f);
+ Py_INCREF(f->f_locals);
+ return f->f_locals;
}
int
PyFrame_GetLineNumber(PyFrameObject *f)
{
- if (f->f_trace)
- return f->f_lineno;
- else
- return PyCode_Addr2Line(f->f_code, f->f_lasti);
+ if (f->f_trace)
+ return f->f_lineno;
+ else
+ return PyCode_Addr2Line(f->f_code, f->f_lasti);
}
static PyObject *
frame_getlineno(PyFrameObject *f, void *closure)
{
- return PyLong_FromLong(PyFrame_GetLineNumber(f));
+ return PyLong_FromLong(PyFrame_GetLineNumber(f));
}
/* Setter for f_lineno - you can set f_lineno from within a trace function in
- * order to jump to a given line of code, subject to some restrictions. Most
+ * order to jump to a given line of code, subject to some restrictions. Most
* lines are OK to jump to because they don't make any assumptions about the
* state of the stack (obvious because you could remove the line and the code
* would still work without any stack errors), but there are some constructs
@@ -64,309 +64,309 @@ frame_getlineno(PyFrameObject *f, void *closure)
static int
frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
{
- int new_lineno = 0; /* The new value of f_lineno */
- long l_new_lineno;
- int overflow;
- int new_lasti = 0; /* The new value of f_lasti */
- int new_iblock = 0; /* The new value of f_iblock */
- unsigned char *code = NULL; /* The bytecode for the frame... */
- Py_ssize_t code_len = 0; /* ...and its length */
- unsigned char *lnotab = NULL; /* Iterating over co_lnotab */
- Py_ssize_t lnotab_len = 0; /* (ditto) */
- int offset = 0; /* (ditto) */
- int line = 0; /* (ditto) */
- int addr = 0; /* (ditto) */
- int min_addr = 0; /* Scanning the SETUPs and POPs */
- int max_addr = 0; /* (ditto) */
- int delta_iblock = 0; /* (ditto) */
- int min_delta_iblock = 0; /* (ditto) */
- int min_iblock = 0; /* (ditto) */
- int f_lasti_setup_addr = 0; /* Policing no-jump-into-finally */
- int new_lasti_setup_addr = 0; /* (ditto) */
- int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */
- int in_finally[CO_MAXBLOCKS]; /* (ditto) */
- int blockstack_top = 0; /* (ditto) */
- unsigned char setup_op = 0; /* (ditto) */
-
- /* f_lineno must be an integer. */
- if (!PyLong_CheckExact(p_new_lineno)) {
- PyErr_SetString(PyExc_ValueError,
- "lineno must be an integer");
- return -1;
- }
-
- /* You can only do this from within a trace function, not via
- * _getframe or similar hackery. */
- if (!f->f_trace)
- {
- PyErr_Format(PyExc_ValueError,
- "f_lineno can only be set by a"
- " line trace function");
- return -1;
- }
-
- /* Fail if the line comes before the start of the code block. */
- l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow);
- if (overflow
+ int new_lineno = 0; /* The new value of f_lineno */
+ long l_new_lineno;
+ int overflow;
+ int new_lasti = 0; /* The new value of f_lasti */
+ int new_iblock = 0; /* The new value of f_iblock */
+ unsigned char *code = NULL; /* The bytecode for the frame... */
+ Py_ssize_t code_len = 0; /* ...and its length */
+ unsigned char *lnotab = NULL; /* Iterating over co_lnotab */
+ Py_ssize_t lnotab_len = 0; /* (ditto) */
+ int offset = 0; /* (ditto) */
+ int line = 0; /* (ditto) */
+ int addr = 0; /* (ditto) */
+ int min_addr = 0; /* Scanning the SETUPs and POPs */
+ int max_addr = 0; /* (ditto) */
+ int delta_iblock = 0; /* (ditto) */
+ int min_delta_iblock = 0; /* (ditto) */
+ int min_iblock = 0; /* (ditto) */
+ int f_lasti_setup_addr = 0; /* Policing no-jump-into-finally */
+ int new_lasti_setup_addr = 0; /* (ditto) */
+ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */
+ int in_finally[CO_MAXBLOCKS]; /* (ditto) */
+ int blockstack_top = 0; /* (ditto) */
+ unsigned char setup_op = 0; /* (ditto) */
+
+ /* f_lineno must be an integer. */
+ if (!PyLong_CheckExact(p_new_lineno)) {
+ PyErr_SetString(PyExc_ValueError,
+ "lineno must be an integer");
+ return -1;
+ }
+
+ /* You can only do this from within a trace function, not via
+ * _getframe or similar hackery. */
+ if (!f->f_trace)
+ {
+ PyErr_Format(PyExc_ValueError,
+ "f_lineno can only be set by a"
+ " line trace function");
+ return -1;
+ }
+
+ /* Fail if the line comes before the start of the code block. */
+ l_new_lineno = PyLong_AsLongAndOverflow(p_new_lineno, &overflow);
+ if (overflow
#if SIZEOF_LONG > SIZEOF_INT
- || l_new_lineno > INT_MAX
- || l_new_lineno < INT_MIN
+ || l_new_lineno > INT_MAX
+ || l_new_lineno < INT_MIN
#endif
- ) {
- PyErr_SetString(PyExc_ValueError,
- "lineno out of range");
- return -1;
- }
- new_lineno = (int)l_new_lineno;
-
- if (new_lineno < f->f_code->co_firstlineno) {
- PyErr_Format(PyExc_ValueError,
- "line %d comes before the current code block",
- new_lineno);
- return -1;
- }
- else if (new_lineno == f->f_code->co_firstlineno) {
- new_lasti = 0;
- new_lineno = f->f_code->co_firstlineno;
- }
- else {
- /* Find the bytecode offset for the start of the given
- * line, or the first code-owning line after it. */
- char *tmp;
- PyBytes_AsStringAndSize(f->f_code->co_lnotab,
- &tmp, &lnotab_len);
- lnotab = (unsigned char *) tmp;
- addr = 0;
- line = f->f_code->co_firstlineno;
- new_lasti = -1;
- for (offset = 0; offset < lnotab_len; offset += 2) {
- addr += lnotab[offset];
- line += lnotab[offset+1];
- if (line >= new_lineno) {
- new_lasti = addr;
- new_lineno = line;
- break;
- }
- }
- }
-
- /* If we didn't reach the requested line, return an error. */
- if (new_lasti == -1) {
- PyErr_Format(PyExc_ValueError,
- "line %d comes after the current code block",
- new_lineno);
- return -1;
- }
-
- /* We're now ready to look at the bytecode. */
- PyBytes_AsStringAndSize(f->f_code->co_code, (char **)&code, &code_len);
- min_addr = MIN(new_lasti, f->f_lasti);
- max_addr = MAX(new_lasti, f->f_lasti);
-
- /* You can't jump onto a line with an 'except' statement on it -
- * they expect to have an exception on the top of the stack, which
- * won't be true if you jump to them. They always start with code
- * that either pops the exception using POP_TOP (plain 'except:'
- * lines do this) or duplicates the exception on the stack using
- * DUP_TOP (if there's an exception type specified). See compile.c,
- * 'com_try_except' for the full details. There aren't any other
- * cases (AFAIK) where a line's code can start with DUP_TOP or
- * POP_TOP, but if any ever appear, they'll be subject to the same
- * restriction (but with a different error message). */
- if (code[new_lasti] == DUP_TOP || code[new_lasti] == POP_TOP) {
- PyErr_SetString(PyExc_ValueError,
- "can't jump to 'except' line as there's no exception");
- return -1;
- }
-
- /* You can't jump into or out of a 'finally' block because the 'try'
- * block leaves something on the stack for the END_FINALLY to clean
- * up. So we walk the bytecode, maintaining a simulated blockstack.
- * When we reach the old or new address and it's in a 'finally' block
- * we note the address of the corresponding SETUP_FINALLY. The jump
- * is only legal if neither address is in a 'finally' block or
- * they're both in the same one. 'blockstack' is a stack of the
- * bytecode addresses of the SETUP_X opcodes, and 'in_finally' tracks
- * whether we're in a 'finally' block at each blockstack level. */
- f_lasti_setup_addr = -1;
- new_lasti_setup_addr = -1;
- memset(blockstack, '\0', sizeof(blockstack));
- memset(in_finally, '\0', sizeof(in_finally));
- blockstack_top = 0;
- for (addr = 0; addr < code_len; addr++) {
- unsigned char op = code[addr];
- switch (op) {
- case SETUP_LOOP:
- case SETUP_EXCEPT:
- case SETUP_FINALLY:
- blockstack[blockstack_top++] = addr;
- in_finally[blockstack_top-1] = 0;
- break;
-
- case POP_BLOCK:
- assert(blockstack_top > 0);
- setup_op = code[blockstack[blockstack_top-1]];
- if (setup_op == SETUP_FINALLY) {
- in_finally[blockstack_top-1] = 1;
- }
- else {
- blockstack_top--;
- }
- break;
-
- case END_FINALLY:
- /* Ignore END_FINALLYs for SETUP_EXCEPTs - they exist
- * in the bytecode but don't correspond to an actual
- * 'finally' block. (If blockstack_top is 0, we must
- * be seeing such an END_FINALLY.) */
- if (blockstack_top > 0) {
- setup_op = code[blockstack[blockstack_top-1]];
- if (setup_op == SETUP_FINALLY) {
- blockstack_top--;
- }
- }
- break;
- }
-
- /* For the addresses we're interested in, see whether they're
- * within a 'finally' block and if so, remember the address
- * of the SETUP_FINALLY. */
- if (addr == new_lasti || addr == f->f_lasti) {
- int i = 0;
- int setup_addr = -1;
- for (i = blockstack_top-1; i >= 0; i--) {
- if (in_finally[i]) {
- setup_addr = blockstack[i];
- break;
- }
- }
-
- if (setup_addr != -1) {
- if (addr == new_lasti) {
- new_lasti_setup_addr = setup_addr;
- }
-
- if (addr == f->f_lasti) {
- f_lasti_setup_addr = setup_addr;
- }
- }
- }
-
- if (op >= HAVE_ARGUMENT) {
- addr += 2;
- }
- }
-
- /* Verify that the blockstack tracking code didn't get lost. */
- assert(blockstack_top == 0);
-
- /* After all that, are we jumping into / out of a 'finally' block? */
- if (new_lasti_setup_addr != f_lasti_setup_addr) {
- PyErr_SetString(PyExc_ValueError,
- "can't jump into or out of a 'finally' block");
- return -1;
- }
-
-
- /* Police block-jumping (you can't jump into the middle of a block)
- * and ensure that the blockstack finishes up in a sensible state (by
- * popping any blocks we're jumping out of). We look at all the
- * blockstack operations between the current position and the new
- * one, and keep track of how many blocks we drop out of on the way.
- * By also keeping track of the lowest blockstack position we see, we
- * can tell whether the jump goes into any blocks without coming out
- * again - in that case we raise an exception below. */
- delta_iblock = 0;
- for (addr = min_addr; addr < max_addr; addr++) {
- unsigned char op = code[addr];
- switch (op) {
- case SETUP_LOOP:
- case SETUP_EXCEPT:
- case SETUP_FINALLY:
- delta_iblock++;
- break;
-
- case POP_BLOCK:
- delta_iblock--;
- break;
- }
-
- min_delta_iblock = MIN(min_delta_iblock, delta_iblock);
-
- if (op >= HAVE_ARGUMENT) {
- addr += 2;
- }
- }
-
- /* Derive the absolute iblock values from the deltas. */
- min_iblock = f->f_iblock + min_delta_iblock;
- if (new_lasti > f->f_lasti) {
- /* Forwards jump. */
- new_iblock = f->f_iblock + delta_iblock;
- }
- else {
- /* Backwards jump. */
- new_iblock = f->f_iblock - delta_iblock;
- }
-
- /* Are we jumping into a block? */
- if (new_iblock > min_iblock) {
- PyErr_SetString(PyExc_ValueError,
- "can't jump into the middle of a block");
- return -1;
- }
-
- /* Pop any blocks that we're jumping out of. */
- while (f->f_iblock > new_iblock) {
- PyTryBlock *b = &f->f_blockstack[--f->f_iblock];
- while ((f->f_stacktop - f->f_valuestack) > b->b_level) {
- PyObject *v = (*--f->f_stacktop);
- Py_DECREF(v);
- }
- }
-
- /* Finally set the new f_lineno and f_lasti and return OK. */
- f->f_lineno = new_lineno;
- f->f_lasti = new_lasti;
- return 0;
+ ) {
+ PyErr_SetString(PyExc_ValueError,
+ "lineno out of range");
+ return -1;
+ }
+ new_lineno = (int)l_new_lineno;
+
+ if (new_lineno < f->f_code->co_firstlineno) {
+ PyErr_Format(PyExc_ValueError,
+ "line %d comes before the current code block",
+ new_lineno);
+ return -1;
+ }
+ else if (new_lineno == f->f_code->co_firstlineno) {
+ new_lasti = 0;
+ new_lineno = f->f_code->co_firstlineno;
+ }
+ else {
+ /* Find the bytecode offset for the start of the given
+ * line, or the first code-owning line after it. */
+ char *tmp;
+ PyBytes_AsStringAndSize(f->f_code->co_lnotab,
+ &tmp, &lnotab_len);
+ lnotab = (unsigned char *) tmp;
+ addr = 0;
+ line = f->f_code->co_firstlineno;
+ new_lasti = -1;
+ for (offset = 0; offset < lnotab_len; offset += 2) {
+ addr += lnotab[offset];
+ line += lnotab[offset+1];
+ if (line >= new_lineno) {
+ new_lasti = addr;
+ new_lineno = line;
+ break;
+ }
+ }
+ }
+
+ /* If we didn't reach the requested line, return an error. */
+ if (new_lasti == -1) {
+ PyErr_Format(PyExc_ValueError,
+ "line %d comes after the current code block",
+ new_lineno);
+ return -1;
+ }
+
+ /* We're now ready to look at the bytecode. */
+ PyBytes_AsStringAndSize(f->f_code->co_code, (char **)&code, &code_len);
+ min_addr = MIN(new_lasti, f->f_lasti);
+ max_addr = MAX(new_lasti, f->f_lasti);
+
+ /* You can't jump onto a line with an 'except' statement on it -
+ * they expect to have an exception on the top of the stack, which
+ * won't be true if you jump to them. They always start with code
+ * that either pops the exception using POP_TOP (plain 'except:'
+ * lines do this) or duplicates the exception on the stack using
+ * DUP_TOP (if there's an exception type specified). See compile.c,
+ * 'com_try_except' for the full details. There aren't any other
+ * cases (AFAIK) where a line's code can start with DUP_TOP or
+ * POP_TOP, but if any ever appear, they'll be subject to the same
+ * restriction (but with a different error message). */
+ if (code[new_lasti] == DUP_TOP || code[new_lasti] == POP_TOP) {
+ PyErr_SetString(PyExc_ValueError,
+ "can't jump to 'except' line as there's no exception");
+ return -1;
+ }
+
+ /* You can't jump into or out of a 'finally' block because the 'try'
+ * block leaves something on the stack for the END_FINALLY to clean
+ * up. So we walk the bytecode, maintaining a simulated blockstack.
+ * When we reach the old or new address and it's in a 'finally' block
+ * we note the address of the corresponding SETUP_FINALLY. The jump
+ * is only legal if neither address is in a 'finally' block or
+ * they're both in the same one. 'blockstack' is a stack of the
+ * bytecode addresses of the SETUP_X opcodes, and 'in_finally' tracks
+ * whether we're in a 'finally' block at each blockstack level. */
+ f_lasti_setup_addr = -1;
+ new_lasti_setup_addr = -1;
+ memset(blockstack, '\0', sizeof(blockstack));
+ memset(in_finally, '\0', sizeof(in_finally));
+ blockstack_top = 0;
+ for (addr = 0; addr < code_len; addr++) {
+ unsigned char op = code[addr];
+ switch (op) {
+ case SETUP_LOOP:
+ case SETUP_EXCEPT:
+ case SETUP_FINALLY:
+ blockstack[blockstack_top++] = addr;
+ in_finally[blockstack_top-1] = 0;
+ break;
+
+ case POP_BLOCK:
+ assert(blockstack_top > 0);
+ setup_op = code[blockstack[blockstack_top-1]];
+ if (setup_op == SETUP_FINALLY) {
+ in_finally[blockstack_top-1] = 1;
+ }
+ else {
+ blockstack_top--;
+ }
+ break;
+
+ case END_FINALLY:
+ /* Ignore END_FINALLYs for SETUP_EXCEPTs - they exist
+ * in the bytecode but don't correspond to an actual
+ * 'finally' block. (If blockstack_top is 0, we must
+ * be seeing such an END_FINALLY.) */
+ if (blockstack_top > 0) {
+ setup_op = code[blockstack[blockstack_top-1]];
+ if (setup_op == SETUP_FINALLY) {
+ blockstack_top--;
+ }
+ }
+ break;
+ }
+
+ /* For the addresses we're interested in, see whether they're
+ * within a 'finally' block and if so, remember the address
+ * of the SETUP_FINALLY. */
+ if (addr == new_lasti || addr == f->f_lasti) {
+ int i = 0;
+ int setup_addr = -1;
+ for (i = blockstack_top-1; i >= 0; i--) {
+ if (in_finally[i]) {
+ setup_addr = blockstack[i];
+ break;
+ }
+ }
+
+ if (setup_addr != -1) {
+ if (addr == new_lasti) {
+ new_lasti_setup_addr = setup_addr;
+ }
+
+ if (addr == f->f_lasti) {
+ f_lasti_setup_addr = setup_addr;
+ }
+ }
+ }
+
+ if (op >= HAVE_ARGUMENT) {
+ addr += 2;
+ }
+ }
+
+ /* Verify that the blockstack tracking code didn't get lost. */
+ assert(blockstack_top == 0);
+
+ /* After all that, are we jumping into / out of a 'finally' block? */
+ if (new_lasti_setup_addr != f_lasti_setup_addr) {
+ PyErr_SetString(PyExc_ValueError,
+ "can't jump into or out of a 'finally' block");
+ return -1;
+ }
+
+
+ /* Police block-jumping (you can't jump into the middle of a block)
+ * and ensure that the blockstack finishes up in a sensible state (by
+ * popping any blocks we're jumping out of). We look at all the
+ * blockstack operations between the current position and the new
+ * one, and keep track of how many blocks we drop out of on the way.
+ * By also keeping track of the lowest blockstack position we see, we
+ * can tell whether the jump goes into any blocks without coming out
+ * again - in that case we raise an exception below. */
+ delta_iblock = 0;
+ for (addr = min_addr; addr < max_addr; addr++) {
+ unsigned char op = code[addr];
+ switch (op) {
+ case SETUP_LOOP:
+ case SETUP_EXCEPT:
+ case SETUP_FINALLY:
+ delta_iblock++;
+ break;
+
+ case POP_BLOCK:
+ delta_iblock--;
+ break;
+ }
+
+ min_delta_iblock = MIN(min_delta_iblock, delta_iblock);
+
+ if (op >= HAVE_ARGUMENT) {
+ addr += 2;
+ }
+ }
+
+ /* Derive the absolute iblock values from the deltas. */
+ min_iblock = f->f_iblock + min_delta_iblock;
+ if (new_lasti > f->f_lasti) {
+ /* Forwards jump. */
+ new_iblock = f->f_iblock + delta_iblock;
+ }
+ else {
+ /* Backwards jump. */
+ new_iblock = f->f_iblock - delta_iblock;
+ }
+
+ /* Are we jumping into a block? */
+ if (new_iblock > min_iblock) {
+ PyErr_SetString(PyExc_ValueError,
+ "can't jump into the middle of a block");
+ return -1;
+ }
+
+ /* Pop any blocks that we're jumping out of. */
+ while (f->f_iblock > new_iblock) {
+ PyTryBlock *b = &f->f_blockstack[--f->f_iblock];
+ while ((f->f_stacktop - f->f_valuestack) > b->b_level) {
+ PyObject *v = (*--f->f_stacktop);
+ Py_DECREF(v);
+ }
+ }
+
+ /* Finally set the new f_lineno and f_lasti and return OK. */
+ f->f_lineno = new_lineno;
+ f->f_lasti = new_lasti;
+ return 0;
}
static PyObject *
frame_gettrace(PyFrameObject *f, void *closure)
{
- PyObject* trace = f->f_trace;
+ PyObject* trace = f->f_trace;
- if (trace == NULL)
- trace = Py_None;
+ if (trace == NULL)
+ trace = Py_None;
- Py_INCREF(trace);
+ Py_INCREF(trace);
- return trace;
+ return trace;
}
static int
frame_settrace(PyFrameObject *f, PyObject* v, void *closure)
{
- PyObject* old_value;
+ PyObject* old_value;
- /* We rely on f_lineno being accurate when f_trace is set. */
- f->f_lineno = PyFrame_GetLineNumber(f);
+ /* We rely on f_lineno being accurate when f_trace is set. */
+ f->f_lineno = PyFrame_GetLineNumber(f);
- old_value = f->f_trace;
- Py_XINCREF(v);
- f->f_trace = v;
- Py_XDECREF(old_value);
+ old_value = f->f_trace;
+ Py_XINCREF(v);
+ f->f_trace = v;
+ Py_XDECREF(old_value);
- return 0;
+ return 0;
}
static PyGetSetDef frame_getsetlist[] = {
- {"f_locals", (getter)frame_getlocals, NULL, NULL},
- {"f_lineno", (getter)frame_getlineno,
- (setter)frame_setlineno, NULL},
- {"f_trace", (getter)frame_gettrace, (setter)frame_settrace, NULL},
- {0}
+ {"f_locals", (getter)frame_getlocals, NULL, NULL},
+ {"f_lineno", (getter)frame_getlineno,
+ (setter)frame_setlineno, NULL},
+ {"f_trace", (getter)frame_gettrace, (setter)frame_settrace, NULL},
+ {0}
};
/* Stack frames are allocated and deallocated at a considerable rate.
@@ -383,7 +383,7 @@ static PyGetSetDef frame_getsetlist[] = {
the following fields are still valid:
* ob_type, ob_size, f_code, f_valuestack;
-
+
* f_locals, f_trace,
f_exc_type, f_exc_value, f_exc_traceback are NULL;
@@ -394,10 +394,10 @@ static PyGetSetDef frame_getsetlist[] = {
integers are allocated in a special way -- see intobject.c). When
a stack frame is on the free list, only the following members have
a meaning:
- ob_type == &Frametype
- f_back next item on free list, or NULL
- f_stacksize size of value stack
- ob_size size of localsplus
+ ob_type == &Frametype
+ f_back next item on free list, or NULL
+ f_stacksize size of value stack
+ ob_size size of localsplus
Note that the value and block stacks are preserved -- this can save
another malloc() call or two (and two free() calls as well!).
Also note that, unlike for integers, each frame object is a
@@ -413,307 +413,307 @@ static PyGetSetDef frame_getsetlist[] = {
*/
static PyFrameObject *free_list = NULL;
-static int numfree = 0; /* number of frames currently in free_list */
+static int numfree = 0; /* number of frames currently in free_list */
/* max value for numfree */
-#define PyFrame_MAXFREELIST 200
+#define PyFrame_MAXFREELIST 200
static void
frame_dealloc(PyFrameObject *f)
{
- PyObject **p, **valuestack;
- PyCodeObject *co;
-
- PyObject_GC_UnTrack(f);
- Py_TRASHCAN_SAFE_BEGIN(f)
- /* Kill all local variables */
- valuestack = f->f_valuestack;
- for (p = f->f_localsplus; p < valuestack; p++)
- Py_CLEAR(*p);
-
- /* Free stack */
- if (f->f_stacktop != NULL) {
- for (p = valuestack; p < f->f_stacktop; p++)
- Py_XDECREF(*p);
- }
-
- Py_XDECREF(f->f_back);
- Py_DECREF(f->f_builtins);
- Py_DECREF(f->f_globals);
- Py_CLEAR(f->f_locals);
- Py_CLEAR(f->f_trace);
- Py_CLEAR(f->f_exc_type);
- Py_CLEAR(f->f_exc_value);
- Py_CLEAR(f->f_exc_traceback);
-
- co = f->f_code;
- if (co->co_zombieframe == NULL)
- co->co_zombieframe = f;
- else if (numfree < PyFrame_MAXFREELIST) {
- ++numfree;
- f->f_back = free_list;
- free_list = f;
- }
- else
- PyObject_GC_Del(f);
-
- Py_DECREF(co);
- Py_TRASHCAN_SAFE_END(f)
+ PyObject **p, **valuestack;
+ PyCodeObject *co;
+
+ PyObject_GC_UnTrack(f);
+ Py_TRASHCAN_SAFE_BEGIN(f)
+ /* Kill all local variables */
+ valuestack = f->f_valuestack;
+ for (p = f->f_localsplus; p < valuestack; p++)
+ Py_CLEAR(*p);
+
+ /* Free stack */
+ if (f->f_stacktop != NULL) {
+ for (p = valuestack; p < f->f_stacktop; p++)
+ Py_XDECREF(*p);
+ }
+
+ Py_XDECREF(f->f_back);
+ Py_DECREF(f->f_builtins);
+ Py_DECREF(f->f_globals);
+ Py_CLEAR(f->f_locals);
+ Py_CLEAR(f->f_trace);
+ Py_CLEAR(f->f_exc_type);
+ Py_CLEAR(f->f_exc_value);
+ Py_CLEAR(f->f_exc_traceback);
+
+ co = f->f_code;
+ if (co->co_zombieframe == NULL)
+ co->co_zombieframe = f;
+ else if (numfree < PyFrame_MAXFREELIST) {
+ ++numfree;
+ f->f_back = free_list;
+ free_list = f;
+ }
+ else
+ PyObject_GC_Del(f);
+
+ Py_DECREF(co);
+ Py_TRASHCAN_SAFE_END(f)
}
static int
frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
{
- PyObject **fastlocals, **p;
- int i, slots;
-
- Py_VISIT(f->f_back);
- Py_VISIT(f->f_code);
- Py_VISIT(f->f_builtins);
- Py_VISIT(f->f_globals);
- Py_VISIT(f->f_locals);
- Py_VISIT(f->f_trace);
- Py_VISIT(f->f_exc_type);
- Py_VISIT(f->f_exc_value);
- Py_VISIT(f->f_exc_traceback);
-
- /* locals */
- slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
- fastlocals = f->f_localsplus;
- for (i = slots; --i >= 0; ++fastlocals)
- Py_VISIT(*fastlocals);
-
- /* stack */
- if (f->f_stacktop != NULL) {
- for (p = f->f_valuestack; p < f->f_stacktop; p++)
- Py_VISIT(*p);
- }
- return 0;
+ PyObject **fastlocals, **p;
+ int i, slots;
+
+ Py_VISIT(f->f_back);
+ Py_VISIT(f->f_code);
+ Py_VISIT(f->f_builtins);
+ Py_VISIT(f->f_globals);
+ Py_VISIT(f->f_locals);
+ Py_VISIT(f->f_trace);
+ Py_VISIT(f->f_exc_type);
+ Py_VISIT(f->f_exc_value);
+ Py_VISIT(f->f_exc_traceback);
+
+ /* locals */
+ slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
+ fastlocals = f->f_localsplus;
+ for (i = slots; --i >= 0; ++fastlocals)
+ Py_VISIT(*fastlocals);
+
+ /* stack */
+ if (f->f_stacktop != NULL) {
+ for (p = f->f_valuestack; p < f->f_stacktop; p++)
+ Py_VISIT(*p);
+ }
+ return 0;
}
static void
frame_clear(PyFrameObject *f)
{
- PyObject **fastlocals, **p, **oldtop;
- int i, slots;
-
- /* Before anything else, make sure that this frame is clearly marked
- * as being defunct! Else, e.g., a generator reachable from this
- * frame may also point to this frame, believe itself to still be
- * active, and try cleaning up this frame again.
- */
- oldtop = f->f_stacktop;
- f->f_stacktop = NULL;
-
- Py_CLEAR(f->f_exc_type);
- Py_CLEAR(f->f_exc_value);
- Py_CLEAR(f->f_exc_traceback);
- Py_CLEAR(f->f_trace);
-
- /* locals */
- slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
- fastlocals = f->f_localsplus;
- for (i = slots; --i >= 0; ++fastlocals)
- Py_CLEAR(*fastlocals);
-
- /* stack */
- if (oldtop != NULL) {
- for (p = f->f_valuestack; p < oldtop; p++)
- Py_CLEAR(*p);
- }
+ PyObject **fastlocals, **p, **oldtop;
+ int i, slots;
+
+ /* Before anything else, make sure that this frame is clearly marked
+ * as being defunct! Else, e.g., a generator reachable from this
+ * frame may also point to this frame, believe itself to still be
+ * active, and try cleaning up this frame again.
+ */
+ oldtop = f->f_stacktop;
+ f->f_stacktop = NULL;
+
+ Py_CLEAR(f->f_exc_type);
+ Py_CLEAR(f->f_exc_value);
+ Py_CLEAR(f->f_exc_traceback);
+ Py_CLEAR(f->f_trace);
+
+ /* locals */
+ slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
+ fastlocals = f->f_localsplus;
+ for (i = slots; --i >= 0; ++fastlocals)
+ Py_CLEAR(*fastlocals);
+
+ /* stack */
+ if (oldtop != NULL) {
+ for (p = f->f_valuestack; p < oldtop; p++)
+ Py_CLEAR(*p);
+ }
}
static PyObject *
frame_sizeof(PyFrameObject *f)
{
- Py_ssize_t res, extras, ncells, nfrees;
+ Py_ssize_t res, extras, ncells, nfrees;
- ncells = PyTuple_GET_SIZE(f->f_code->co_cellvars);
- nfrees = PyTuple_GET_SIZE(f->f_code->co_freevars);
- extras = f->f_code->co_stacksize + f->f_code->co_nlocals +
- ncells + nfrees;
- /* subtract one as it is already included in PyFrameObject */
- res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *);
+ ncells = PyTuple_GET_SIZE(f->f_code->co_cellvars);
+ nfrees = PyTuple_GET_SIZE(f->f_code->co_freevars);
+ extras = f->f_code->co_stacksize + f->f_code->co_nlocals +
+ ncells + nfrees;
+ /* subtract one as it is already included in PyFrameObject */
+ res = sizeof(PyFrameObject) + (extras-1) * sizeof(PyObject *);
- return PyLong_FromSsize_t(res);
+ return PyLong_FromSsize_t(res);
}
PyDoc_STRVAR(sizeof__doc__,
"F.__sizeof__() -> size of F in memory, in bytes");
static PyMethodDef frame_methods[] = {
- {"__sizeof__", (PyCFunction)frame_sizeof, METH_NOARGS,
- sizeof__doc__},
- {NULL, NULL} /* sentinel */
+ {"__sizeof__", (PyCFunction)frame_sizeof, METH_NOARGS,
+ sizeof__doc__},
+ {NULL, NULL} /* sentinel */
};
PyTypeObject PyFrame_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "frame",
- sizeof(PyFrameObject),
- sizeof(PyObject *),
- (destructor)frame_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)frame_traverse, /* tp_traverse */
- (inquiry)frame_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- frame_methods, /* tp_methods */
- frame_memberlist, /* tp_members */
- frame_getsetlist, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "frame",
+ sizeof(PyFrameObject),
+ sizeof(PyObject *),
+ (destructor)frame_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_reserved */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ PyObject_GenericGetAttr, /* tp_getattro */
+ PyObject_GenericSetAttr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
+ 0, /* tp_doc */
+ (traverseproc)frame_traverse, /* tp_traverse */
+ (inquiry)frame_clear, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ frame_methods, /* tp_methods */
+ frame_memberlist, /* tp_members */
+ frame_getsetlist, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
};
static PyObject *builtin_object;
int _PyFrame_Init()
{
- builtin_object = PyUnicode_InternFromString("__builtins__");
- if (builtin_object == NULL)
- return 0;
- return 1;
+ builtin_object = PyUnicode_InternFromString("__builtins__");
+ if (builtin_object == NULL)
+ return 0;
+ return 1;
}
PyFrameObject *
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
- PyObject *locals)
+ PyObject *locals)
{
- PyFrameObject *back = tstate->frame;
- PyFrameObject *f;
- PyObject *builtins;
- Py_ssize_t i;
+ PyFrameObject *back = tstate->frame;
+ PyFrameObject *f;
+ PyObject *builtins;
+ Py_ssize_t i;
#ifdef Py_DEBUG
- if (code == NULL || globals == NULL || !PyDict_Check(globals) ||
- (locals != NULL && !PyMapping_Check(locals))) {
- PyErr_BadInternalCall();
- return NULL;
- }
+ if (code == NULL || globals == NULL || !PyDict_Check(globals) ||
+ (locals != NULL && !PyMapping_Check(locals))) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
#endif
- if (back == NULL || back->f_globals != globals) {
- builtins = PyDict_GetItem(globals, builtin_object);
- if (builtins) {
- if (PyModule_Check(builtins)) {
- builtins = PyModule_GetDict(builtins);
- assert(!builtins || PyDict_Check(builtins));
- }
- else if (!PyDict_Check(builtins))
- builtins = NULL;
- }
- if (builtins == NULL) {
- /* No builtins! Make up a minimal one
- Give them 'None', at least. */
- builtins = PyDict_New();
- if (builtins == NULL ||
- PyDict_SetItemString(
- builtins, "None", Py_None) < 0)
- return NULL;
- }
- else
- Py_INCREF(builtins);
-
- }
- else {
- /* If we share the globals, we share the builtins.
- Save a lookup and a call. */
- builtins = back->f_builtins;
- assert(builtins != NULL && PyDict_Check(builtins));
- Py_INCREF(builtins);
- }
- if (code->co_zombieframe != NULL) {
- f = code->co_zombieframe;
- code->co_zombieframe = NULL;
- _Py_NewReference((PyObject *)f);
- assert(f->f_code == code);
- }
- else {
- Py_ssize_t extras, ncells, nfrees;
- ncells = PyTuple_GET_SIZE(code->co_cellvars);
- nfrees = PyTuple_GET_SIZE(code->co_freevars);
- extras = code->co_stacksize + code->co_nlocals + ncells +
- nfrees;
- if (free_list == NULL) {
- f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type,
- extras);
- if (f == NULL) {
- Py_DECREF(builtins);
- return NULL;
- }
- }
- else {
- assert(numfree > 0);
- --numfree;
- f = free_list;
- free_list = free_list->f_back;
- if (Py_SIZE(f) < extras) {
- f = PyObject_GC_Resize(PyFrameObject, f, extras);
- if (f == NULL) {
- Py_DECREF(builtins);
- return NULL;
- }
- }
- _Py_NewReference((PyObject *)f);
- }
-
- f->f_code = code;
- extras = code->co_nlocals + ncells + nfrees;
- f->f_valuestack = f->f_localsplus + extras;
- for (i=0; i<extras; i++)
- f->f_localsplus[i] = NULL;
- f->f_locals = NULL;
- f->f_trace = NULL;
- f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL;
- }
- f->f_stacktop = f->f_valuestack;
- f->f_builtins = builtins;
- Py_XINCREF(back);
- f->f_back = back;
- Py_INCREF(code);
- Py_INCREF(globals);
- f->f_globals = globals;
- /* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */
- if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) ==
- (CO_NEWLOCALS | CO_OPTIMIZED))
- ; /* f_locals = NULL; will be set by PyFrame_FastToLocals() */
- else if (code->co_flags & CO_NEWLOCALS) {
- locals = PyDict_New();
- if (locals == NULL) {
- Py_DECREF(f);
- return NULL;
- }
- f->f_locals = locals;
- }
- else {
- if (locals == NULL)
- locals = globals;
- Py_INCREF(locals);
- f->f_locals = locals;
- }
- f->f_tstate = tstate;
-
- f->f_lasti = -1;
- f->f_lineno = code->co_firstlineno;
- f->f_iblock = 0;
-
- _PyObject_GC_TRACK(f);
- return f;
+ if (back == NULL || back->f_globals != globals) {
+ builtins = PyDict_GetItem(globals, builtin_object);
+ if (builtins) {
+ if (PyModule_Check(builtins)) {
+ builtins = PyModule_GetDict(builtins);
+ assert(!builtins || PyDict_Check(builtins));
+ }
+ else if (!PyDict_Check(builtins))
+ builtins = NULL;
+ }
+ if (builtins == NULL) {
+ /* No builtins! Make up a minimal one
+ Give them 'None', at least. */
+ builtins = PyDict_New();
+ if (builtins == NULL ||
+ PyDict_SetItemString(
+ builtins, "None", Py_None) < 0)
+ return NULL;
+ }
+ else
+ Py_INCREF(builtins);
+
+ }
+ else {
+ /* If we share the globals, we share the builtins.
+ Save a lookup and a call. */
+ builtins = back->f_builtins;
+ assert(builtins != NULL && PyDict_Check(builtins));
+ Py_INCREF(builtins);
+ }
+ if (code->co_zombieframe != NULL) {
+ f = code->co_zombieframe;
+ code->co_zombieframe = NULL;
+ _Py_NewReference((PyObject *)f);
+ assert(f->f_code == code);
+ }
+ else {
+ Py_ssize_t extras, ncells, nfrees;
+ ncells = PyTuple_GET_SIZE(code->co_cellvars);
+ nfrees = PyTuple_GET_SIZE(code->co_freevars);
+ extras = code->co_stacksize + code->co_nlocals + ncells +
+ nfrees;
+ if (free_list == NULL) {
+ f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type,
+ extras);
+ if (f == NULL) {
+ Py_DECREF(builtins);
+ return NULL;
+ }
+ }
+ else {
+ assert(numfree > 0);
+ --numfree;
+ f = free_list;
+ free_list = free_list->f_back;
+ if (Py_SIZE(f) < extras) {
+ f = PyObject_GC_Resize(PyFrameObject, f, extras);
+ if (f == NULL) {
+ Py_DECREF(builtins);
+ return NULL;
+ }
+ }
+ _Py_NewReference((PyObject *)f);
+ }
+
+ f->f_code = code;
+ extras = code->co_nlocals + ncells + nfrees;
+ f->f_valuestack = f->f_localsplus + extras;
+ for (i=0; i<extras; i++)
+ f->f_localsplus[i] = NULL;
+ f->f_locals = NULL;
+ f->f_trace = NULL;
+ f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL;
+ }
+ f->f_stacktop = f->f_valuestack;
+ f->f_builtins = builtins;
+ Py_XINCREF(back);
+ f->f_back = back;
+ Py_INCREF(code);
+ Py_INCREF(globals);
+ f->f_globals = globals;
+ /* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */
+ if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) ==
+ (CO_NEWLOCALS | CO_OPTIMIZED))
+ ; /* f_locals = NULL; will be set by PyFrame_FastToLocals() */
+ else if (code->co_flags & CO_NEWLOCALS) {
+ locals = PyDict_New();
+ if (locals == NULL) {
+ Py_DECREF(f);
+ return NULL;
+ }
+ f->f_locals = locals;
+ }
+ else {
+ if (locals == NULL)
+ locals = globals;
+ Py_INCREF(locals);
+ f->f_locals = locals;
+ }
+ f->f_tstate = tstate;
+
+ f->f_lasti = -1;
+ f->f_lineno = code->co_firstlineno;
+ f->f_iblock = 0;
+
+ _PyObject_GC_TRACK(f);
+ return f;
}
/* Block management */
@@ -721,28 +721,28 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
void
PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level)
{
- PyTryBlock *b;
- if (f->f_iblock >= CO_MAXBLOCKS)
- Py_FatalError("XXX block stack overflow");
- b = &f->f_blockstack[f->f_iblock++];
- b->b_type = type;
- b->b_level = level;
- b->b_handler = handler;
+ PyTryBlock *b;
+ if (f->f_iblock >= CO_MAXBLOCKS)
+ Py_FatalError("XXX block stack overflow");
+ b = &f->f_blockstack[f->f_iblock++];
+ b->b_type = type;
+ b->b_level = level;
+ b->b_handler = handler;
}
PyTryBlock *
PyFrame_BlockPop(PyFrameObject *f)
{
- PyTryBlock *b;
- if (f->f_iblock <= 0)
- Py_FatalError("XXX block stack underflow");
- b = &f->f_blockstack[--f->f_iblock];
- return b;
+ PyTryBlock *b;
+ if (f->f_iblock <= 0)
+ Py_FatalError("XXX block stack underflow");
+ b = &f->f_blockstack[--f->f_iblock];
+ return b;
}
/* Convert between "fast" version of locals and dictionary version.
-
- map and values are input arguments. map is a tuple of strings.
+
+ map and values are input arguments. map is a tuple of strings.
values is an array of PyObject*. At index i, map[i] is the name of
the variable with value values[i]. The function copies the first
nmap variable from map/values into dict. If values[i] is NULL,
@@ -758,29 +758,29 @@ PyFrame_BlockPop(PyFrameObject *f)
static void
map_to_dict(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
- int deref)
+ int deref)
{
- Py_ssize_t j;
- assert(PyTuple_Check(map));
- assert(PyDict_Check(dict));
- assert(PyTuple_Size(map) >= nmap);
- for (j = nmap; --j >= 0; ) {
- PyObject *key = PyTuple_GET_ITEM(map, j);
- PyObject *value = values[j];
- assert(PyUnicode_Check(key));
- if (deref) {
- assert(PyCell_Check(value));
- value = PyCell_GET(value);
- }
- if (value == NULL) {
- if (PyObject_DelItem(dict, key) != 0)
- PyErr_Clear();
- }
- else {
- if (PyObject_SetItem(dict, key, value) != 0)
- PyErr_Clear();
- }
- }
+ Py_ssize_t j;
+ assert(PyTuple_Check(map));
+ assert(PyDict_Check(dict));
+ assert(PyTuple_Size(map) >= nmap);
+ for (j = nmap; --j >= 0; ) {
+ PyObject *key = PyTuple_GET_ITEM(map, j);
+ PyObject *value = values[j];
+ assert(PyUnicode_Check(key));
+ if (deref) {
+ assert(PyCell_Check(value));
+ value = PyCell_GET(value);
+ }
+ if (value == NULL) {
+ if (PyObject_DelItem(dict, key) != 0)
+ PyErr_Clear();
+ }
+ else {
+ if (PyObject_SetItem(dict, key, value) != 0)
+ PyErr_Clear();
+ }
+ }
}
/* Copy values from the "locals" dict into the fast locals.
@@ -788,7 +788,7 @@ map_to_dict(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
dict is an input argument containing string keys representing
variables names and arbitrary PyObject* as values.
- map and values are input arguments. map is a tuple of strings.
+ map and values are input arguments. map is a tuple of strings.
values is an array of PyObject*. At index i, map[i] is the name of
the variable with value values[i]. The function copies the first
nmap variable from map/values into dict. If values[i] is NULL,
@@ -806,150 +806,150 @@ map_to_dict(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
static void
dict_to_map(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
- int deref, int clear)
+ int deref, int clear)
{
- Py_ssize_t j;
- assert(PyTuple_Check(map));
- assert(PyDict_Check(dict));
- assert(PyTuple_Size(map) >= nmap);
- for (j = nmap; --j >= 0; ) {
- PyObject *key = PyTuple_GET_ITEM(map, j);
- PyObject *value = PyObject_GetItem(dict, key);
- assert(PyUnicode_Check(key));
- /* We only care about NULLs if clear is true. */
- if (value == NULL) {
- PyErr_Clear();
- if (!clear)
- continue;
- }
- if (deref) {
- assert(PyCell_Check(values[j]));
- if (PyCell_GET(values[j]) != value) {
- if (PyCell_Set(values[j], value) < 0)
- PyErr_Clear();
- }
- } else if (values[j] != value) {
- Py_XINCREF(value);
- Py_XDECREF(values[j]);
- values[j] = value;
- }
- Py_XDECREF(value);
- }
+ Py_ssize_t j;
+ assert(PyTuple_Check(map));
+ assert(PyDict_Check(dict));
+ assert(PyTuple_Size(map) >= nmap);
+ for (j = nmap; --j >= 0; ) {
+ PyObject *key = PyTuple_GET_ITEM(map, j);
+ PyObject *value = PyObject_GetItem(dict, key);
+ assert(PyUnicode_Check(key));
+ /* We only care about NULLs if clear is true. */
+ if (value == NULL) {
+ PyErr_Clear();
+ if (!clear)
+ continue;
+ }
+ if (deref) {
+ assert(PyCell_Check(values[j]));
+ if (PyCell_GET(values[j]) != value) {
+ if (PyCell_Set(values[j], value) < 0)
+ PyErr_Clear();
+ }
+ } else if (values[j] != value) {
+ Py_XINCREF(value);
+ Py_XDECREF(values[j]);
+ values[j] = value;
+ }
+ Py_XDECREF(value);
+ }
}
void
PyFrame_FastToLocals(PyFrameObject *f)
{
- /* Merge fast locals into f->f_locals */
- PyObject *locals, *map;
- PyObject **fast;
- PyObject *error_type, *error_value, *error_traceback;
- PyCodeObject *co;
- Py_ssize_t j;
- int ncells, nfreevars;
- if (f == NULL)
- return;
- locals = f->f_locals;
- if (locals == NULL) {
- locals = f->f_locals = PyDict_New();
- if (locals == NULL) {
- PyErr_Clear(); /* Can't report it :-( */
- return;
- }
- }
- co = f->f_code;
- map = co->co_varnames;
- if (!PyTuple_Check(map))
- return;
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
- fast = f->f_localsplus;
- j = PyTuple_GET_SIZE(map);
- if (j > co->co_nlocals)
- j = co->co_nlocals;
- if (co->co_nlocals)
- map_to_dict(map, j, locals, fast, 0);
- ncells = PyTuple_GET_SIZE(co->co_cellvars);
- nfreevars = PyTuple_GET_SIZE(co->co_freevars);
- if (ncells || nfreevars) {
- map_to_dict(co->co_cellvars, ncells,
- locals, fast + co->co_nlocals, 1);
- /* If the namespace is unoptimized, then one of the
- following cases applies:
- 1. It does not contain free variables, because it
- uses import * or is a top-level namespace.
- 2. It is a class namespace.
- We don't want to accidentally copy free variables
- into the locals dict used by the class.
- */
- if (co->co_flags & CO_OPTIMIZED) {
- map_to_dict(co->co_freevars, nfreevars,
- locals, fast + co->co_nlocals + ncells, 1);
- }
- }
- PyErr_Restore(error_type, error_value, error_traceback);
+ /* Merge fast locals into f->f_locals */
+ PyObject *locals, *map;
+ PyObject **fast;
+ PyObject *error_type, *error_value, *error_traceback;
+ PyCodeObject *co;
+ Py_ssize_t j;
+ int ncells, nfreevars;
+ if (f == NULL)
+ return;
+ locals = f->f_locals;
+ if (locals == NULL) {
+ locals = f->f_locals = PyDict_New();
+ if (locals == NULL) {
+ PyErr_Clear(); /* Can't report it :-( */
+ return;
+ }
+ }
+ co = f->f_code;
+ map = co->co_varnames;
+ if (!PyTuple_Check(map))
+ return;
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ fast = f->f_localsplus;
+ j = PyTuple_GET_SIZE(map);
+ if (j > co->co_nlocals)
+ j = co->co_nlocals;
+ if (co->co_nlocals)
+ map_to_dict(map, j, locals, fast, 0);
+ ncells = PyTuple_GET_SIZE(co->co_cellvars);
+ nfreevars = PyTuple_GET_SIZE(co->co_freevars);
+ if (ncells || nfreevars) {
+ map_to_dict(co->co_cellvars, ncells,
+ locals, fast + co->co_nlocals, 1);
+ /* If the namespace is unoptimized, then one of the
+ following cases applies:
+ 1. It does not contain free variables, because it
+ uses import * or is a top-level namespace.
+ 2. It is a class namespace.
+ We don't want to accidentally copy free variables
+ into the locals dict used by the class.
+ */
+ if (co->co_flags & CO_OPTIMIZED) {
+ map_to_dict(co->co_freevars, nfreevars,
+ locals, fast + co->co_nlocals + ncells, 1);
+ }
+ }
+ PyErr_Restore(error_type, error_value, error_traceback);
}
void
PyFrame_LocalsToFast(PyFrameObject *f, int clear)
{
- /* Merge f->f_locals into fast locals */
- PyObject *locals, *map;
- PyObject **fast;
- PyObject *error_type, *error_value, *error_traceback;
- PyCodeObject *co;
- Py_ssize_t j;
- int ncells, nfreevars;
- if (f == NULL)
- return;
- locals = f->f_locals;
- co = f->f_code;
- map = co->co_varnames;
- if (locals == NULL)
- return;
- if (!PyTuple_Check(map))
- return;
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
- fast = f->f_localsplus;
- j = PyTuple_GET_SIZE(map);
- if (j > co->co_nlocals)
- j = co->co_nlocals;
- if (co->co_nlocals)
- dict_to_map(co->co_varnames, j, locals, fast, 0, clear);
- ncells = PyTuple_GET_SIZE(co->co_cellvars);
- nfreevars = PyTuple_GET_SIZE(co->co_freevars);
- if (ncells || nfreevars) {
- dict_to_map(co->co_cellvars, ncells,
- locals, fast + co->co_nlocals, 1, clear);
- /* Same test as in PyFrame_FastToLocals() above. */
- if (co->co_flags & CO_OPTIMIZED) {
- dict_to_map(co->co_freevars, nfreevars,
- locals, fast + co->co_nlocals + ncells, 1,
- clear);
- }
- }
- PyErr_Restore(error_type, error_value, error_traceback);
+ /* Merge f->f_locals into fast locals */
+ PyObject *locals, *map;
+ PyObject **fast;
+ PyObject *error_type, *error_value, *error_traceback;
+ PyCodeObject *co;
+ Py_ssize_t j;
+ int ncells, nfreevars;
+ if (f == NULL)
+ return;
+ locals = f->f_locals;
+ co = f->f_code;
+ map = co->co_varnames;
+ if (locals == NULL)
+ return;
+ if (!PyTuple_Check(map))
+ return;
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ fast = f->f_localsplus;
+ j = PyTuple_GET_SIZE(map);
+ if (j > co->co_nlocals)
+ j = co->co_nlocals;
+ if (co->co_nlocals)
+ dict_to_map(co->co_varnames, j, locals, fast, 0, clear);
+ ncells = PyTuple_GET_SIZE(co->co_cellvars);
+ nfreevars = PyTuple_GET_SIZE(co->co_freevars);
+ if (ncells || nfreevars) {
+ dict_to_map(co->co_cellvars, ncells,
+ locals, fast + co->co_nlocals, 1, clear);
+ /* Same test as in PyFrame_FastToLocals() above. */
+ if (co->co_flags & CO_OPTIMIZED) {
+ dict_to_map(co->co_freevars, nfreevars,
+ locals, fast + co->co_nlocals + ncells, 1,
+ clear);
+ }
+ }
+ PyErr_Restore(error_type, error_value, error_traceback);
}
/* Clear out the free list */
int
PyFrame_ClearFreeList(void)
{
- int freelist_size = numfree;
-
- while (free_list != NULL) {
- PyFrameObject *f = free_list;
- free_list = free_list->f_back;
- PyObject_GC_Del(f);
- --numfree;
- }
- assert(numfree == 0);
- return freelist_size;
+ int freelist_size = numfree;
+
+ while (free_list != NULL) {
+ PyFrameObject *f = free_list;
+ free_list = free_list->f_back;
+ PyObject_GC_Del(f);
+ --numfree;
+ }
+ assert(numfree == 0);
+ return freelist_size;
}
void
PyFrame_Fini(void)
{
- (void)PyFrame_ClearFreeList();
- Py_XDECREF(builtin_object);
- builtin_object = NULL;
+ (void)PyFrame_ClearFreeList();
+ Py_XDECREF(builtin_object);
+ builtin_object = NULL;
}