[pypy-svn] pypy default: Avoid calling space.id when doing == or != compares.

alex_gaynor commits-noreply at bitbucket.org
Mon Jan 17 05:39:03 CET 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r40739:eabb1fc065a7
Date: 2011-01-16 22:38 -0600
http://bitbucket.org/pypy/pypy/changeset/eabb1fc065a7/

Log:	Avoid calling space.id when doing == or != compares.

diff --git a/pypy/module/pypyjit/test/test_pypy_c.py b/pypy/module/pypyjit/test/test_pypy_c.py
--- a/pypy/module/pypyjit/test/test_pypy_c.py
+++ b/pypy/module/pypyjit/test/test_pypy_c.py
@@ -1471,6 +1471,21 @@
                          ([a3, b3], 2000 * res3),
                          count_debug_merge_point=False)
         
+    def test_id_compare_optimization(self):
+        # XXX: lower the instruction count, 35 is the old value.
+        self.run_source("""
+        class A(object):
+            pass
+        def main():
+            i = 0
+            a = A()
+            while i < 5:
+                if A() != a:
+                    pass
+                i += 1
+        """, 35, ([], None))
+        _, compare = self.get_by_bytecode("COMPARE_OP")
+        assert "call" not in compare.get_opnames()
 
 class AppTestJIT(PyPyCJITTests):
     def setup_class(cls):

diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -473,7 +473,7 @@
     else:
         return w_obj
 
-def _cmp(space, w_obj1, w_obj2):
+def _cmp(space, w_obj1, w_obj2, symbol):
     w_typ1 = space.type(w_obj1)
     w_typ2 = space.type(w_obj2)
     w_left_src, w_left_impl = space.lookup_in_type_where(w_typ1, '__cmp__')
@@ -504,9 +504,7 @@
         return space.wrap(1)
     if space.is_w(w_typ1, w_typ2):
         #print "WARNING, comparison by address!"
-        w_id1 = space.id(w_obj1)
-        w_id2 = space.id(w_obj2)
-        lt = space.is_true(space.lt(w_id1, w_id2))
+        lt = _id_cmpr(space, w_obj1, w_obj2, symbol)
     else:
         #print "WARNING, comparison by type name!"
 
@@ -523,14 +521,22 @@
             if name1 != name2:
                 lt = name1 < name2
             else:
-                w_id1 = space.id(w_typ1)
-                w_id2 = space.id(w_typ2)
-                lt = space.is_true(space.lt(w_id1, w_id2))
+                lt = _id_cmpr(space, w_typ1, w_typ2, symbol)
     if lt:
         return space.wrap(-1)
     else:
         return space.wrap(1)
 
+def _id_cmpr(space, w_obj1, w_obj2, symbol):
+    if symbol == "==":
+        return not space.is_w(w_obj1, w_obj2)
+    elif symbol == "!=":
+        return space.is_w(w_obj1, w_obj2)
+    w_id1 = space.id(w_obj1)
+    w_id2 = space.id(w_obj2)
+    return space.is_true(space.lt(w_id1, w_id2))
+
+
 def number_check(space, w_obj):
     # avoid this as much as possible.  It checks if w_obj "looks like"
     # it might be a number-ish thing.
@@ -640,7 +646,6 @@
 def _make_comparison_impl(symbol, specialnames):
     left, right = specialnames
     op = getattr(operator, left)
-    
     def comparison_impl(space, w_obj1, w_obj2):
         w_typ1 = space.type(w_obj1)
         w_typ2 = space.type(w_obj2)
@@ -664,7 +669,7 @@
         if w_res is not None:
             return w_res
         # fallback: lt(a, b) <= lt(cmp(a, b), 0) ...
-        w_res = _cmp(space, w_first, w_second)
+        w_res = _cmp(space, w_first, w_second, symbol)
         res = space.int_w(w_res)
         return space.wrap(op(res, 0))
 
@@ -790,4 +795,3 @@
                            # not really to be defined in DescrOperation
                            'ord', 'unichr', 'unicode']:
             raise Exception, "missing def for operation %s" % _name
-            


More information about the Pypy-commit mailing list