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

ac at codespeak.net ac at codespeak.net
Sun Jan 14 17:24:16 CET 2007


Author: ac
Date: Sun Jan 14 17:24:15 2007
New Revision: 36743

Modified:
   pypy/dist/pypy/jit/timeshifter/hrtyper.py
   pypy/dist/pypy/jit/timeshifter/rcontainer.py
   pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py
Log:
(pedronis, arre) Small support for lazy forcing of virtual structures in
virtualizable structures. Much more to be fixed such as aliasing and doing
the right thing after a residual call that resulted in forcing of one or more
structures.



Modified: pypy/dist/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/hrtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/hrtyper.py	Sun Jan 14 17:24:15 2007
@@ -8,6 +8,8 @@
 from pypy.annotation import listdef
 from pypy.annotation.pairtype import pair, pairtype
 from pypy.rpython.annlowlevel import PseudoHighLevelCallable
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rpython import annlowlevel
 from pypy.rpython.rtyper import RPythonTyper, LowLevelOpList, TyperError
@@ -154,6 +156,68 @@
         self.v_queue = varoftype(self.r_Queue.lowleveltype, 'queue')
         #self.void_red_repr = VoidRedRepr(self)
 
+        annhelper = self.annhelper
+        def make_vinfo():
+            vinfo = rcontainer.VirtualInfo(RGenOp)
+            return cast_instance_to_base_ptr(vinfo)
+
+        s_vableinfoptr = annmodel.lltype_to_annotation(rcontainer.VABLEINFOPTR)
+        s_info = annmodel.lltype_to_annotation(llmemory.GCREF)
+        
+        make_vinfo_ptr = annhelper.delayedfunction(make_vinfo, [],
+                                                   s_vableinfoptr,
+                                                   needtype=True)
+        self.gv_make_vinfo_ptr = RGenOp.constPrebuiltGlobal(make_vinfo_ptr)
+        self.make_vinfo_token = RGenOp.sigToken(
+                                     lltype.typeOf(make_vinfo_ptr).TO)
+
+        def vinfo_set_info(vinfo, info):
+            vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
+                                              vinfo)
+            vinfo.info = info
+
+        vinfo_set_info_ptr = annhelper.delayedfunction(vinfo_set_info,
+                              [s_vableinfoptr, s_info],
+                              annmodel.s_None,
+                              needtype=True)
+        self.gv_vinfo_set_info_ptr = RGenOp.constPrebuiltGlobal(
+            vinfo_set_info_ptr)
+        self.vinfo_set_info_token = RGenOp.sigToken(
+                                     lltype.typeOf(vinfo_set_info_ptr).TO)
+        
+
+        def vinfo_append_vinfo(vinfo, vinfo1):
+            vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
+                                              vinfo)
+            vinfo1 = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
+                                              vinfo1)
+            vinfo.vinfos.append(vinfo1)
+
+        vinfo_append_vinfo_ptr = annhelper.delayedfunction(vinfo_append_vinfo,
+                              [s_vableinfoptr, s_vableinfoptr],
+                              annmodel.s_None,
+                              needtype=True)
+        self.gv_vinfo_append_vinfo_ptr = RGenOp.constPrebuiltGlobal(
+            vinfo_append_vinfo_ptr)
+        self.vinfo_append_vinfo_token = RGenOp.sigToken(
+                                     lltype.typeOf(vinfo_append_vinfo_ptr).TO)
+        
+        def vinfo_skip_vinfo(vinfo):
+            vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
+                                              vinfo)
+            vinfo.vinfos.append(None)
+
+        vinfo_skip_vinfo_ptr = annhelper.delayedfunction(vinfo_skip_vinfo,
+                              [s_vableinfoptr],
+                              annmodel.s_None,
+                              needtype=True)
+        self.gv_vinfo_skip_vinfo_ptr = RGenOp.constPrebuiltGlobal(
+            vinfo_skip_vinfo_ptr)
+        self.vinfo_skip_vinfo_token = RGenOp.sigToken(
+                                     lltype.typeOf(vinfo_skip_vinfo_ptr).TO)
+        
+
+
     def specialize(self, origportalgraph=None, view=False):
         """
         Driver for running the timeshifter.

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Sun Jan 14 17:24:15 2007
@@ -1,12 +1,13 @@
 
 import operator
 from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.annlowlevel import cachedtype
+from pypy.rpython.annlowlevel import cachedtype, cast_base_ptr_to_instance
+from pypy.rpython.annlowlevel import base_ptr_lltype, cast_instance_to_base_ptr
 from pypy.jit.timeshifter import rvalue
 from pypy.rlib.unroll import unrolling_iterable
 
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltypesystem import lloperation
+from pypy.rpython.lltypesystem import lloperation, llmemory
 debug_print = lloperation.llop.debug_print
 debug_pdb = lloperation.llop.debug_pdb
 
@@ -40,6 +41,7 @@
 
 VABLEFIELDS = ('vable_base', 'vable_info', 'vable_access')
 NVABLEFIELDS = len(VABLEFIELDS)
+VABLEINFOPTR = base_ptr_lltype()
 
 class StructTypeDesc(object):
     __metaclass__ = cachedtype
@@ -108,14 +110,16 @@
             j = 0
             def make_get_field(T, j):
                 def get_field(struc):
-                    return RGenOp.read_frame_var(T, struc.vable_base,
-                                                 struc.vable_info,
-                                                 j)
+                    vable_info = struc.vable_info
+                    vable_info = cast_base_ptr_to_instance(VirtualInfo,
+                                                           vable_info)
+                    return vable_info.read_field(fielddesc,
+                                                 struc.vable_base, j)
                 return get_field
             s_structtype = annmodel.lltype_to_annotation(self.PTRTYPE)
             for i in range(NVABLEFIELDS, len(fielddescs)):
                 fielddesc = fielddescs[i]        
-                get_field = make_get_field(fielddesc.RESTYPE, j)
+                get_field = make_get_field(fielddesc, j)
                 j += 1
                 s_lltype = annmodel.lltype_to_annotation(fielddesc.RESTYPE)
                 get_field_ptr = annhelper.delayedfunction(get_field,
@@ -126,9 +130,10 @@
                 setattr(access, 'get_'+name, get_field_ptr)
         else:
             self.VStructCls = VirtualStruct
-            
+
+        descs = unrolling_iterable(fielddescs)
         if self.immutable and self.noidentity:
-            descs = unrolling_iterable(fielddescs)
+            
             def materialize(rgenop, boxes):
                 s = lltype.malloc(TYPE)
                 i = 0
@@ -139,7 +144,25 @@
                 return rgenop.genconst(s)
 
             self.materialize = materialize
-                
+
+        def fill_into(s, base, vinfo):
+            i = 0
+            for desc in descs:
+                v = vinfo.read_field(desc, base, i)
+                i += 1
+                setattr(s, desc.fieldname, v)
+        self.fill_into = fill_into
+
+        self.gv_make_vinfo_ptr = hrtyper.gv_make_vinfo_ptr
+        self.make_vinfo_token = hrtyper.make_vinfo_token
+
+        self.gv_vinfo_set_info_ptr = hrtyper.gv_vinfo_set_info_ptr
+        self.vinfo_set_info_token = hrtyper.vinfo_set_info_token
+        self.gv_vinfo_append_vinfo_ptr = hrtyper.gv_vinfo_append_vinfo_ptr
+        self.vinfo_append_vinfo_token = hrtyper.vinfo_append_vinfo_token
+        self.gv_vinfo_skip_vinfo_ptr = hrtyper.gv_vinfo_skip_vinfo_ptr
+        self.vinfo_skip_vinfo_token = hrtyper.vinfo_skip_vinfo_token
+        
     def getfielddesc(self, name):
         return self.fielddesc_by_name[name]
 
@@ -172,16 +195,20 @@
     allow_void = False
     virtualizable = False
     gv_default = None
-
+    
     def __init__(self, hrtyper, PTRTYPE, RESTYPE):
         RGenOp = hrtyper.RGenOp
         self.PTRTYPE = PTRTYPE
+        T = None
         if isinstance(RESTYPE, lltype.ContainerType):
+            T = RESTYPE
             RESTYPE = lltype.Ptr(RESTYPE)
         elif isinstance(RESTYPE, lltype.Ptr):
             T = RESTYPE.TO
             if hasattr(T, '_hints'):
                 self.virtualizable = T._hints.get('virtualizable', False)
+            if not isinstance(T, lltype.ContainerType):
+                T = None
         self.RESTYPE = RESTYPE
         self.ptrkind = RGenOp.kindToken(PTRTYPE)
         self.kind = RGenOp.kindToken(RESTYPE)
@@ -190,9 +217,14 @@
         if RESTYPE is lltype.Void and self.allow_void:
             pass   # no redboxcls at all
         elif self.virtualizable:
-            self.structdesc = StructTypeDesc(hrtyper, T)
+            pass
         else:
             self.redboxcls = rvalue.ll_redboxcls(RESTYPE)
+
+        if T is not None and isinstance(T, lltype.Struct): # xxx for now
+            self.structdesc = StructTypeDesc(hrtyper, T)
+            self.fill_into = self.structdesc.fill_into
+            
         self.immutable = PTRTYPE.TO._hints.get('immutable', False)
 
     def _freeze_(self):
@@ -212,6 +244,7 @@
             return structbox
         return self.redboxcls(self.kind, gvar)
 
+    
 class NamedFieldDesc(FieldDesc):
 
     def __init__(self, hrtyper, PTRTYPE, name):
@@ -390,6 +423,60 @@
     def op_getsubstruct(self, jitstate, fielddesc):
         return self.ownbox
 
+    def make_vinfo(self, jitstate):
+        # xxx aliasing
+        typedesc = self.typedesc
+        assert typedesc is not None
+        builder = jitstate.curbuilder
+        gv_vinfo = builder.genop_call(typedesc.make_vinfo_token,
+                           typedesc.gv_make_vinfo_ptr,
+                           [])
+        vars_gv = []
+        for box in self.content_boxes:
+            if box.genvar:
+                vars_gv.append(box.genvar)
+                builder.genop_call(typedesc.vinfo_skip_vinfo_token,
+                           typedesc.gv_vinfo_skip_vinfo_ptr,
+                           [gv_vinfo])
+
+            else:
+                vars_gv.append(None)
+                assert isinstance(box, rvalue.PtrRedBox)
+                content = box.content
+                assert isinstance(content, VirtualStruct) # XXX for now
+                gv_vinfo1 = content.make_vinfo(jitstate)
+                builder.genop_call(typedesc.vinfo_append_vinfo_token,
+                           typedesc.gv_vinfo_append_vinfo_ptr,
+                           [gv_vinfo, gv_vinfo1])
+
+
+        gv_info = builder.get_frame_info(vars_gv)
+        builder.genop_call(typedesc.vinfo_set_info_token,
+                           typedesc.gv_vinfo_set_info_ptr,
+                           [gv_vinfo, gv_info])
+        return gv_vinfo
+
+class VirtualInfo(object):
+
+    def __init__(self, RGenOp):
+        self.RGenOp = RGenOp
+        self.vinfos = []
+
+    def read_field(self, fielddesc, base, index):
+        T = fielddesc.RESTYPE
+        vinfo = self.vinfos[index]
+        if vinfo is None:
+            return self.RGenOp.read_frame_var(T, base,
+                                              self.info, index)
+        assert isinstance(T, lltype.Ptr)
+        S = T.TO
+        s = lltype.malloc(S)
+        # xxx remember that s has been forced
+        fielddesc.fill_into(s, base, vinfo)
+        return s
+                    
+    read_field._annspecialcase_ = "specialize:arg(1)"
+
 class VirtualizableStruct(VirtualStruct):
 
     def force_runtime_container(self, jitstate):
@@ -434,19 +521,42 @@
             assert base_desc is not None
             base_token = base_desc.fieldtoken
             builder.genop_setfield(base_token, gv_outside, gv_base)
-            # xxx recursive and virtual stuff
+            # xxx aliasing
             boxes = self.content_boxes
             vars_gv = []
             n = len(boxes)
+            gv_vinfo = builder.genop_call(typedesc.make_vinfo_token,
+                               typedesc.gv_make_vinfo_ptr,
+                               [])
             for i in range(NVABLEFIELDS, n-1):
                 box = boxes[i]
-                assert box.genvar
-                vars_gv.append(box.genvar)
+                if box.genvar:
+                    vars_gv.append(box.genvar)
+                    builder.genop_call(typedesc.vinfo_skip_vinfo_token,
+                               typedesc.gv_vinfo_skip_vinfo_ptr,
+                               [gv_vinfo])
+                    
+                else:
+                    vars_gv.append(None)
+                    assert isinstance(box, rvalue.PtrRedBox)
+                    content = box.content
+                    assert isinstance(content, VirtualStruct) # XXX for now
+                    gv_vinfo1 = content.make_vinfo(jitstate)
+                    builder.genop_call(typedesc.vinfo_append_vinfo_token,
+                               typedesc.gv_vinfo_append_vinfo_ptr,
+                               [gv_vinfo, gv_vinfo1])
+                    
+                    
             gv_info = builder.get_frame_info(vars_gv)
+            builder.genop_call(typedesc.vinfo_set_info_token,
+                               typedesc.gv_vinfo_set_info_ptr,
+                               [gv_vinfo, gv_info])
             info_token = typedesc.info_desc.fieldtoken
+            builder.genop_setfield(info_token, gv_outside,
+                                   gv_vinfo)
             access_token = typedesc.access_desc.fieldtoken
-            builder.genop_setfield(info_token, gv_outside, gv_info)
-            builder.genop_setfield(access_token, gv_outside, typedesc.gv_access)
+            builder.genop_setfield(access_token, gv_outside,
+                                   typedesc.gv_access)
 
     def after_residual_call(self, jitstate):
         typedesc = self.typedesc

Modified: pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py	Sun Jan 14 17:24:15 2007
@@ -1,7 +1,7 @@
 from pypy.jit.hintannotator.annotator import HintAnnotatorPolicy
 from pypy.jit.timeshifter.test.test_portal import PortalTest, P_NOVIRTUAL
 from pypy.rpython.lltypesystem import lltype, llmemory
-
+from pypy.jit.timeshifter.rcontainer import VABLEINFOPTR
 import py
 
 S = lltype.GcStruct('s', ('a', lltype.Signed), ('b', lltype.Signed))
@@ -38,7 +38,7 @@
 
 XY.become(lltype.GcStruct('xy',
                           ('vable_base', llmemory.Address),
-                          ('vable_info', llmemory.GCREF),
+                          ('vable_info', VABLEINFOPTR),
                           ('vable_access', lltype.Ptr(XY_ACCESS)),
                           ('x', lltype.Signed),
                           ('y', lltype.Signed),
@@ -50,13 +50,16 @@
 
 XP.become(lltype.GcStruct('xp',
                           ('vable_base', llmemory.Address),
-                          ('vable_info', llmemory.GCREF),                     
+                          ('vable_info', VABLEINFOPTR),                     
                           ('vable_access', lltype.Ptr(XP_ACCESS)),
                           ('x', lltype.Signed),
                           ('p', PS),
                           hints = {'virtualizable': True}
               ))
 
+E2 = lltype.GcStruct('e', ('xp', lltype.Ptr(XP)),
+                         ('w',  lltype.Signed))
+
      
 class TestVirtualizable(PortalTest):
 
@@ -506,7 +509,8 @@
 
 
         class StopAtGPolicy(HintAnnotatorPolicy):
-            novirtualcontainer = True
+            def __init__(self):
+                HintAnnotatorPolicy.__init__(self, novirtualcontainer=True)
 
             def look_inside_graph(self, graph):
                 if graph.name == 'g':
@@ -556,7 +560,8 @@
 
 
         class StopAtGPolicy(HintAnnotatorPolicy):
-            novirtualcontainer = True
+            def __init__(self):
+                HintAnnotatorPolicy.__init__(self, novirtualcontainer=True)
 
             def look_inside_graph(self, graph):
                 if graph.name == 'g':
@@ -566,3 +571,70 @@
         res = self.timeshift_from_portal(main, f, [2, 20],
                                          policy=StopAtGPolicy())
         assert res == 42
+
+    def test_explicit_force_in_residual_red_call(self):
+
+        def g(e):
+            xp = e.xp
+            xp_access = xp.vable_access
+            if xp_access:
+                p = xp_access.get_p(xp)
+            else:
+                p = xp.p
+            xp_access = xp.vable_access
+            if xp_access:
+                x = xp_access.get_x(xp)
+            else:
+                x = xp.x
+                
+            e.w = p.a + p.b + x
+
+        def f(e, a, b):
+            xp = e.xp
+            s = lltype.malloc(S)
+            s.a = a
+            s.b = b            
+            xp_access = xp.vable_access
+            if xp_access:
+                xp_access.set_p(xp, s)
+            else:
+                xp.p = s
+            xp_access = xp.vable_access
+            
+            xp_access = xp.vable_access
+            if xp_access:
+                x = xp_access.get_x(xp)
+            else:
+                x = xp.x
+            xp_access = xp.vable_access
+            newx = 2*x
+            if xp_access:
+                xp_access.set_x(xp, newx)
+            else:
+                xp.x = newx
+            g(e)            
+            return xp.x
+            
+        def main(a, b, x):
+            xp = lltype.malloc(XP)
+            xp.vable_access = lltype.nullptr(XP_ACCESS)
+            xp.x = x
+            xp.p = lltype.nullptr(S)
+            e = lltype.malloc(E2)
+            e.xp = xp
+            f(e, a, b)
+            return e.w
+
+
+        class StopAtGPolicy(HintAnnotatorPolicy):
+            def __init__(self):
+                HintAnnotatorPolicy.__init__(self, novirtualcontainer=True)
+
+            def look_inside_graph(self, graph):
+                if graph.name == 'g':
+                    return False
+                return True
+
+        res = self.timeshift_from_portal(main, f, [2, 20, 10],
+                                         policy=StopAtGPolicy())
+        assert res == 42


More information about the pypy-svn mailing list