[pypy-svn] r34843 - in pypy/dist/pypy/jit: codegen/i386/test timeshifter timeshifter/test

arigo at codespeak.net arigo at codespeak.net
Tue Nov 21 23:09:50 CET 2006


Author: arigo
Date: Tue Nov 21 23:09:47 2006
New Revision: 34843

Modified:
   pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py
   pypy/dist/pypy/jit/timeshifter/rcontainer.py
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
   pypy/dist/pypy/jit/timeshifter/rvalue.py
   pypy/dist/pypy/jit/timeshifter/test/test_promotion.py
   pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/dist/pypy/jit/timeshifter/vdict.py
   pypy/dist/pypy/jit/timeshifter/vlist.py
Log:
(pedronis, arre, arigo)

Make PartialDataStruct survive across merges, at least as long as their
information doesn't conflict with another merged path's information.

(Missing: make recursive PartialDataStructs survive too)


Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_ts.py	Tue Nov 21 23:09:47 2006
@@ -140,6 +140,9 @@
     def check_insns(self, expected=None, **counts):
         "Cannot check instructions in the generated assembler."
 
+    def check_flexswitches(self, expected_count):
+        "Cannot check instructions in the generated assembler."
+
 class TestTimeshiftI386(I386TimeshiftingTestMixin,
                         test_timeshift.TestTimeshift):
 

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Tue Nov 21 23:09:47 2006
@@ -19,6 +19,15 @@
     def op_getsubstruct(self, jitstate, fielddesc):
         raise NotImplementedError
 
+
+class VirtualContainer(AbstractContainer):
+    __slots__ = []
+
+
+class FrozenContainer(AbstractContainer):
+    __slots__ = []
+
+
 # ____________________________________________________________
 
 class StructTypeDesc(object):
@@ -158,7 +167,7 @@
 
 # ____________________________________________________________
 
-class FrozenVirtualStruct(AbstractContainer):
+class FrozenVirtualStruct(FrozenContainer):
 
     def __init__(self, typedesc):
         self.typedesc = typedesc
@@ -199,6 +208,7 @@
         ownbox = typedesc.factory()
         contmemo[self] = ownbox
         vstruct = ownbox.content
+        assert isinstance(vstruct, VirtualStruct)
         self_boxes = self.fz_content_boxes
         for i in range(len(self_boxes)):
             fz_box = self_boxes[i]
@@ -207,11 +217,7 @@
         return ownbox
 
 
-class AbstractStruct(AbstractContainer):
-    pass
-
-
-class VirtualStruct(AbstractStruct):
+class VirtualStruct(VirtualContainer):
 
     def __init__(self, typedesc):
         self.typedesc = typedesc
@@ -284,8 +290,46 @@
     def op_getsubstruct(self, jitstate, fielddesc):
         return self.ownbox
 
+# ____________________________________________________________
 
-class PartialDataStruct(AbstractStruct):
+class FrozenPartialDataStruct(AbstractContainer):
+
+    def __init__(self):
+        self.fz_data = []
+
+    def getfzbox(self, searchindex):
+        for index, fzbox in self.fz_data:
+            if index == searchindex:
+                return fzbox
+        else:
+            return None
+
+    def match(self, box, partialdatamatch):
+        content = box.content
+        if not isinstance(content, PartialDataStruct):
+            return False
+
+        cankeep = {}
+        for index, subbox in content.data:
+            selfbox = self.getfzbox(index)
+            if selfbox is not None and selfbox.is_constant_equal(subbox):
+                cankeep[index] = None
+        fullmatch = len(cankeep) == len(self.fz_data)
+        try:
+            prevkeep = partialdatamatch[box]
+        except KeyError:
+            partialdatamatch[box] = cankeep
+        else:
+            if prevkeep is not None:
+                d = {}
+                for index in prevkeep:
+                    if index in cankeep:
+                        d[index] = None
+                partialdatamatch[box] = d
+        return fullmatch
+
+
+class PartialDataStruct(AbstractContainer):
 
     def __init__(self):
         self.data = []
@@ -307,6 +351,19 @@
         else:
             self.data.append((searchindex, box))
 
+    def partialfreeze(self, memo):
+        contmemo = memo.containers
+        assert self not in contmemo     # contmemo no longer used
+        result = contmemo[self] = FrozenPartialDataStruct()
+        for index, box in self.data:
+            if box.is_constant():
+                frozenbox = box.freeze(memo)
+                result.fz_data.append((index, frozenbox))
+        if len(result.fz_data) == 0:
+            return None
+        else:
+            return result
+
     def copy(self, memo):
         result = PartialDataStruct()
         for index, box in self.data:
@@ -325,3 +382,18 @@
             contmemo[self] = None
             for index, box in self.data:
                 box.enter_block(incoming, memo)
+
+    def cleanup_partial_data(self, keep):
+        if keep is None:
+            return None
+        j = 0
+        data = self.data
+        for i in range(len(data)):
+            item = data[i]
+            if item[0] in keep:
+                data[j] = item
+                j += 1
+        if j == 0:
+            return None
+        del data[j:]
+        return self

Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Tue Nov 21 23:09:47 2006
@@ -2,7 +2,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem import lltype, lloperation, llmemory
 from pypy.jit.hintannotator.model import originalconcretetype
-from pypy.jit.timeshifter import rvalue
+from pypy.jit.timeshifter import rvalue, rcontainer
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rpython.annlowlevel import cachedtype, base_ptr_lltype
 from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
@@ -219,6 +219,7 @@
     outgoingvarboxes = []
     res = frozen.exactmatch(jitstate, outgoingvarboxes, memo)
     assert res, "exactmatch() failed"
+    cleanup_partial_data(memo.partialdatamatch)
     newblock = enter_next_block(jitstate, outgoingvarboxes)
     states_dic[key] = frozen, newblock
     if global_resumer is not None and global_resumer is not return_marker:
@@ -251,6 +252,7 @@
     # We need a more general block.  Do it by generalizing all the
     # redboxes from outgoingvarboxes, by making them variables.
     # Then we make a new block based on this new state.
+    cleanup_partial_data(memo.partialdatamatch)
     replace_memo = rvalue.copy_memo()
     for box in outgoingvarboxes:
         box.forcevar(jitstate.curbuilder, replace_memo)
@@ -262,6 +264,14 @@
     return False       # continue
 retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)"
 
+def cleanup_partial_data(partialdatamatch):
+    # remove entries from PartialDataStruct unless they matched
+    # their frozen equivalent
+    for box, keep in partialdatamatch.iteritems():
+        content = box.content
+        if isinstance(content, rcontainer.PartialDataStruct):
+            box.content = content.cleanup_partial_data(keep)
+
 def merge_generalized(jitstate):
     resuming = jitstate.resuming
     if resuming is None:

Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py	Tue Nov 21 23:09:47 2006
@@ -14,7 +14,9 @@
     return Memo()
 
 def exactmatch_memo():
-    return Memo()
+    memo = Memo()
+    memo.partialdatamatch = {}
+    return memo
 
 def copy_memo():
     return Memo()
@@ -242,29 +244,35 @@
         try:
             return boxmemo[self]
         except KeyError:
+            content = self.content
             if not self.genvar:
-                assert self.content is not None
+                from pypy.jit.timeshifter import rcontainer
+                assert isinstance(content, rcontainer.VirtualContainer)
                 result = FrozenPtrVirtual(self.kind)
                 boxmemo[self] = result
-                result.fz_content = self.content.freeze(memo)
+                result.fz_content = content.freeze(memo)
+                return result
+            elif self.genvar.is_const:
+                result = FrozenPtrConst(self.kind, self.genvar)
+            elif content is None:
+                result = FrozenPtrVar(self.kind)
             else:
-                if self.is_constant():
-                    result = FrozenPtrConst(self.kind, self.genvar)
-                else:
-                    result = FrozenPtrVar(self.kind)
-                    # if self.content is not None, it's a PartialDataStruct
-                    # - for now, we always remove it while freezing so that
-                    #   we exactly match our frozen version
-                    # XXX unsure if it's the correct place to do that.
-                    # XXX maybe in exactmatch??
-                    self.content = None
+                # if self.content is not None, it's a PartialDataStruct
+                from pypy.jit.timeshifter import rcontainer
+                assert isinstance(content, rcontainer.PartialDataStruct)
+                result = FrozenPtrVarWithPartialData(self.kind)
                 boxmemo[self] = result
+                result.fz_partialcontent = content.partialfreeze(memo)
+                return result
+            boxmemo[self] = result
             return result
 
     def getgenvar(self, builder):
         if not self.genvar:
-            assert self.content
-            self.content.force_runtime_container(builder)
+            content = self.content
+            from pypy.jit.timeshifter import rcontainer
+            assert isinstance(content, rcontainer.VirtualContainer)
+            content.force_runtime_container(builder)
             assert self.genvar
         return self.genvar
 
@@ -288,28 +296,21 @@
     def __init__(self, kind):
         self.kind = kind
 
+    def is_constant_equal(self, box):
+        return False
 
-class FrozenIntConst(FrozenValue):
 
-    def __init__(self, kind, gv_const):
-        self.kind = kind
-        self.gv_const = gv_const
+class FrozenConst(FrozenValue):
 
     def exactmatch(self, box, outgoingvarboxes, memo):
-        if (box.is_constant() and
-            self.gv_const.revealconst(lltype.Signed) ==
-               box.genvar.revealconst(lltype.Signed)):
+        if self.is_constant_equal(box):
             return True
         else:
             outgoingvarboxes.append(box)
             return False
 
-    def unfreeze(self, incomingvarboxes, memo):
-        # XXX could return directly the original IntRedBox
-        return IntRedBox(self.kind, self.gv_const)
-
 
-class FrozenIntVar(FrozenValue):
+class FrozenVar(FrozenValue):
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         memo = memo.boxes
@@ -323,6 +324,25 @@
             outgoingvarboxes.append(box)
             return False
 
+
+class FrozenIntConst(FrozenConst):
+
+    def __init__(self, kind, gv_const):
+        self.kind = kind
+        self.gv_const = gv_const
+
+    def is_constant_equal(self, box):
+        return (box.is_constant() and
+                self.gv_const.revealconst(lltype.Signed) ==
+                box.genvar.revealconst(lltype.Signed))
+
+    def unfreeze(self, incomingvarboxes, memo):
+        # XXX could return directly the original IntRedBox
+        return IntRedBox(self.kind, self.gv_const)
+
+
+class FrozenIntVar(FrozenVar):
+
     def unfreeze(self, incomingvarboxes, memo):
         memo = memo.boxes
         if self not in memo:
@@ -334,38 +354,22 @@
             return memo[self]
 
 
-class FrozenDoubleConst(FrozenValue):
+class FrozenDoubleConst(FrozenConst):
 
     def __init__(self, kind, gv_const):
         self.kind = kind
         self.gv_const = gv_const
 
-    def exactmatch(self, box, outgoingvarboxes, memo):
-        if (box.is_constant() and
-            self.gv_const.revealconst(lltype.Float) ==
-               box.genvar.revealconst(lltype.Float)):
-            return True
-        else:
-            outgoingvarboxes.append(box)
-            return False
+    def is_constant_equal(self, box):
+        return (box.is_constant() and
+                self.gv_const.revealconst(lltype.Float) ==
+                box.genvar.revealconst(lltype.Float))
 
     def unfreeze(self, incomingvarboxes, memo):
         return DoubleRedBox(self.kind, self.gv_const)
 
 
-class FrozenDoubleVar(FrozenValue):
-
-    def exactmatch(self, box, outgoingvarboxes, memo):
-        memo = memo.boxes
-        if self not in memo:
-            memo[self] = box
-            outgoingvarboxes.append(box)
-            return True
-        elif memo[self] is box:
-            return True
-        else:
-            outgoingvarboxes.append(box)
-            return False
+class FrozenDoubleVar(FrozenVar):
 
     def unfreeze(self, incomingvarboxes, memo):
         memo = memo.boxes
@@ -378,38 +382,32 @@
             return memo[self]
 
 
-class FrozenPtrConst(FrozenValue):
+class FrozenPtrConst(FrozenConst):
 
     def __init__(self, kind, gv_const):
         self.kind = kind
         self.gv_const = gv_const
 
+    def is_constant_equal(self, box):
+        return (box.is_constant() and
+                self.gv_const.revealconst(llmemory.Address) ==
+                box.genvar.revealconst(llmemory.Address))
+
     def exactmatch(self, box, outgoingvarboxes, memo):
-        if (box.is_constant() and
-            self.gv_const.revealconst(llmemory.Address) ==
-               box.genvar.revealconst(llmemory.Address)):
-            return True
-        else:
-            outgoingvarboxes.append(box)
-            return False
+        assert isinstance(box, PtrRedBox)
+        memo.partialdatamatch[box] = None     # could do better
+        return FrozenConst.exactmatch(self, box, outgoingvarboxes, memo)
 
     def unfreeze(self, incomingvarboxes, memo):
         return PtrRedBox(self.kind, self.gv_const)
 
 
-class FrozenPtrVar(FrozenValue):
+class FrozenPtrVar(FrozenVar):
 
     def exactmatch(self, box, outgoingvarboxes, memo):
-        memo = memo.boxes
-        if self not in memo:
-            memo[self] = box
-            outgoingvarboxes.append(box)
-            return True
-        elif memo[self] is box:
-            return True
-        else:
-            outgoingvarboxes.append(box)
-            return False
+        assert isinstance(box, PtrRedBox)
+        memo.partialdatamatch[box] = None
+        return FrozenVar.exactmatch(self, box, outgoingvarboxes, memo)
 
     def unfreeze(self, incomingvarboxes, memo):
         memo = memo.boxes
@@ -422,6 +420,19 @@
             return memo[self]
 
 
+class FrozenPtrVarWithPartialData(FrozenPtrVar):
+
+    def exactmatch(self, box, outgoingvarboxes, memo):
+        if self.fz_partialcontent is None:
+            return FrozenPtrVar.exactmatch(self, box, outgoingvarboxes, memo)
+        assert isinstance(box, PtrRedBox)
+        partialdatamatch = self.fz_partialcontent.match(box,
+                                                        memo.partialdatamatch)
+        # skip the parent's exactmatch()!
+        exact = FrozenVar.exactmatch(self, box, outgoingvarboxes, memo)
+        return exact and partialdatamatch
+
+
 class FrozenPtrVirtual(FrozenValue):
 
     def exactmatch(self, box, outgoingvarboxes, memo):

Modified: pypy/dist/pypy/jit/timeshifter/test/test_promotion.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_promotion.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_promotion.py	Tue Nov 21 23:09:47 2006
@@ -263,3 +263,28 @@
 
         res = self.timeshift(ll_function, [5, 100], [0], policy=P_NOVIRTUAL)
         assert res == 115
+
+    def test_remembers_across_mp(self):
+        def ll_function(x, flag):
+            hint(None, global_merge_point=True)
+            hint(x.field, promote=True)
+            m = x.field
+            if flag:
+                m += 1 * flag
+            else:
+                m += 2 + flag
+            hint(x.field, promote=True)
+            return m + x.field
+
+        S = lltype.GcStruct('S', ('field', lltype.Signed),
+                            hints={'immutable': True})
+
+        def struct_S(string):
+            s = lltype.malloc(S)
+            s.field = int(string)
+            return s
+        ll_function.convert_arguments = [struct_S, int]
+
+        res = self.timeshift(ll_function, ["20", 0], [], policy=P_NOVIRTUAL)
+        assert res == 42
+        self.check_flexswitches(1)

Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	Tue Nov 21 23:09:47 2006
@@ -5,7 +5,7 @@
 from pypy.jit.hintannotator.model import *
 from pypy.jit.timeshifter.hrtyper import HintRTyper, originalconcretetype
 from pypy.jit.timeshifter import rtimeshift, rvalue
-from pypy.objspace.flow.model import summary
+from pypy.objspace.flow.model import summary, Variable
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr
 from pypy.rlib.objectmodel import hint, keepalive_until_here
 from pypy.rlib.unroll import unrolling_iterable
@@ -320,6 +320,14 @@
         for opname, count in counts.items():
             assert self.insns.get(opname, 0) == count
 
+    def check_flexswitches(self, expected_count):
+        count = 0
+        for block in self.residual_graph.iterblocks():
+            if (isinstance(block.exitswitch, Variable) and
+                block.exitswitch.concretetype is lltype.Signed):
+                count += 1
+        assert count == expected_count
+
 
 class TestTimeshift(TimeshiftingTests):
 

Modified: pypy/dist/pypy/jit/timeshifter/vdict.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vdict.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/vdict.py	Tue Nov 21 23:09:47 2006
@@ -1,12 +1,16 @@
 import operator
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem import rdict
-from pypy.jit.timeshifter.rcontainer import AbstractContainer, cachedtype
+from pypy.jit.timeshifter.rcontainer import VirtualContainer, FrozenContainer
+from pypy.jit.timeshifter.rcontainer import cachedtype
 from pypy.jit.timeshifter import rvalue
 from pypy.rlib.objectmodel import r_dict
 
 HASH = lltype.Signed
 
+# XXXXXXXXXX! ARGH.
+# cannot use a dictionary as the item_boxes at all, because of order issues
+
 
 class LLEqDesc(object):
     __metaclass__ = cachedtype
@@ -48,7 +52,7 @@
                 for key, valuebox in other.item_boxes.iteritems():
                     self.item_boxes[key] = valuebox.copy(memo)
 
-            def replace(self, memo):
+            def internal_replace(self, memo):
                 changes = []
                 for key, valuebox in self.item_boxes.iteritems():
                     newbox = valuebox.replace(memo)
@@ -137,7 +141,7 @@
 TypeDesc = DictTypeDesc
 
 
-class AbstractFrozenVirtualDict(AbstractContainer):
+class AbstractFrozenVirtualDict(FrozenContainer):
     __slots__ = ('typedesc',)
 
     def __init__(self, typedesc):
@@ -171,10 +175,18 @@
                 fullmatch = False
         return fullmatch
 
+    def freeze_from(self, vdict, memo):
+        raise NotImplementedError
+
+    def same_keys_as(self, vdict, boxes):
+        raise NotImplementedError
+
 
-class AbstractVirtualDict(AbstractContainer):
+class AbstractVirtualDict(VirtualContainer):
     __slots__ = ('typedesc', 'ownbox')     # and no item_boxes
 
+    FrozenVirtualDict = AbstractFrozenVirtualDict    # overridden in subclasses
+
     def __init__(self, typedesc):
         self.typedesc = typedesc
         self.make_item_boxes()
@@ -228,9 +240,30 @@
         contmemo = memo.containers
         if self not in contmemo:
             contmemo[self] = None
-            self.replace(memo)
+            self.internal_replace(memo)
             self.ownbox = self.ownbox.replace(memo)
 
+    def make_item_boxes(self):
+        raise NotImplementedError
+
+    def getboxes(self):
+        raise NotImplementedError
+
+    def getitems_and_makeempty(self, rgenop):
+        raise NotImplementedError
+
+    def getitem(self, keybox):
+        raise NotImplementedError
+
+    def setitem(self, keybox, valuebox):
+        raise NotImplementedError
+
+    def copy_from(self, other, memo):
+        raise NotImplementedError
+
+    def internal_replace(self, memo):
+        raise NotImplementedError
+
 
 def oop_newdict(jitstate, oopspecdesc):
     return oopspecdesc.typedesc.factory()

Modified: pypy/dist/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vlist.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/vlist.py	Tue Nov 21 23:09:47 2006
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem import lltype
-from pypy.jit.timeshifter.rcontainer import AbstractContainer, cachedtype
+from pypy.jit.timeshifter.rcontainer import VirtualContainer, FrozenContainer
+from pypy.jit.timeshifter.rcontainer import cachedtype
 from pypy.jit.timeshifter import rvalue
 
 
@@ -39,7 +40,7 @@
 TypeDesc = ListTypeDesc
 
 
-class FrozenVirtualList(AbstractContainer):
+class FrozenVirtualList(FrozenContainer):
 
     def __init__(self, typedesc):
         self.typedesc = typedesc
@@ -74,7 +75,7 @@
         return fullmatch
 
 
-class VirtualList(AbstractContainer):
+class VirtualList(VirtualContainer):
 
     def __init__(self, typedesc, length=0, itembox=None):
         self.typedesc = typedesc



More information about the Pypy-commit mailing list