Commits

Alex Gaynor  committed eabb1fc

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

  • Participants
  • Parent commits 963e808

Comments (0)

Files changed (2)

File pypy/module/pypyjit/test/test_pypy_c.py

                          ([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):

File pypy/objspace/descroperation.py

     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__')
         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!"
 
             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.
 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)
         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))
 
                            # not really to be defined in DescrOperation
                            'ord', 'unichr', 'unicode']:
             raise Exception, "missing def for operation %s" % _name
-