[pypy-svn] r33072 - in pypy/dist/pypy/jit: codegen/llgraph timeshifter timeshifter/test

arigo at codespeak.net arigo at codespeak.net
Mon Oct 9 20:45:42 CEST 2006


Author: arigo
Date: Mon Oct  9 20:45:39 2006
New Revision: 33072

Modified:
   pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
   pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
   pypy/dist/pypy/jit/timeshifter/rcontainer.py
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
   pypy/dist/pypy/jit/timeshifter/rtyper.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
Log:
(pedronis, arigo)

Promotion of the __class__ of an instance works.  This contains a bit of
pushing and pulling (but also some clean-ups, cheer :-).  Some more work
needed.



Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py	(original)
+++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py	Mon Oct  9 20:45:39 2006
@@ -7,6 +7,7 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, rtupletype
 from pypy.objspace.flow import model as flowmodel
 from pypy.translator.simplify import eliminate_empty_blocks, join_blocks
+from pypy.translator.unsimplify import varoftype
 from pypy.rpython.module.support import init_opaque_object
 from pypy.rpython.module.support import to_opaque_object, from_opaque_object
 from pypy.rpython.module.support import LLSupport
@@ -251,6 +252,13 @@
     block.blockcolor = getcolor()
     exitswitch = from_opaque_object(exitswitch)
     assert isinstance(exitswitch, flowmodel.Variable)
+    TYPE = exitswitch.concretetype
+    if isinstance(TYPE, lltype.Ptr):
+        # XXX hack!
+        v1 = varoftype(lltype.Signed)
+        block.operations.append(flowmodel.SpaceOperation(
+            'cast_ptr_to_int', [exitswitch], v1))
+        exitswitch = v1
     block.exitswitch = exitswitch
     default_link = flowmodel.Link([], None)
     default_link.exitcase = "default"
@@ -264,8 +272,12 @@
     assert isinstance(exitcase, flowmodel.Constant)
     assert isinstance(block.exitswitch, flowmodel.Variable)
     case_link = flowmodel.Link([], None)
-    case_link.exitcase = exitcase.value
-    case_link.llexitcase = exitcase.value
+    exitvalue = exitcase.value
+    if isinstance(lltype.typeOf(exitvalue), lltype.Ptr):
+        # XXX hack!
+        exitvalue = lltype.cast_ptr_to_int(exitvalue)
+    case_link.exitcase = exitvalue
+    case_link.llexitcase = exitvalue
     exits = block.exits[:-1] + (case_link,) + block.exits[-1:]
     block.recloseblock(*exits)
     return to_opaque_object(case_link)

Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py	Mon Oct  9 20:45:39 2006
@@ -39,8 +39,10 @@
     def __init__(self, b, g):
         self.b = b
         self.g = g
+        self.cases_gv = []
 
     def add_case(self, gv_case):
+        self.cases_gv.append(gv_case)  # not used so far, but keeps ptrs alive
         l_case = llimpl.add_case(self.b, gv_case.v)
         builder = LLBuilder(self.g)
         builder.lnk = l_case

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Mon Oct  9 20:45:39 2006
@@ -60,6 +60,8 @@
 
     def factory(self):
         vstruct = VirtualStruct(self)
+        vstruct.content_boxes = [desc.redboxcls(desc.kind, desc.gv_default)
+                                 for desc in self.fielddescs]
         box = rvalue.PtrRedBox(self.innermostdesc.ptrkind)
         box.content = vstruct
         vstruct.ownbox = box
@@ -179,15 +181,17 @@
             vstruct.content_boxes[i] = fz_box.unfreeze(incomingvarboxes,
                                                        memo)
         return ownbox
-        
 
-class VirtualStruct(AbstractContainer):
+
+class AbstractStruct(AbstractContainer):
+    pass
+
+
+class VirtualStruct(AbstractStruct):
 
     def __init__(self, typedesc):
         self.typedesc = typedesc
-        self.content_boxes = [desc.redboxcls(desc.kind,
-                                             desc.gv_default)
-                              for desc in typedesc.fielddescs]
+        #self.content_boxes = ... set in factory()
         #self.ownbox = ... set in factory()
 
     def enter_block(self, incoming, memo):
@@ -213,33 +217,29 @@
 
     def freeze(self, memo):
         contmemo = memo.containers
-        try:
-            return contmemo[self]
-        except KeyError:
-            result = contmemo[self] = FrozenVirtualStruct(self.typedesc)
-            frozens = [box.freeze(memo) for box in self.content_boxes]
-            result.fz_content_boxes = frozens
-            return result
+        assert self not in contmemo     # contmemo no longer used
+        result = contmemo[self] = FrozenVirtualStruct(self.typedesc)
+        frozens = [box.freeze(memo) for box in self.content_boxes]
+        result.fz_content_boxes = frozens
+        return result
         
     def copy(self, memo):
         contmemo = memo.containers
-        try:
-            return contmemo[self]
-        except KeyError:
-            result = contmemo[self] = VirtualStruct(self.typedesc)
-            result.content_boxes = [box.copy(memo)
-                                    for box in self.content_boxes]
-            result.ownbox = self.ownbox.copy(memo)
-            return result
+        assert self not in contmemo     # contmemo no longer used
+        result = contmemo[self] = VirtualStruct(self.typedesc)
+        result.content_boxes = [box.copy(memo)
+                                for box in self.content_boxes]
+        result.ownbox = self.ownbox.copy(memo)
+        return result
 
     def replace(self, memo):
         contmemo = memo.containers
-        if self not in contmemo:
-            contmemo[self] = None
-            content_boxes = self.content_boxes
-            for i in range(len(content_boxes)):
-                content_boxes[i] = content_boxes[i].replace(memo)
-            self.ownbox = self.ownbox.replace(memo)
+        assert self not in contmemo     # contmemo no longer used
+        contmemo[self] = None
+        content_boxes = self.content_boxes
+        for i in range(len(content_boxes)):
+            content_boxes[i] = content_boxes[i].replace(memo)
+        self.ownbox = self.ownbox.replace(memo)
 
     def op_getfield(self, jitstate, fielddesc):
         return self.content_boxes[fielddesc.fieldindex]
@@ -249,3 +249,45 @@
 
     def op_getsubstruct(self, jitstate, fielddesc):
         return self.ownbox
+
+
+class PartialDataStruct(AbstractStruct):
+
+    def __init__(self):
+        self.data = []
+
+    def op_getfield(self, jitstate, fielddesc):
+        searchindex = fielddesc.fieldindex
+        for index, box in self.data:
+            if index == searchindex:
+                return box
+        else:
+            return None
+
+    def remember_field(self, fielddesc, box):
+        searchindex = fielddesc.fieldindex
+        for i in range(len(self.data)):
+            if self.data[i][0] == searchindex:
+                self.data[i] = searchindex, box
+                return
+        else:
+            self.data.append((searchindex, box))
+
+    def copy(self, memo):
+        result = PartialDataStruct()
+        for index, box in self.data:
+            result.data.append((index, box.copy(memo)))
+        return result
+
+    def replace(self, memo):
+        for i in range(len(self.data)):
+            index, box = self.data[i]
+            box = box.replace(memo)
+            self.data[i] = index, box
+
+    def enter_block(self, incoming, memo):
+        contmemo = memo.containers
+        if self not in contmemo:
+            contmemo[self] = None
+            for index, box in self.data:
+                box.enter_block(incoming, memo)

Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Mon Oct  9 20:45:39 2006
@@ -101,33 +101,17 @@
         res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE),
                       fielddesc.fieldname)
         return rvalue.ll_fromvalue(jitstate, res)
-    assert isinstance(argbox, rvalue.PtrRedBox)
-    if argbox.content is None:
-        gv_ptr = argbox.getgenvar(jitstate.curbuilder)
-        return fielddesc.generate_get(jitstate.curbuilder, gv_ptr)
-    else:
-        return argbox.content.op_getfield(jitstate, fielddesc)
+    return argbox.op_getfield(jitstate, fielddesc)
 
 def ll_gensetfield(jitstate, fielddesc, destbox, valuebox):
-    assert isinstance(destbox, rvalue.PtrRedBox)
-    if destbox.content is None:
-        gv_ptr = destbox.getgenvar(jitstate.curbuilder)
-        fielddesc.generate_set(jitstate.curbuilder, gv_ptr, valuebox)
-    else:
-        destbox.content.op_setfield(jitstate, fielddesc, valuebox)
+    return destbox.op_setfield(jitstate, fielddesc, valuebox)
 
 def ll_gengetsubstruct(jitstate, fielddesc, argbox):
     if argbox.is_constant():
         res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE),
                       fielddesc.fieldname)
         return rvalue.ll_fromvalue(jitstate, res)
-    assert isinstance(argbox, rvalue.PtrRedBox)
-    if argbox.content is None:
-        gv_ptr = argbox.getgenvar(jitstate.curbuilder)
-        return fielddesc.generate_getsubstruct(jitstate.curbuilder, gv_ptr)
-    else:
-        return argbox.content.op_getsubstruct(jitstate, fielddesc)
-
+    return argbox.op_getsubstruct(jitstate, fielddesc)
 
 def ll_gengetarrayitem(jitstate, fielddesc, argbox, indexbox):
     if fielddesc.immutable and argbox.is_constant() and indexbox.is_constant():

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Mon Oct  9 20:45:39 2006
@@ -409,14 +409,15 @@
             
         v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
                                               green_void_repr)
+        v_argbox = hop.llops.as_ptrredbox(v_argbox)
         structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
         fielddesc = structdesc.getfielddesc(c_fieldname.value)
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gengetfield,
-            [ts.s_JITState, s_fielddesc, ts.s_RedBox],
-            [v_jitstate,    c_fielddesc, v_argbox   ],
+            [ts.s_JITState, s_fielddesc, ts.s_PtrRedBox],
+            [v_jitstate,    c_fielddesc, v_argbox      ],
             ts.s_RedBox)
 
     def translate_op_getarrayitem(self, hop):
@@ -486,14 +487,15 @@
                                                            green_void_repr,
                                                            self.getredrepr(VALUETYPE)
                                                            )
+        v_destbox = hop.llops.as_ptrredbox(v_destbox)
         structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
         fielddesc = structdesc.getfielddesc(c_fieldname.value)
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gensetfield,
-            [ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
-            [v_jitstate,    c_fielddesc, v_destbox,   v_valuebox],
+            [ts.s_JITState, s_fielddesc, ts.s_PtrRedBox, ts.s_RedBox],
+            [v_jitstate,    c_fielddesc, v_destbox,      v_valuebox],
             annmodel.s_None)
 
     def translate_op_setarrayitem(self, hop):
@@ -519,14 +521,15 @@
         PTRTYPE = originalconcretetype(hop.args_s[0])
         v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
                                               green_void_repr)
+        v_argbox = hop.llops.as_ptrredbox(v_argbox)
         fielddesc = rcontainer.NamedFieldDesc(self.RGenOp, PTRTYPE,
                                               c_fieldname.value)
         c_fielddesc = inputconst(lltype.Void, fielddesc)
         s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
         v_jitstate = hop.llops.getjitstate()
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_gengetsubstruct,
-            [ts.s_JITState, s_fielddesc, ts.s_RedBox],
-            [v_jitstate,    c_fielddesc, v_argbox   ],
+            [ts.s_JITState, s_fielddesc, ts.s_PtrRedBox],
+            [v_jitstate,    c_fielddesc, v_argbox      ],
             ts.s_RedBox)
 
     def translate_op_cast_pointer(self, hop):
@@ -894,8 +897,7 @@
         args_s = [ts.s_RedBox] * len(args_v)
         if oopspecdesc.is_method:
             args_s[0] = ts.s_PtrRedBox    # for more precise annotations
-            args_v[0] = hop.llops.genop('cast_pointer', [args_v[0]],
-                               resulttype = ts.r_PtrRedBox.lowleveltype)
+            args_v[0] = hop.llops.as_ptrredbox(args_v[0])
         RESULT = originalconcretetype(hop.s_result)
         if RESULT is lltype.Void:
             s_result = annmodel.s_None
@@ -1033,6 +1035,14 @@
     def setjitstate(self, v_newjitstate):
         self.genop('setjitstate', [v_newjitstate])
 
+    def as_redbox(self, v_ptrredbox):
+        return self.genop('cast_pointer', [v_ptrredbox],
+                          resulttype = self.hrtyper.r_RedBox)
+
+    def as_ptrredbox(self, v_redbox):
+        return self.genop('cast_pointer', [v_redbox],
+                          resulttype = self.hrtyper.r_PtrRedBox)
+
 # ____________________________________________________________
 
 class __extend__(pairtype(HintTypeSystem, hintmodel.SomeLLAbstractValue)):
@@ -1120,8 +1130,7 @@
             self.typedesc = rcontainer.StructTypeDesc(ts.RGenOp, T)
         v_ptrbox = hop.llops.genmixlevelhelpercall(self.typedesc.ll_factory,
             [], [], ts.s_PtrRedBox)
-        return hop.llops.genop('cast_pointer', [v_ptrbox], resulttype=
-                               ts.r_RedBox)
+        return hop.llops.as_redbox(v_ptrbox)
 
 
 class BlueRepr(Repr):

Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py	Mon Oct  9 20:45:39 2006
@@ -178,6 +178,41 @@
         else:
             return RedBox.__repr__(self)
 
+    def op_getfield(self, jitstate, fielddesc):
+        if self.content is not None:
+            box = self.content.op_getfield(jitstate, fielddesc)
+            if box is not None:
+                return box
+        gv_ptr = self.getgenvar(jitstate.curbuilder)
+        box = fielddesc.generate_get(jitstate.curbuilder, gv_ptr)
+        if fielddesc.immutable:
+            self.remember_field(fielddesc, box)
+        return box
+
+    def op_setfield(self, jitstate, fielddesc, valuebox):
+        gv_ptr = self.genvar
+        if gv_ptr:
+            fielddesc.generate_set(jitstate.curbuilder, gv_ptr, valuebox)
+        else:
+            assert self.content is not None
+            self.content.op_setfield(jitstate, fielddesc, valuebox)
+
+    def op_getsubstruct(self, jitstate, fielddesc):
+        gv_ptr = self.genvar
+        if gv_ptr:
+            return fielddesc.generate_getsubstruct(jitstate.curbuilder, gv_ptr)
+        else:
+            assert self.content is not None
+            return self.content.op_getsubstruct(jitstate, fielddesc)
+
+    def remember_field(self, fielddesc, box):
+        if self.genvar.is_const:
+            return      # no point in remembering field then
+        if self.content is None:
+            from pypy.jit.timeshifter import rcontainer
+            self.content = rcontainer.PartialDataStruct()
+        self.content.remember_field(fielddesc, box)
+
     def copy(self, memo):
         boxmemo = memo.boxes
         try:
@@ -207,7 +242,8 @@
         try:
             return boxmemo[self]
         except KeyError:
-            if self.content:
+            if not self.genvar:
+                assert self.content is not None
                 result = FrozenPtrVirtual(self.kind)
                 boxmemo[self] = result
                 result.fz_content = self.content.freeze(memo)
@@ -216,6 +252,12 @@
                     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
                 boxmemo[self] = result
             return result
 
@@ -226,11 +268,17 @@
             assert self.genvar
         return self.genvar
 
+##    def forcevar(self, builder, memo):
+##        RedBox.forcevar(self, builder, memo)
+##        # if self.content is still there, it's a PartialDataStruct
+##        # - for now, we always remove it in this situation
+##        self.content = None
+
     def enter_block(self, incoming, memo):
+        if self.genvar:
+            RedBox.enter_block(self, incoming, memo)
         if self.content:
             self.content.enter_block(incoming, memo)
-        else:
-            RedBox.enter_block(self, incoming, memo)
 
 # ____________________________________________________________
 
@@ -378,12 +426,28 @@
 
     def exactmatch(self, box, outgoingvarboxes, memo):
         assert isinstance(box, PtrRedBox)
-        if box.content is None:
+        if box.genvar:
             outgoingvarboxes.append(box)
             return False
         else:
+            assert box.content is not None
             return self.fz_content.exactmatch(box.content, outgoingvarboxes,
                                               memo)
 
     def unfreeze(self, incomingvarboxes, memo):
         return self.fz_content.unfreeze(incomingvarboxes, memo)
+
+
+##class FrozenPtrVarWithData(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

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	Mon Oct  9 20:45:39 2006
@@ -43,8 +43,6 @@
         self.check_insns(int_add=10, int_mul=0)
 
     def test_multiple_portal_calls(self):
-        # so far, crashes when we call timeshift() multiple times
-        py.test.skip("in-progress")
         def ll_function(n):
             k = n
             if k > 5:
@@ -244,7 +242,6 @@
 
 
     def test_method_call_promote(self):
-        py.test.skip("in-progress")
         class Base(object):
             pass
         class Int(Base):
@@ -276,8 +273,8 @@
 
         res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
         assert res == 10
-        self.check_insns(indirect_call=0, direct_call=1)
+        self.check_insns(indirect_call=0)
 
         res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL)
         assert res == ord('2')
-        self.check_insns(indirect_call=0, direct_call=1)
+        self.check_insns(indirect_call=0)

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	Mon Oct  9 20:45:39 2006
@@ -80,6 +80,10 @@
         key = ll_function, inline, policy
         try:
             cache, argtypes = self._cache[key]
+            # XXX TEMPORARY: for now, caching doesn't work in the presence
+            # of global caches
+            if getattr(ll_function, '_global_merge_points_', False):
+                raise KeyError
         except KeyError:
             pass
         else:



More information about the Pypy-commit mailing list