Author: georg.brandl
Date: Mon Jun 11 09:26:37 2007
New Revision: 55886

Modified:
   python/branches/p3yk/Lib/test/test_peepholer.py
   python/branches/p3yk/Python/compile.c
   python/branches/p3yk/Python/peephole.c
Log:
Optimize access to True and False in the compiler (if True)
and the peepholer (LOAD_NAME True).


Modified: python/branches/p3yk/Lib/test/test_peepholer.py
==============================================================================
--- python/branches/p3yk/Lib/test/test_peepholer.py     (original)
+++ python/branches/p3yk/Lib/test/test_peepholer.py     Mon Jun 11 09:26:37 2007
@@ -39,16 +39,24 @@
             asm = dis_single(line)
             self.assert_(elem in asm)
 
-    def test_none_as_constant(self):
-        # LOAD_GLOBAL None  -->  LOAD_CONST None
+    def test_global_as_constant(self):
+        # LOAD_GLOBAL None/True/False  -->  LOAD_CONST None/True/False
         def f(x):
             None
+            None
             return x
-        asm = disassemble(f)
-        for elem in ('LOAD_GLOBAL',):
-            self.assert_(elem not in asm)
-        for elem in ('LOAD_CONST', '(None)'):
-            self.assert_(elem in asm)
+        def g(x):
+            True
+            return x
+        def h(x):
+            False
+            return x
+        for func, name in ((f, 'None'), (g, 'True'), (h, 'False')):
+            asm = disassemble(func)
+            for elem in ('LOAD_GLOBAL',):
+                self.assert_(elem not in asm)
+            for elem in ('LOAD_CONST', '('+name+')'):
+                self.assert_(elem in asm)
         def f():
             'Adding a docstring made this test fail in Py2.5.0'
             return None

Modified: python/branches/p3yk/Python/compile.c
==============================================================================
--- python/branches/p3yk/Python/compile.c       (original)
+++ python/branches/p3yk/Python/compile.c       Mon Jun 11 09:26:37 2007
@@ -2948,6 +2948,7 @@
 static int
 expr_constant(expr_ty e)
 {
+       char *id;
        switch (e->kind) {
        case Ellipsis_kind:
                return 1;
@@ -2956,11 +2957,13 @@
        case Str_kind:
                return PyObject_IsTrue(e->v.Str.s);
        case Name_kind:
-               /* __debug__ is not assignable, so we can optimize
-                * it away in if and while statements */
-               if (strcmp(PyString_AS_STRING(e->v.Name.id),
-                          "__debug__") == 0)
-                          return ! Py_OptimizeFlag;
+               /* optimize away names that can't be reassigned */
+               id = PyString_AS_STRING(e->v.Name.id);
+               if (strcmp(id, "True") == 0) return 1;
+               if (strcmp(id, "False") == 0) return 0;
+               if (strcmp(id, "None") == 0) return 0;
+               if (strcmp(id, "__debug__") == 0)
+                       return ! Py_OptimizeFlag;
                /* fall through */
        default:
                return -1;

Modified: python/branches/p3yk/Python/peephole.c
==============================================================================
--- python/branches/p3yk/Python/peephole.c      (original)
+++ python/branches/p3yk/Python/peephole.c      Mon Jun 11 09:26:37 2007
@@ -257,6 +257,37 @@
        return blocks;
 }
 
+/* Helper to replace LOAD_NAME None/True/False with LOAD_CONST
+   Returns: 0 if no change, 1 if change, -1 if error */
+static int
+load_global(unsigned char *codestr, Py_ssize_t i, char *name, PyObject *consts)
+{
+       Py_ssize_t j;
+       PyObject *obj;
+       if (name == NULL)
+               return 0;
+       if (strcmp(name, "None") == 0)
+               obj = Py_None;
+       else if (strcmp(name, "True") == 0)
+               obj = Py_True;
+       else if (strcmp(name, "False") == 0)
+               obj = Py_False;
+       else
+               return 0;
+       for (j = 0; j < PyList_GET_SIZE(consts); j++) {
+               if (PyList_GET_ITEM(consts, j) == obj)
+                       break;
+       }
+       if (j == PyList_GET_SIZE(consts)) {
+               if (PyList_Append(consts, obj) < 0)
+                       return -1;
+       }
+       assert(PyList_GET_ITEM(consts, j) == obj);
+       codestr[i] = LOAD_CONST;
+       SETARG(codestr, i, j);
+       return 1;
+}
+
 /* Perform basic peephole optimizations to components of a code object.
    The consts object should still be in list form to allow new constants 
    to be appended.
@@ -371,25 +402,17 @@
                                codestr[i+3] = NOP;
                                break;
 
-                               /* Replace LOAD_GLOBAL/LOAD_NAME None
-                                   with LOAD_CONST None */
+                               /* Replace LOAD_GLOBAL/LOAD_NAME None/True/False
+                                   with LOAD_CONST None/True/False */
                        case LOAD_NAME:
                        case LOAD_GLOBAL:
                                j = GETARG(codestr, i);
                                name = 
PyString_AsString(PyTuple_GET_ITEM(names, j));
-                               if (name == NULL  ||  strcmp(name, "None") != 0)
+                               h = load_global(codestr, i, name, consts);
+                               if (h < 0)
+                                       goto exitUnchanged;
+                               else if (h == 0)
                                        continue;
-                               for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) {
-                                       if (PyList_GET_ITEM(consts, j) == 
Py_None)
-                                               break;
-                               }
-                               if (j == PyList_GET_SIZE(consts)) {
-                                       if (PyList_Append(consts, Py_None) == 
-1)
-                                               goto exitUnchanged;             
                           
-                               }
-                               assert(PyList_GET_ITEM(consts, j) == Py_None);
-                               codestr[i] = LOAD_CONST;
-                               SETARG(codestr, i, j);
                                cumlc = lastlc + 1;
                                break;
 
_______________________________________________
Python-3000-checkins mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-3000-checkins

Reply via email to