[pypy-svn] r21037 - in pypy/dist/pypy/jit: . test

arigo at codespeak.net arigo at codespeak.net
Sun Dec 11 13:27:05 CET 2005


Author: arigo
Date: Sun Dec 11 13:27:03 2005
New Revision: 21037

Modified:
   pypy/dist/pypy/jit/llabstractinterp.py
   pypy/dist/pypy/jit/test/test_llabstractinterp.py
Log:
* Bug fix & test: forgot to create the exitcase and llexitcase on the new
  links!

* Added caching of specializations for the tests, similar to test_llinterp.


Modified: pypy/dist/pypy/jit/llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp.py	Sun Dec 11 13:27:03 2005
@@ -52,7 +52,7 @@
     def with_fresh_variables(self, memo):
         return self
 
-    def match(self, other):
+    def match(self, other, memo):
         return isinstance(other, LLConcreteValue) and self.value == other.value
 
 
@@ -92,7 +92,7 @@
     def with_fresh_variables(self, memo):
         return LLRuntimeValue(self.getconcretetype())
 
-    def match(self, other):
+    def match(self, other, memo):
         # Note: the meaning of match() is actually to see if calling
         # with_fresh_variables() on both 'self' and 'other' would give the
         # same result.  This is why any two LLRuntimeValues match each other.
@@ -222,14 +222,18 @@
                 result.extend(self.getfield(name).getruntimevars(memo))
         return result
 
-    def match(self, other):
-        if self is other:
-            return True
+    def match(self, other, memo):
+        if (False, self) in memo:
+            return other is memo[False, self]
+        if (True, other) in memo:
+            return self is memo[True, other]
+        memo[False, self] = other
+        memo[True, other] = self
         assert self.T == other.T
         for name in self.T._names:
             a1 = self.getfield(name)
             a2 = other.getfield(name)
-            if not a1.match(a2):
+            if not a1.match(a2, memo):
                 return False
         else:
             return True
@@ -258,9 +262,9 @@
     def with_fresh_variables(self, memo):
         return LLVirtualPtr(self.containerobj.copy(memo))
 
-    def match(self, other):
+    def match(self, other, memo):
         if isinstance(other, LLVirtualPtr):
-            return self.containerobj.match(other.containerobj)
+            return self.containerobj.match(other.containerobj, memo)
         else:
             return False
 
@@ -278,8 +282,9 @@
 
     def match(self, args_a):
         # simple for now
+        memo = {}
         for a1, a2 in zip(self.args_a, args_a):
-            if not a1.match(a2):
+            if not a1.match(a2, memo):
                 return False
         else:
             return True
@@ -468,6 +473,9 @@
             for origlink in links:
                 args_a = [builder.binding(v) for v in origlink.args]
                 newlink = self.interp.schedule(args_a, origlink.target)
+                if newexitswitch is not None:
+                    newlink.exitcase = origlink.exitcase
+                    newlink.llexitcase = origlink.llexitcase
                 newlinks.append(newlink)
         else:
             # copies of return and except blocks are *normal* blocks currently;

Modified: pypy/dist/pypy/jit/test/test_llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/test/test_llabstractinterp.py	(original)
+++ pypy/dist/pypy/jit/test/test_llabstractinterp.py	Sun Dec 11 13:27:03 2005
@@ -15,23 +15,38 @@
         t = annmodel.lltype_to_annotation(T)
     return a.typeannotation(t)
 
-def abstrinterp(ll_function, argvalues, arghints):
+_lastinterpreted = []
+def get_and_residualize_graph(ll_function, argvalues, arghints):
+    key = ll_function, tuple(arghints), tuple([argvalues[n] for n in arghints])
+    for key1, value1 in _lastinterpreted:    # 'key' is not hashable
+        if key1 == key:
+            return value1
+    if len(_lastinterpreted) >= 3:
+        del _lastinterpreted[0]
+    # build the normal ll graphs for ll_function
     t = TranslationContext()
     a = t.buildannotator()
     argtypes = [annotation(a, value) for value in argvalues]
     graph1 = annotate_lowlevel_helper(a, ll_function, argtypes)
     rtyper = t.buildrtyper()
     rtyper.specialize()
+    # build the residual ll graphs by propagating the hints
     interp = LLAbstractInterp()
     hints = {}
-    argvalues2 = argvalues[:]
-    lst = list(arghints)
-    lst.sort()
-    lst.reverse()
-    for hint in lst:
-        hints[graph1.getargs()[hint]] = argvalues2[hint]
-        del argvalues2[hint]
+    for hint in arghints:
+        hints[graph1.getargs()[hint]] = argvalues[hint]
     graph2 = interp.eval(graph1, hints)
+    # cache and return the original and the residual ll graph
+    result = t, interp, graph1, graph2
+    _lastinterpreted.append((key, result))
+    return result
+
+def abstrinterp(ll_function, argvalues, arghints):
+    t, interp, graph1, graph2 = get_and_residualize_graph(
+        ll_function, argvalues, arghints)
+    argvalues2 = [argvalues[n] for n in range(len(argvalues))
+                               if n not in arghints]
+    rtyper = t.rtyper
     # check the result by running it
     llinterp = LLInterpreter(rtyper)
     result1 = llinterp.eval_graph(graph1, argvalues)
@@ -95,6 +110,8 @@
         return y
     graph2, insns = abstrinterp(ll_function, [6, 42], [])
     assert insns == {'int_is_true': 1, 'int_add': 2}
+    graph2, insns = abstrinterp(ll_function, [0, 42], [])
+    assert insns == {'int_is_true': 1, 'int_add': 2}
 
 def test_unrolling_loop():
     def ll_function(x, y):



More information about the Pypy-commit mailing list