diff Python/compile.c @ 54889:3aaf2e065db0

Merged revisions 72912,72920,72940 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r72912 | benjamin.peterson | 2009-05-25 08:13:44 -0500 (Mon, 25 May 2009) | 5 lines add a SETUP_WITH opcode It speeds up the with statement and correctly looks up the special methods involved. ........ r72920 | benjamin.peterson | 2009-05-25 15:12:57 -0500 (Mon, 25 May 2009) | 1 line take into account the fact that SETUP_WITH pushes a finally block ........ r72940 | benjamin.peterson | 2009-05-26 07:49:59 -0500 (Tue, 26 May 2009) | 1 line teach the peepholer about SETUP_WITH ........
author Benjamin Peterson <benjamin@python.org>
date Sun, 28 Jun 2009 03:18:59 +0000
parents 911df82bc25d
children 1e5589a17cf0
line wrap: on
line diff
--- a/Python/compile.c	Sat Jun 27 23:45:02 2009 +0000
+++ b/Python/compile.c	Sun Jun 28 03:18:59 2009 +0000
@@ -761,6 +761,8 @@
 			return -1;
 		case BREAK_LOOP:
 			return 0;
+	        case SETUP_WITH:
+			return 7;
 		case WITH_CLEANUP:
 			return -1; /* XXX Sometimes more */
 		case STORE_LOCALS:
@@ -3085,85 +3087,31 @@
 static int
 compiler_with(struct compiler *c, stmt_ty s)
 {
-    static identifier enter_attr, exit_attr;
     basicblock *block, *finally;
-    identifier tmpvalue = NULL, tmpexit = NULL;
 
     assert(s->kind == With_kind);
 
-    if (!enter_attr) {
-	enter_attr = PyUnicode_InternFromString("__enter__");
-	if (!enter_attr)
-	    return 0;
-    }
-    if (!exit_attr) {
-	exit_attr = PyUnicode_InternFromString("__exit__");
-	if (!exit_attr)
-	    return 0;
-    }
-
     block = compiler_new_block(c);
     finally = compiler_new_block(c);
     if (!block || !finally)
 	return 0;
 
-    if (s->v.With.optional_vars) {
-	/* Create a temporary variable to hold context.__enter__().
-	   We need to do this rather than preserving it on the stack
-	   because SETUP_FINALLY remembers the stack level.
-	   We need to do the assignment *inside* the try/finally
-	   so that context.__exit__() is called when the assignment
-	   fails.  But we need to call context.__enter__() *before*
-	   the try/finally so that if it fails we won't call
-	   context.__exit__().
-	*/
-	tmpvalue = compiler_new_tmpname(c);
-	if (tmpvalue == NULL)
-	    return 0;
-	PyArena_AddPyObject(c->c_arena, tmpvalue);
-    }
-	tmpexit = compiler_new_tmpname(c);
-	if (tmpexit == NULL)
-	    return 0;
-	PyArena_AddPyObject(c->c_arena, tmpexit);
-
     /* Evaluate EXPR */
     VISIT(c, expr, s->v.With.context_expr);
-
-    /* Squirrel away context.__exit__ by stuffing it under context */
-    ADDOP(c, DUP_TOP);
-    ADDOP_O(c, LOAD_ATTR, exit_attr, names);
-	if (!compiler_nameop(c, tmpexit, Store))
-	    return 0;
-
-    /* Call context.__enter__() */
-    ADDOP_O(c, LOAD_ATTR, enter_attr, names);
-    ADDOP_I(c, CALL_FUNCTION, 0);
-
-    if (s->v.With.optional_vars) {
-	/* Store it in tmpvalue */
-	if (!compiler_nameop(c, tmpvalue, Store))
-	    return 0;
-    }
-    else {
-	/* Discard result from context.__enter__() */
-	ADDOP(c, POP_TOP);
-    }
-
-    /* Start the try block */
-    ADDOP_JREL(c, SETUP_FINALLY, finally);
-
+    ADDOP_JREL(c, SETUP_WITH, finally);
+
+    /* SETUP_WITH pushes a finally block. */
     compiler_use_next_block(c, block);
     if (!compiler_push_fblock(c, FINALLY_TRY, block)) {
 	return 0;
     }
 
     if (s->v.With.optional_vars) {
-	/* Bind saved result of context.__enter__() to VAR */
-	if (!compiler_nameop(c, tmpvalue, Load) ||
-	    !compiler_nameop(c, tmpvalue, Del))
-	  return 0;
-	VISIT(c, expr, s->v.With.optional_vars);
+        VISIT(c, expr, s->v.With.optional_vars);
+    }
+    else {
+        /* Discard result from context.__enter__() */
+        ADDOP(c, POP_TOP);
     }
 
     /* BLOCK code */
@@ -3181,9 +3129,6 @@
     /* Finally block starts; context.__exit__ is on the stack under
        the exception or return information. Just issue our magic
        opcode. */
-	if (!compiler_nameop(c, tmpexit, Load) ||
-		!compiler_nameop(c, tmpexit, Del))
-		return 0;
     ADDOP(c, WITH_CLEANUP);
 
     /* Finally block ends. */