Author: Hakan Ardo <[email protected]>
Branch: jit-short_from_state
Changeset: r44525:edf56e2eb1ae
Date: 2011-05-26 20:00 +0200
http://bitbucket.org/pypy/pypy/changeset/edf56e2eb1ae/

Log:    Allow a VirtualState with two separate boxes to be considered a
        generaltiation of a VirtualState where those two boxes are assumed
        equal. Verify that the VirtualState at the end of a loop is
        compatible with the VirtualState at the start of the loop which
        makes it allowed to close the loop.

diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py 
b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -40,7 +40,10 @@
         if intbound:
             self.intbound = intbound
         else:
-            self.intbound = IntBound(MININT, MAXINT) #IntUnbounded()
+            if isinstance(box, BoxInt):
+                self.intbound = IntBound(MININT, MAXINT)
+            else:
+                self.intbound = IntUnbounded()
 
         if isinstance(box, Const):
             self.make_constant(box)
diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py 
b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -283,6 +283,7 @@
         self.boxes_created_this_iteration = {}
 
         assert jumpop
+        original_jumpargs = jumpop.getarglist()[:]
         values = [self.getvalue(arg) for arg in jumpop.getarglist()]
         jumpargs = virtual_state.make_inputargs(values)
         jumpop.initarglist(jumpargs)
@@ -326,6 +327,18 @@
         jumpop.initarglist(jumpargs)
         self.optimizer.send_extra_operation(jumpop)
         short.append(ResOperation(rop.JUMP, short_jumpargs, None))
+
+        modifier = VirtualStateAdder(self.optimizer)
+        final_virtual_state = modifier.get_virtual_state(original_jumpargs)
+        if not virtual_state.generalization_of(final_virtual_state):
+            # We ended up with a virtual state that is not compatible
+            # and we are thus unable to jump to the start of the loop
+            # XXX Is it possible to end up here? If so, consider:
+            #    - Fallback on having the preamble jump to itself?
+            #    - Would virtual_state.generate_guards make sense here?
+            debug_print("Bad virtual state at end of loop")
+            raise InvalidLoop
+
         return inputargs, short_inputargs, short
 
     def add_op_to_short(self, op, short, short_seen):
diff --git a/pypy/jit/metainterp/optimizeopt/virtualstate.py 
b/pypy/jit/metainterp/optimizeopt/virtualstate.py
--- a/pypy/jit/metainterp/optimizeopt/virtualstate.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualstate.py
@@ -14,12 +14,14 @@
 class AbstractVirtualStateInfo(resume.AbstractVirtualInfo):
     position = -1
     
-    def generalization_of(self, other):
+    def generalization_of(self, other, renum):
         raise NotImplementedError
 
-    def generate_guards(self, other, box, cpu, extra_guards):
-        if self.generalization_of(other):
+    def generate_guards(self, other, box, cpu, extra_guards, renum):
+        if self.generalization_of(other, renum):
             return
+        if renum[self.position] != other.position:
+            raise InvalidLoop
         self._generate_guards(other, box, cpu, extra_guards)
 
     def _generate_guards(self, other, box, cpu, extra_guards):
@@ -42,10 +44,11 @@
     def __init__(self, fielddescrs):
         self.fielddescrs = fielddescrs
 
-    def generalization_of(self, other):
+    def generalization_of(self, other, renum):
         assert self.position != -1
-        if self.position != other.position:
-            return False
+        if self.position in renum:
+            return renum[self.position] == other.position
+        renum[self.position] = other.position
         if not self._generalization_of(other):
             return False
         assert len(self.fielddescrs) == len(self.fieldstate)
@@ -56,7 +59,7 @@
         for i in range(len(self.fielddescrs)):
             if other.fielddescrs[i] is not self.fielddescrs[i]:
                 return False
-            if not self.fieldstate[i].generalization_of(other.fieldstate[i]):
+            if not self.fieldstate[i].generalization_of(other.fieldstate[i], 
renum):
                 return False
 
         return True
@@ -82,7 +85,7 @@
         AbstractVirtualStructStateInfo.__init__(self, fielddescrs)
         self.known_class = known_class
 
-    def _generalization_of(self, other):        
+    def _generalization_of(self, other):
         if not isinstance(other, VirtualStateInfo):
             return False
         if not self.known_class.same_constant(other.known_class):
@@ -105,16 +108,17 @@
     def __init__(self, arraydescr):
         self.arraydescr = arraydescr
 
-    def generalization_of(self, other):
+    def generalization_of(self, other, renum):
         assert self.position != -1
-        if self.position != other.position:
-            return False
+        if self.position in renum:
+            return renum[self.position] == other.position
+        renum[self.position] = other.position
         if self.arraydescr is not other.arraydescr:
             return False
         if len(self.fieldstate) != len(other.fieldstate):
             return False
         for i in range(len(self.fieldstate)):
-            if not self.fieldstate[i].generalization_of(other.fieldstate[i]):
+            if not self.fieldstate[i].generalization_of(other.fieldstate[i], 
renum):
                 return False
         return True
 
@@ -145,12 +149,13 @@
             self.constbox = None
         self.position_in_notvirtuals = -1
 
-    def generalization_of(self, other):
+    def generalization_of(self, other, renum):
         # XXX This will always retrace instead of forcing anything which
         # might be what we want sometimes?
         assert self.position != -1
-        if self.position != other.position:
-            return False
+        if self.position in renum:
+            return renum[self.position] == other.position
+        renum[self.position] = other.position
         if not isinstance(other, NotVirtualStateInfo):
             return False
         if other.level < self.level:
@@ -241,16 +246,18 @@
 
     def generalization_of(self, other):
         assert len(self.state) == len(other.state)
+        renum = {}
         for i in range(len(self.state)):
-            if not self.state[i].generalization_of(other.state[i]):
+            if not self.state[i].generalization_of(other.state[i], renum):
                 return False
         return True
 
     def generate_guards(self, other, args, cpu, extra_guards):        
         assert len(self.state) == len(other.state) == len(args)
+        renum = {}
         for i in range(len(self.state)):
             self.state[i].generate_guards(other.state[i], args[i],
-                                          cpu, extra_guards)
+                                          cpu, extra_guards, renum)
 
     def make_inputargs(self, values, keyboxes=False):
         assert len(values) == len(self.state)
diff --git a/pypy/jit/metainterp/test/test_ajit.py 
b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -2387,6 +2387,28 @@
             return sa
         assert self.meta_interp(f, [20, 1, 2]) == f(20, 1, 2)
 
+    def test_args_becomming_not_equal_boxed1(self):
+        class A(object):
+            def __init__(self, a, b):
+                self.a = a
+                self.b = b
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a', 'b', 
'node'])
+
+        def f(n, a, b):
+            sa = i = 0
+            node = A(b, b)
+            while i < n:
+                myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a, b=b, 
node=node)
+                sa += node.a
+                sa *= node.b
+                if i > n/2:
+                    node = A(a, b)
+                else:
+                    node = A(b, b)
+                i += 1
+            return sa
+        assert self.meta_interp(f, [20, 1, 2]) == f(20, 1, 2)
+
     def test_args_becomming_equal_boxed2(self):
         class A(object):
             def __init__(self, a, b):
diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py 
b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -1292,38 +1292,6 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_virtual_field_forced_by_later_jumpargs(self):
-        # FIXME: Can that occure? How to test?!?
-        ops = """
-        [i0, p1, p3, p3next]
-        i28 = int_add(i0, 1)
-        p30 = new_with_vtable(ConstClass(node_vtable))
-        setfield_gc(p30, i28, descr=nextdescr)
-        i29 = int_add(i28, 1)
-        p3v = new_with_vtable(ConstClass(node_vtable))        
-        setfield_gc(p3v, p30, descr=valuedescr)
-        p45 = getfield_gc(p3next, descr=valuedescr)
-        jump(i29, p45, p3next, p3v)
-        """
-        preamble = """
-        [i0, p1, p3, p3next]
-        i28 = int_add(i0, 1)
-        i29 = int_add(i28, 1)
-        p45 = getfield_gc(p3next, descr=valuedescr)        
-        jump(i29, p45, p3next, i28)
-        """
-        expected = """
-        [i0, p1, p3, i1]
-        i28 = int_add(i0, 1)
-        i29 = int_add(i28, 1)
-        p3v = new_with_vtable(ConstClass(node_vtable))
-        p30 = new_with_vtable(ConstClass(node_vtable))
-        setfield_gc(p30, i1, descr=nextdescr)
-        setfield_gc(p3v, p30, descr=valuedescr)        
-        jump(i29, i28, p3v)
-        """
-        self.optimize_loop(ops, expected, preamble)
-
     def test_virtual_field_forced_by_lazy_setfield(self):
         ops = """
         [i0, p1, p3]
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to