summaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c53
1 files changed, 44 insertions, 9 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 45d0a6ac41..cdd71a89d9 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -45,6 +45,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define CHECKEXC 1 /* Double-check exception checking */
#endif
+#define DEBUG
+
+
/* Forward declarations */
#ifdef LLTRACE
@@ -82,6 +85,7 @@ static object *cmp_outcome PROTO((int, object *, object *));
static int import_from PROTO((object *, object *, object *));
static object *build_class PROTO((object *, object *));
static void locals_2_fast PROTO((frameobject *, int));
+static void fast_2_locals PROTO((frameobject *));
/* Pointer to current frame, used to link new frames to */
@@ -178,6 +182,7 @@ eval_code(co, globals, locals, arg)
object *trace = NULL; /* Trace function or NULL */
object *retval; /* Return value iff why == WHY_RETURN */
char *name; /* Name used by some instructions */
+ int needmerge = 0;
#ifdef LLTRACE
int lltrace = dictlookup(globals, "__lltrace__") != NULL;
#endif
@@ -217,6 +222,18 @@ eval_code(co, globals, locals, arg)
#define POP() BASIC_POP()
#endif
+ if (globals == NULL) {
+ globals = getglobals();
+ if (locals == NULL) {
+ locals = getlocals();
+ needmerge = 1;
+ }
+ }
+ else {
+ if (locals == NULL)
+ locals = globals;
+ }
+
f = newframeobject(
current_frame, /*back*/
co, /*code*/
@@ -1328,11 +1345,17 @@ eval_code(co, globals, locals, arg)
why = WHY_EXCEPTION;
}
}
+
+ if (fastlocals && (f->ob_refcnt > 1 || f->f_locals->ob_refcnt > 2))
+ fast_2_locals(f);
/* Restore previous frame and release the current one */
current_frame = f->f_back;
DECREF(f);
+
+ if (needmerge)
+ locals_2_fast(current_frame, 1);
return retval;
}
@@ -1417,7 +1440,9 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
INCREF(arg);
settupleitem(arglist, 2, arg);
tracing++;
+ fast_2_locals(f);
res = call_object(*p_trace, arglist);
+ locals_2_fast(f, 1);
tracing--;
cleanup:
XDECREF(arglist);
@@ -1447,24 +1472,25 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
}
}
-object *
-getlocals()
-{
- /* Merge f->f_fastlocals into f->f_locals, then return the latter */
+static void
+fast_2_locals(f)
frameobject *f;
+{
+ /* Merge f->f_fastlocals into f->f_locals */
object *locals, *fast, *map;
+ object *error_type, *error_value;
int i;
- f = current_frame;
if (f == NULL)
- return NULL;
+ return;
locals = f->f_locals;
fast = f->f_fastlocals;
map = f->f_localmap;
if (locals == NULL || fast == NULL || map == NULL)
- return locals;
+ return;
if (!is_dictobject(locals) || !is_listobject(fast) ||
!is_dictobject(map))
- return locals;
+ return;
+ err_get(&error_type, &error_value);
i = getdictsize(map);
while (--i >= 0) {
object *key;
@@ -1488,7 +1514,7 @@ getlocals()
err_clear();
}
}
- return locals;
+ err_setval(error_type, error_value);
}
static void
@@ -1539,6 +1565,15 @@ mergelocals()
}
object *
+getlocals()
+{
+ if (current_frame == NULL)
+ return NULL;
+ fast_2_locals(current_frame);
+ return current_frame->f_locals;
+}
+
+object *
getglobals()
{
if (current_frame == NULL)