[pypy-svn] r37308 - in pypy/dist/pypy: jit/codegen jit/codegen/llgraph jit/codegen/llgraph/test jit/goal jit/timeshifter jit/timeshifter/test rpython rpython/lltypesystem

ac at codespeak.net ac at codespeak.net
Wed Jan 24 23:33:54 CET 2007


Author: ac
Date: Wed Jan 24 23:33:53 2007
New Revision: 37308

Added:
   pypy/dist/pypy/jit/timeshifter/rvirtualizable.py   (contents, props changed)
Modified:
   pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
   pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
   pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py
   pypy/dist/pypy/jit/codegen/model.py
   pypy/dist/pypy/jit/goal/jitstep.py
   pypy/dist/pypy/jit/timeshifter/hrtyper.py
   pypy/dist/pypy/jit/timeshifter/rcontainer.py
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
   pypy/dist/pypy/jit/timeshifter/test/test_portal.py
   pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/rvirtualizable.py
Log:
(arre, pedronis)

do less work around residual calls in the presence of virtualizable, one test about this.

various refactorings to achieve this and streamline and cleanup the related code.



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	Wed Jan 24 23:33:53 2007
@@ -219,6 +219,7 @@
     c = from_opaque_object(gv_value)
     return isinstance(c, flowmodel.Constant)
 
+
 # XXX
 # temporary interface; it's unclear if genop itself should change to
 # ease dinstinguishing Void special args from the rest. Or there
@@ -569,8 +570,17 @@
 
 # read frame var support
 
+def get_frame_info(block, vars_gv):
+    genop(block, 'frame_info', vars_gv, lltype.Void)
+    block = from_opaque_object(block)
+    frame_info = block.operations[-1]
+    return lltype.opaqueptr(llmemory.GCREF.TO, 'frame_info',
+                            info=frame_info)
+
+setannotation(get_frame_info, annmodel.SomePtr(llmemory.GCREF))
+
 def read_frame_var(T, base, info, index):
-    vars = info._obj.vars
+    vars = info._obj.info.args
     v = vars[index]
     if isinstance(v, flowmodel.Constant):
         val = v.value

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	Wed Jan 24 23:33:53 2007
@@ -40,7 +40,6 @@
 gv_dummy_placeholder = LLConst(llimpl.dummy_placeholder)
 
 gv_Address = gv_TYPE(llmemory.Address)
-gv_GCREF = gv_TYPE(llmemory.GCREF)
 
 class LLLabel(GenLabel):
     def __init__(self, b, g):
@@ -276,13 +275,12 @@
 
     # read_frame_var support
 
-    def get_frame_base(self):
+    def genop_get_frame_base(self):
         return LLVar(llimpl.genop(self.b, 'get_frame_base', [],
                                   gv_Address.v))
 
     def get_frame_info(self, vars):
-        return LLVar(llimpl.genop(self.b, 'get_frame_info', vars,
-                                  gv_GCREF.v))
+        return llimpl.get_frame_info(self.b, vars)
 
 class RGenOp(AbstractRGenOp):
     gv_Void = gv_Void

Modified: pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py	Wed Jan 24 23:33:53 2007
@@ -47,8 +47,9 @@
     builder.start_writing()
 
     gv_y = builder.genop2("int_mul", gv_x, rgenop.genconst(2))
-    gv_base = builder.get_frame_base()
-    gv_info = builder.get_frame_info([gv_y])
+    gv_base = builder.genop_get_frame_base()
+    info = builder.get_frame_info([gv_y])
+    gv_info = RGenOp.constPrebuiltGlobal(info)
     gv_z = builder.genop_call(readertoken, gv_reader, [gv_base, gv_info])
     builder.finish_and_return(sigtoken, gv_z)
     builder.end()

Modified: pypy/dist/pypy/jit/codegen/model.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/model.py	(original)
+++ pypy/dist/pypy/jit/codegen/model.py	Wed Jan 24 23:33:53 2007
@@ -175,10 +175,10 @@
 
     # read frame var support
     
-    def get_frame_base(self):
+    def genop_get_frame_base(self):
         pass
 
-    def get_frame_info(self):
+    def get_frame_info(self, vars):
         pass
         
 class GenLabel(object):

Modified: pypy/dist/pypy/jit/goal/jitstep.py
==============================================================================
--- pypy/dist/pypy/jit/goal/jitstep.py	(original)
+++ pypy/dist/pypy/jit/goal/jitstep.py	Wed Jan 24 23:33:53 2007
@@ -11,9 +11,12 @@
 class PyPyHintAnnotatorPolicy(HintAnnotatorPolicy):
 
     def look_inside_graph(self, graph):
-        func = graph.func
+        try:
+            func = graph.func
+        except AttributeError:
+            return True
         mod = func.__module__ or '?'
-        if mod.startswith('pypy.objspace.'):
+        if mod.startswith('pypy.objspace'):
             return False
         if mod.startswith('pypy.module.'):
             return False
@@ -32,7 +35,6 @@
 POLICY = PyPyHintAnnotatorPolicy(novirtualcontainer = True,
                                  oopspec = True)
 
-
 def hintannotate(drv):
     t = drv.translator
     portal_graph = graphof(t, PORTAL)
@@ -65,4 +67,4 @@
         t.graphs.append(graph)
         
     # XXX temp
-    drv.source()
+    drv.compile()

Modified: pypy/dist/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/hrtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/hrtyper.py	Wed Jan 24 23:33:53 2007
@@ -158,108 +158,41 @@
 
         # XXX use helpers, factor out perhaps?
         annhelper = self.annhelper
-        def make_vinfo(bitmask):
-            vinfo = rcontainer.VirtualInfo(RGenOp, bitmask)
-            return cast_instance_to_base_ptr(vinfo)
+        from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR
+        s_vablertiptr = annmodel.lltype_to_annotation(VABLERTIPTR)
 
-        s_vableinfoptr = annmodel.lltype_to_annotation(rcontainer.VABLEINFOPTR)
         s_gcref = annmodel.lltype_to_annotation(llmemory.GCREF)
-        s_info = s_gcref
-        
-        make_vinfo_ptr = annhelper.delayedfunction(make_vinfo, [annmodel.SomeInteger()],
-                                                   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 vinfo_get_shape(vinfo):
-            vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
-                                              vinfo)
-            return vinfo.get_shape()
-        vinfo_get_shape_ptr = annhelper.delayedfunction(vinfo_get_shape,
-                                                        [s_vableinfoptr],
-                                                        annmodel.SomeInteger(),
-                                                        needtype=True)
-        self.gv_vinfo_get_shape_ptr = RGenOp.constPrebuiltGlobal(
-            vinfo_get_shape_ptr)
-        self.vinfo_get_shape_token = RGenOp.sigToken(
-                                     lltype.typeOf(vinfo_get_shape_ptr).TO)
-
-
-        def vinfo_get_vinfo(vinfo, index):
-            vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
-                                              vinfo)
-            childvinfo = vinfo.vinfos[index]
-            return cast_instance_to_base_ptr(childvinfo)            
-
-        vinfo_get_vinfo_ptr = annhelper.delayedfunction(vinfo_get_vinfo,
-                              [s_vableinfoptr, annmodel.SomeInteger()],
-                              s_vableinfoptr,
-                              needtype=True)
-        self.gv_vinfo_get_vinfo_ptr = RGenOp.constPrebuiltGlobal(
-            vinfo_get_vinfo_ptr)
-        self.vinfo_get_vinfo_token = RGenOp.sigToken(
-                                     lltype.typeOf(vinfo_get_vinfo_ptr).TO)
-
-        def vinfo_read_forced(vinfo):
-            vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
-                                              vinfo)
-            return vinfo.read_forced()
+        from pypy.jit.timeshifter import rvirtualizable
+        def vrti_get_global_shape(vablerti):
+            vablerti = cast_base_ptr_to_instance(
+                         rvirtualizable.VirtualizableRTI,
+                         vablerti)
+            return vablerti.get_global_shape()
+        vrti_get_global_shape_ptr = annhelper.delayedfunction(
+                                        vrti_get_global_shape,
+                                        [s_vablertiptr],
+                                        annmodel.SomeInteger(),
+                                        needtype=True)
+        self.gv_vrti_get_global_shape_ptr = RGenOp.constPrebuiltGlobal(
+            vrti_get_global_shape_ptr)
+        self.vrti_get_global_shape_token = RGenOp.sigToken(
+                                  lltype.typeOf(vrti_get_global_shape_ptr).TO)
+
+
+        def vrti_read_forced(vablerti, bitkey):
+            vablerti = cast_base_ptr_to_instance(
+                     rvirtualizable.WithForcedStateVirtualizableRTI,
+                              vablerti)
+            return vablerti.read_forced(bitkey)
 
-        vinfo_read_forced_ptr = annhelper.delayedfunction(vinfo_read_forced,
-                              [s_vableinfoptr],
+        vrti_read_forced_ptr = annhelper.delayedfunction(vrti_read_forced,
+                              [s_vablertiptr, annmodel.SomeInteger()],
                               s_gcref,
                               needtype=True)
-        self.gv_vinfo_read_forced_ptr = RGenOp.constPrebuiltGlobal(
-            vinfo_read_forced_ptr)
-        self.vinfo_read_forced_token = RGenOp.sigToken(
-                                     lltype.typeOf(vinfo_read_forced_ptr).TO)
+        self.gv_vrti_read_forced_ptr = RGenOp.constPrebuiltGlobal(
+            vrti_read_forced_ptr)
+        self.vrti_read_forced_token = RGenOp.sigToken(
+                                     lltype.typeOf(vrti_read_forced_ptr).TO)
 
         # global state for the portal corresponding to this timeshifted world
         class PortalState(object):
@@ -464,7 +397,7 @@
                                                   TYPES))
         fetch_global_excdata = self.fetch_global_excdata
 
-        def portalreentry(jitstate, *args): # xxx
+        def portalreentry(jitstate, *args): # xxx virtualizables?
             i = 0
             key = ()
             curbuilder = jitstate.curbuilder
@@ -609,7 +542,10 @@
             redreprcls = RedRepr
             if isinstance(lowleveltype, lltype.Ptr):
                 if isinstance(lowleveltype.TO, lltype.Struct):
-                    redreprcls = RedStructRepr
+                    if lowleveltype.TO._hints.get('virtualizable', False):
+                        redreprcls = RedVirtualizableStructRepr
+                    else:
+                        redreprcls = RedStructRepr
             r = redreprcls(lowleveltype, self)
             self.red_reprs[lowleveltype] = r
             return r
@@ -956,14 +892,14 @@
         assert isinstance(hop.r_result, RedRepr)
         PTRTYPE = originalconcretetype(hop.s_result)
         TYPE = PTRTYPE.TO
+        v_size = hop.inputarg(self.getredrepr(lltype.Signed), arg=1)
         if isinstance(TYPE, lltype.Struct):
-            contdesc = rcontainer.StructTypeDesc(self, TYPE)
-        else:
-            contdesc = rcontainer.ArrayFieldDesc(self, TYPE)
+            return hop.r_result.create_varsize(hop, v_size)
+        
+        contdesc = rcontainer.ArrayFieldDesc(self, TYPE)
         c_contdesc = inputconst(lltype.Void, contdesc)
         s_contdesc = ts.rtyper.annotator.bookkeeper.immutablevalue(contdesc)
         v_jitstate = hop.llops.getjitstate()
-        v_size = hop.inputarg(self.getredrepr(lltype.Signed), arg=1)
         return hop.llops.genmixlevelhelpercall(rtimeshift.ll_genmalloc_varsize,
                    [ts.s_JITState, s_contdesc, ts.s_RedBox],
                    [v_jitstate,    c_contdesc, v_size     ], ts.s_RedBox)
@@ -1633,24 +1569,53 @@
 
 class RedStructRepr(RedRepr):
     typedesc = None
+    _s_c_typedesc = None
 
-    def residual_args_collector(self):
+    def gettypedesc(self):
+        if self.typedesc is None:
+            hrtyper = self.hrtyper
+            T = self.original_concretetype.TO
+            self.typedesc = rcontainer.StructTypeDesc(hrtyper, T)
+        return self.typedesc
+
+    def s_c_typedesc(self):
+        if self._s_c_typedesc is not None:
+            return self._s_c_typedesc
+        ts = self.hrtyper
         typedesc = self.gettypedesc()
-        if typedesc.virtualizable:
-            return typedesc.collect_residual_args
-        else:
-            return self.collect_residual_args
+        annhelper = ts.annhelper
+        s_r = annhelper.s_r_instanceof(rcontainer.StructTypeDesc)
+        s_typedesc, r_typedesc = s_r 
+        typedesc_ptr = ts.annhelper.delayedconst(r_typedesc, typedesc)
+        ctypedesc = inputconst(lltype.typeOf(typedesc_ptr), typedesc_ptr)
+        self._s_c_typedesc = s_typedesc, ctypedesc
+        return self._s_c_typedesc
 
-    def build_portal_arg_helpers(self):
-        T = self.original_concretetype.TO
-        if not T._hints.get('virtualizable', False):
-            RedRepr.build_portal_arg_helpers(self)
-            return
+    def create(self, hop):
+        ts = self.hrtyper
+        s_typedesc, ctypedesc = self.s_c_typedesc()
+        v_jitstate = hop.llops.getjitstate()
+        v_ptrbox = hop.llops.genmixlevelhelpercall(rcontainer.create,
+            [ts.s_JITState, s_typedesc], [v_jitstate, ctypedesc],
+            ts.s_PtrRedBox)
+        return hop.llops.as_redbox(v_ptrbox)
+
+    def create_varsize(self, hop, v_size):
+        ts = self.hrtyper
+        s_typedesc, ctypedesc = self.s_c_typedesc()
+        v_jitstate = hop.llops.getjitstate()
+        v_ptrbox = hop.llops.genmixlevelhelpercall(rcontainer.create_varsize,
+            [ts.s_JITState, s_typedesc, ts.s_RedBox],
+            [v_jitstate,    ctypedesc,  v_size     ], ts.s_PtrRedBox)
+        return hop.llops.as_redbox(v_ptrbox)
+
+class RedVirtualizableStructRepr(RedStructRepr):
 
+    def build_portal_arg_helpers(self):
         typedesc = self.gettypedesc()
         names = unrolling_iterable([(fielddesc.fieldname, j)
-                                    for (fielddesc, j) in typedesc.redirected_fielddescs])
-
+                                    for (fielddesc, j) in
+                                    typedesc.redirected_fielddescs])
         TYPE = self.original_concretetype
         kind = self.hrtyper.RGenOp.kindToken(TYPE)
         boxcls = rvalue.ll_redboxcls(TYPE)
@@ -1668,34 +1633,24 @@
                 i += 1
             content_boxes[-1].genvar = gv_outside
             return box
+        
         self.make_arg_redbox = make_arg_redbox
         make_arg_redbox.consumes = len(typedesc.redirected_fielddescs)+1
 
-    def gettypedesc(self):
-        if self.typedesc is None:
-            hrtyper = self.hrtyper
-            T = self.original_concretetype.TO
-            self.typedesc = rcontainer.StructTypeDesc(hrtyper, T)
-        return self.typedesc
-
-    def create(self, hop):
-        ts = self.hrtyper
-        typedesc = self.gettypedesc()
-        v_ptrbox = hop.llops.genmixlevelhelpercall(typedesc.ll_factory,
-            [], [], ts.s_PtrRedBox)
-        return hop.llops.as_redbox(v_ptrbox)
-
     def residual_argtypes(self):
         argtypes = [self.original_concretetype]
-        T = self.original_concretetype.TO
-        if T._hints.get('virtualizable', False):
-            getredrepr = self.hrtyper.getredrepr
-            typedesc = self.gettypedesc()
-            for fielddesc, _ in typedesc.redirected_fielddescs:
-                FIELDTYPE = fielddesc.RESTYPE
-                argtypes += getredrepr(FIELDTYPE).residual_argtypes()
+        getredrepr = self.hrtyper.getredrepr
+        typedesc = self.gettypedesc()
+        for fielddesc, _ in typedesc.redirected_fielddescs:
+            FIELDTYPE = fielddesc.RESTYPE
+            argtypes += getredrepr(FIELDTYPE).residual_argtypes()
         return argtypes
 
+    def residual_args_collector(self):
+        typedesc = self.gettypedesc()
+        return typedesc.collect_residual_args
+    
+
 ##class VoidRedRepr(Repr):
 ##    def __init__(self, hrtyper):
 ##        self.lowleveltype = hrtyper.r_RedBox.lowleveltype

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Wed Jan 24 23:33:53 2007
@@ -4,6 +4,7 @@
 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.jit.timeshifter import rvirtualizable
 
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem import lloperation, llmemory
@@ -37,52 +38,82 @@
         raise NotImplementedError
 
 # ____________________________________________________________
-from pypy.rpython.lltypesystem.rvirtualizable import VABLEINFOPTR
 
 class StructTypeDesc(object):
     __metaclass__ = cachedtype
 
-    _attrs_ = """firstsubstructdesc arrayfielddesc
-                 alloctoken varsizealloctoken
-                 materialize
-                 base_desc info_desc access_desc
-                 redirected_fielddescs
-                 gv_access
-                 gv_access_is_null_ptr access_is_null_token
-              """.split()
+    VirtualStructCls = None # patched later with VirtualStruct
+
+    __slots__ =  """TYPE PTRTYPE
+                    firstsubstructdesc arrayfielddesc
+                    innermostdesc
+                    ptrkind
+                    alloctoken varsizealloctoken
+                    null gv_null
+                    fielddescs fielddesc_by_name
+                    immutable noidentity
+                    materialize
+                    fill_into
+
+                    vrti_get_global_shape_token
+                    gv_vrti_get_global_shape_ptr
+                    vrti_read_forced_token
+                    gv_vrti_read_forced_ptr
+                    __dict__
+                 """.split()  # XXX remove rpython abuse of __slots__
+                              # use our own _attrs_ instead
 
     firstsubstructdesc = None
     materialize = None
-   
+
+    def __new__(cls, hrtyper, TYPE):
+        if TYPE._hints.get('virtualizable', False):
+            return object.__new__(VirtualizableStructTypeDesc)
+        else:
+            return object.__new__(StructTypeDesc)
+            
     def __init__(self, hrtyper, TYPE):
         RGenOp = hrtyper.RGenOp
         self.TYPE = TYPE
         self.PTRTYPE = lltype.Ptr(TYPE)
         self.ptrkind = RGenOp.kindToken(self.PTRTYPE)
-        innermostdesc = self
+
+        self.immutable = TYPE._hints.get('immutable', False)
+        self.noidentity = TYPE._hints.get('noidentity', False)
+
         if not TYPE._is_varsize():
             self.alloctoken = RGenOp.allocToken(TYPE)
 
-        # N.B. Closes over descs defined below
-        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.null = self.PTRTYPE._defl()
+        self.gv_null = RGenOp.constPrebuiltGlobal(self.null)
+
+        self._compute_fielddescs(hrtyper)
+        self._define_fill_into()
+        if self.immutable and self.noidentity:
+            self._define_materialize()
+
+        # xxx
+        self.gv_vrti_get_global_shape_ptr = hrtyper.gv_vrti_get_global_shape_ptr
+        self.vrti_get_global_shape_token = hrtyper.vrti_get_global_shape_token
+        
+        self.gv_vrti_read_forced_ptr = hrtyper.gv_vrti_read_forced_ptr
+        self.vrti_read_forced_token = hrtyper.vrti_read_forced_token
 
+    def _compute_fielddescs(self, hrtyper):
+        RGenOp = hrtyper.RGenOp
+        TYPE = self.TYPE
+        innermostdesc = self
         fielddescs = []
         fielddesc_by_name = {}
-        for name in self.TYPE._names:
-            FIELDTYPE = getattr(self.TYPE, name)
+        for name in TYPE._names:
+            FIELDTYPE = getattr(TYPE, name)
             if isinstance(FIELDTYPE, lltype.ContainerType):
                 if isinstance(FIELDTYPE, lltype.Array):
                     self.arrayfielddesc = ArrayFieldDesc(hrtyper, FIELDTYPE)
                     self.varsizealloctoken = RGenOp.varsizeAllocToken(TYPE)
                     continue
                 substructdesc = StructTypeDesc(hrtyper, FIELDTYPE)
-                assert name == self.TYPE._names[0], (
+                assert name == TYPE._names[0], (
                     "unsupported: inlined substructures not as first field")
                 fielddescs.extend(substructdesc.fielddescs)
                 self.firstsubstructdesc = substructdesc
@@ -95,182 +126,226 @@
                     desc = StructFieldDesc(hrtyper, self.PTRTYPE, name, index)
                     fielddescs.append(desc)
                 fielddesc_by_name[name] = desc
-        descs = unrolling_iterable(fielddescs) # Used in fill_into above
 
         self.fielddescs = fielddescs
         self.fielddesc_by_name = fielddesc_by_name
-        self.innermostdesc = innermostdesc
-
-        self.immutable = TYPE._hints.get('immutable', False)
-        self.noidentity = TYPE._hints.get('noidentity', False)
+        self.innermostdesc = innermostdesc        
 
-        self.null = self.PTRTYPE._defl()
-        self.gv_null = RGenOp.constPrebuiltGlobal(self.null)
+    def _define_fill_into(self):
+        descs = unrolling_iterable(self.fielddescs)
+        def fill_into(vablerti, s, base, vrti):
+            i = 0
+            for desc in descs:
+                v = vrti._read_field(vablerti, desc, base, i)
+                i += 1
+                setattr(s, desc.fieldname, v)
+                
+        self.fill_into = fill_into
 
+    def _define_materialize(self):
+        TYPE = self.TYPE
+        descs = unrolling_iterable(self.fielddescs)
+        
+        def materialize(rgenop, boxes):
+            s = lltype.malloc(TYPE)
+            i = 0
+            for desc in descs:
+                v = rvalue.ll_getvalue(boxes[i], desc.RESTYPE)
+                setattr(s, desc.fieldname, v)
+                i = i + 1
+            return rgenop.genconst(s)
 
-        if self.immutable and self.noidentity:
-            
-            def materialize(rgenop, boxes):
-                s = lltype.malloc(TYPE)
-                i = 0
-                for desc in descs:
-                    v = rvalue.ll_getvalue(boxes[i], desc.RESTYPE)
-                    setattr(s, desc.fieldname, v)
-                    i = i + 1
-                return rgenop.genconst(s)
+        self.materialize = materialize
+        
+    def getfielddesc(self, name):
+        try:
+            return self.fielddesc_by_name[name]
+        except KeyError:
+            return self.firstsubstructdesc.getfielddesc(name)
 
-            self.materialize = materialize
 
-        self.virtualizable = TYPE._hints.get('virtualizable', False)
-        if self.virtualizable:
-            self.VStructCls = VirtualizableStruct
-            self.base_desc = self.getfielddesc('vable_base')
-            self.info_desc = self.getfielddesc('vable_info')
-            self.access_desc = self.getfielddesc('vable_access')
-            ACCESS = TYPE.ACCESS
-            redirected_fields = ACCESS.redirected_fields
-            print self.PTRTYPE, redirected_fields
-            access = lltype.malloc(ACCESS, immortal=True)
-            self.gv_access = RGenOp.constPrebuiltGlobal(access)
-            TOPPTR = self.access_desc.PTRTYPE
-            s_structtype = annmodel.lltype_to_annotation(TOPPTR)
-            annhelper = hrtyper.annhelper
-            j = 0
-            def make_get_field(T, j):
-                def get_field(struc):
-                    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
-            
-            self.redirected_fielddescs = redirected_fieldescs = []
-            i = -1
-            my_redirected_names = []
-            self.my_redirected_getters = {}
-            for fielddesc in fielddescs:
-                i += 1
-                name = fielddesc.fieldname
-                if name not in redirected_fields:
-                    continue
-                redirected_fieldescs.append((fielddesc, i))
-                if fielddesc.PTRTYPE != self.PTRTYPE:
-                    continue
-                my_redirected_names.append(name)
-                get_field = make_get_field(fielddesc, j)
-                j += 1
-                s_lltype = annmodel.lltype_to_annotation(fielddesc.RESTYPE)
-                get_field_ptr = annhelper.delayedfunction(get_field,
-                                                          [s_structtype],
-                                                          s_lltype,
-                                                          needtype = True)
-                self.my_redirected_getters[name] = get_field_ptr
-
-            self.fill_access(access)
-
-            def access_is_null(struc):
-                assert not struc.vable_access
-            access_is_null_ptr = annhelper.delayedfunction(access_is_null,
-                                                           [s_structtype],
-                                                           annmodel.s_None,
-                                                           needtype = True)
-            self.gv_access_is_null_ptr = RGenOp.constPrebuiltGlobal(
-                                           access_is_null_ptr)
-            self.access_is_null_token =  RGenOp.sigToken(
-                                     lltype.typeOf(access_is_null_ptr).TO)
+    def factory(self):
+        vstruct = self.VirtualStructCls(self)
+        vstruct.content_boxes = [desc.makedefaultbox()
+                                 for desc in self.fielddescs]
+        box = rvalue.PtrRedBox(self.innermostdesc.ptrkind)
+        box.content = vstruct
+        vstruct.ownbox = box
+        return box
 
-            my_redirected_names = unrolling_iterable(my_redirected_names)
 
-            if TOPPTR == self.PTRTYPE:
-                _super_collect = None
-            else:
-                _super_collect = self.firstsubstructdesc._collect_residual_args
+def create(jitstate, typedesc):
+    return typedesc.factory()
 
-            def _collect_residual_args(v): 
-                if _super_collect is None:
-                    assert not v.vable_access  # xxx need to use access ?
-                    t = ()
-                else:
-                    t = _super_collect(v.super)
-                for name in my_redirected_names:
-                    t = t + (getattr(v, name),)
-                return t
-
-            self._collect_residual_args = _collect_residual_args
-
-            def collect_residual_args(v): 
-                t = (v,) + _collect_residual_args(v)
-                return t
+def create_varsize(jitstate, contdesc, sizebox):
+    gv_size = sizebox.getgenvar(jitstate)
+    alloctoken = contdesc.varsizealloctoken
+    genvar = jitstate.curbuilder.genop_malloc_varsize(alloctoken, gv_size)
+    return rvalue.PtrRedBox(contdesc.ptrkind, genvar)
+
+
+class VirtualizableStructTypeDesc(StructTypeDesc):
+
+    VirtualStructCls = None # patched later with VirtualizableStruct
+
+    __slots__ =  """redirected_fielddescs
+                    base_desc rti_desc access_desc
+                    gv_access
+                    gv_access_is_null_ptr access_is_null_token
+                    get_rti_ptr set_rti_ptr
+                 """.split()
 
-            self.collect_residual_args = collect_residual_args
-        else:
-            self.VStructCls = VirtualStruct
+    def __init__(self, hrtyper, TYPE):
+        RGenOp = hrtyper.RGenOp
+        StructTypeDesc.__init__(self, hrtyper, TYPE)
+        ACCESS = self.TYPE.ACCESS
+        redirected_fields = ACCESS.redirected_fields
+        self.redirected_fielddescs = []
+        i = 0
+        for fielddesc in self.fielddescs:
+            if fielddesc.fieldname in redirected_fields:
+                self.redirected_fielddescs.append((fielddesc, i))
+            i += 1
+        self.base_desc = self.getfielddesc('vable_base')
+        self.rti_desc = self.getfielddesc('vable_rti')
+        self.access_desc = self.getfielddesc('vable_access')
+        TOPPTR = self.access_desc.PTRTYPE
+        self.s_structtype = annmodel.lltype_to_annotation(TOPPTR)
 
-        # xxx
-        self.gv_make_vinfo_ptr = hrtyper.gv_make_vinfo_ptr
-        self.make_vinfo_token = hrtyper.make_vinfo_token
+        annhelper = hrtyper.annhelper
 
-        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
-
-        self.gv_vinfo_get_vinfo_ptr = hrtyper.gv_vinfo_get_vinfo_ptr
-        self.vinfo_get_vinfo_token = hrtyper.vinfo_get_vinfo_token
+        self.my_redirected_getters = {}
+        self.my_redirected_names = my_redirected_names = []
+        j = 0
+        for fielddesc, _  in self.redirected_fielddescs:
+            if fielddesc.PTRTYPE != self.PTRTYPE:
+                continue
+            my_redirected_names.append(fielddesc.fieldname)
+            self._define_get_field_ptr(hrtyper, fielddesc, j)
+            j += 1
+
+        self._define_getset_rti_ptrs(hrtyper)
+
+        access = lltype.malloc(ACCESS, immortal=True)
+        self._fill_access(access)
+        self.gv_access = RGenOp.constPrebuiltGlobal(access)
+
+        self._define_access_is_null(hrtyper)
+        self._define_collect_residual_args()
+
+
+    def _define_get_field_ptr(self, hrtyper, fielddesc, j):
+        annhelper = hrtyper.annhelper
+        def get_field(struc):
+            vable_rti = struc.vable_rti
+            vable_rti = cast_base_ptr_to_instance(rvirtualizable.VirtualRTI,
+                                                  vable_rti)
+            return vable_rti.read_field(fielddesc, struc.vable_base, j)
+
+        s_lltype = annmodel.lltype_to_annotation(fielddesc.RESTYPE)
+        get_field_ptr = annhelper.delayedfunction(get_field,
+                                                  [self.s_structtype],
+                                                  s_lltype,
+                                                  needtype = True)
+        self.my_redirected_getters[fielddesc.fieldname] = get_field_ptr        
 
-        self.gv_vinfo_get_shape_ptr = hrtyper.gv_vinfo_get_shape_ptr
-        self.vinfo_get_shape_token = hrtyper.vinfo_get_shape_token
+    def _define_getset_rti_ptrs(self, hrtyper):
+        RGenOp = hrtyper.RGenOp
+        annhelper = hrtyper.annhelper
+        TOPPTR = self.access_desc.PTRTYPE
+        
+        def get_rti(base, frameinfo, frameindex):
+            struc = RGenOp.read_frame_var(TOPPTR, base, frameinfo, frameindex)
+            return struc.vable_rti
+
+        def set_rti(base, frameinfo, frameindex, new_vable_rti):
+            struc = RGenOp.read_frame_var(TOPPTR, base, frameinfo, frameindex)
+            struc.vable_rti = new_vable_rti
+
+        s_addr = annmodel.SomeAddress()
+        s_frameinfo = annmodel.lltype_to_annotation(llmemory.GCREF)
+        s_frameindex = annmodel.SomeInteger()
+        from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR
+        s_vable_rti = annmodel.lltype_to_annotation(VABLERTIPTR)
+
+        self.get_rti_ptr = annhelper.delayedfunction(get_rti,
+                                [s_addr, s_frameinfo, s_frameindex],
+                                s_vable_rti, needtype=True)
+        self.set_rti_ptr = annhelper.delayedfunction(set_rti,
+                                [s_addr, s_frameinfo, s_frameindex,
+                                 s_vable_rti],
+                                annmodel.s_None, needtype=True)
 
-        self.gv_vinfo_read_forced_ptr = hrtyper.gv_vinfo_read_forced_ptr
-        self.vinfo_read_forced_token = hrtyper.vinfo_read_forced_token
 
-    def fill_access(self, access):
+    def _fill_access(self, access):
         firstsubstructdesc = self.firstsubstructdesc
         if (firstsubstructdesc is not None and 
-            firstsubstructdesc.virtualizable):
-            firstsubstructdesc.fill_access(access.parent)
+            isinstance(firstsubstructdesc, VirtualizableStructTypeDesc)):
+            firstsubstructdesc._fill_access(access.parent)
         for name, get_field_ptr in self.my_redirected_getters.iteritems():
             setattr(access, 'get_'+name, get_field_ptr)
-        
-    def getfielddesc(self, name):
-        try:
-            return self.fielddesc_by_name[name]
-        except KeyError:
-            return self.firstsubstructdesc.getfielddesc(name)
+            
+    def _define_collect_residual_args(self):
+        my_redirected_names = unrolling_iterable(self.my_redirected_names)
+        TOPPTR = self.access_desc.PTRTYPE
 
-    def factory(self):
-        vstruct = self.VStructCls(self)
-        vstruct.content_boxes = [desc.makedefaultbox()
-                                 for desc in self.fielddescs]
-        if self.virtualizable:
-            outsidebox = rvalue.PtrRedBox(self.innermostdesc.ptrkind,
-                                          self.gv_null)
-            vstruct.content_boxes.append(outsidebox)     
-        box = rvalue.PtrRedBox(self.innermostdesc.ptrkind)
-        box.content = vstruct
-        vstruct.ownbox = box
-        return box
+        if TOPPTR == self.PTRTYPE:
+            _super_collect = None
+        else:
+            _super_collect = self.firstsubstructdesc._collect_residual_args
 
-    def ll_factory(self):
-        # interface for rtyper.py, specialized for each 'self'
-        return self.factory()
+        def _collect_residual_args(v): 
+            if _super_collect is None:
+                assert not v.vable_access  # xxx need to use access ?
+                t = ()
+            else:
+                t = _super_collect(v.super)
+            for name in my_redirected_names:
+                t = t + (getattr(v, name),)
+            return t
 
-    def _freeze_(self):
-        return True
+        self._collect_residual_args = _collect_residual_args
+
+        def collect_residual_args(v): 
+            t = (v,) + _collect_residual_args(v)
+            return t
+
+        self.collect_residual_args = collect_residual_args
+
+    def _define_access_is_null(self, hrtyper):
+        RGenOp = hrtyper.RGenOp
+        annhelper = hrtyper.annhelper        
+        def access_is_null(struc):
+            assert not struc.vable_access
+        access_is_null_ptr = annhelper.delayedfunction(access_is_null,
+                                                       [self.s_structtype],
+                                                       annmodel.s_None,
+                                                       needtype = True)
+        self.gv_access_is_null_ptr = RGenOp.constPrebuiltGlobal(
+                                              access_is_null_ptr)
+        self.access_is_null_token =  RGenOp.sigToken(
+                                   lltype.typeOf(access_is_null_ptr).TO)
+
+
+    def factory(self):
+        vstructbox = StructTypeDesc.factory(self)
+        outsidebox = rvalue.PtrRedBox(self.innermostdesc.ptrkind,
+                                      self.gv_null)
+        content = vstructbox.content
+        assert isinstance(content, VirtualizableStruct)
+        content.content_boxes.append(outsidebox)             
+        return vstructbox
+
+# ____________________________________________________________
 
-    def compact_repr(self): # goes in ll helper names
-        return "Desc_%s" % (self.TYPE._short_name(),)
-    
 # XXX basic field descs for now
 class FieldDesc(object):
     __metaclass__ = cachedtype
     allow_void = False
     virtualizable = False
     gv_default = None
-    
+    canbevirtual = False
+
     def __init__(self, hrtyper, PTRTYPE, RESTYPE):
         RGenOp = hrtyper.RGenOp
         self.PTRTYPE = PTRTYPE
@@ -282,7 +357,10 @@
             T = RESTYPE.TO
             if hasattr(T, '_hints'):
                 self.virtualizable = T._hints.get('virtualizable', False)
-            if not isinstance(T, lltype.ContainerType):
+            if isinstance(T, lltype.ContainerType):
+                if isinstance(T, lltype.Struct) and T._arrayfld is None:
+                    self.canbevirtual = True
+            else:
                 T = None
         self.RESTYPE = RESTYPE
         self.ptrkind = RGenOp.kindToken(PTRTYPE)
@@ -298,10 +376,13 @@
 
         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 _get_fill_into(self):
+        return self.structdesc.fill_into
+    fill_into = property(_get_fill_into)
+
     def _freeze_(self):
         return True
 
@@ -469,7 +550,7 @@
         typedesc = self.typedesc
         contmemo = memo.containers
         assert self not in contmemo     # contmemo no longer used
-        result = contmemo[self] = typedesc.VStructCls(typedesc)
+        result = contmemo[self] = typedesc.VirtualStructCls(typedesc)
         result.content_boxes = [box.copy(memo)
                                 for box in self.content_boxes]
         result.ownbox = self.ownbox.copy(memo)
@@ -493,46 +574,37 @@
     def op_getsubstruct(self, jitstate, fielddesc):
         return self.ownbox
 
-    def make_vinfo(self, jitstate, memo):
+    def make_rti(self, jitstate, memo):
         try:
             return memo.containers[self]
         except KeyError:
             pass
         typedesc = self.typedesc
-        builder = jitstate.curbuilder
-        gv_bitmask = builder.rgenop.genconst(1<<memo.bitcount)
+        bitmask = 1 << memo.bitcount
         memo.bitcount += 1
-        gv_vinfo = builder.genop_call(typedesc.make_vinfo_token,
-                           typedesc.gv_make_vinfo_ptr,
-                           [gv_bitmask])
-        memo.containers[self] = gv_vinfo
-        vars_gv = []
+        rgenop = jitstate.curbuilder.rgenop
+        vrti = rvirtualizable.VirtualStructRTI(rgenop, bitmask)
+        memo.containers[self] = vrti
+
+        vars_gv = memo.framevars_gv
+        varindexes = vrti.varindexes
+        vrtis = vrti.vrtis
+        j = -1
         for box in self.content_boxes:
             if box.genvar:
+                varindexes.append(memo.frameindex)
+                memo.frameindex += 1
                 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)
+                varindexes.append(j)
                 assert isinstance(box, rvalue.PtrRedBox)
                 content = box.content
                 assert isinstance(content, VirtualStruct) # XXX for now
-                gv_vinfo1 = content.make_vinfo(jitstate, memo)
-                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
+                vrtis.append(content.make_rti(jitstate, memo))
+                j -= 1
+        return vrti
 
-
-    def reshape(self, jitstate, gv_vinfo, shapemask, memo):
+    def reshape(self, jitstate, shapemask, memo):
         if self in memo.containers:
             return
         typedesc = self.typedesc
@@ -540,68 +612,26 @@
         memo.containers[self] = None
         bitmask = 1<<memo.bitcount
         memo.bitcount += 1
+
         boxes = self.content_boxes
         if bitmask&shapemask:
-            gv_ptr = builder.genop_call(typedesc.vinfo_read_forced_token,
-                                        typedesc.gv_vinfo_read_forced_ptr,
-                                        [gv_vinfo])
+            gv_vable_rti = memo.gv_vable_rti
+            gv_bitkey = builder.rgenop.genconst(bitmask)
+            gv_ptr = builder.genop_call(typedesc.vrti_read_forced_token,
+                                        typedesc.gv_vrti_read_forced_ptr,
+                                        [gv_vable_rti, gv_bitkey])
             self.content_boxes = None
             self.ownbox.genvar = gv_ptr
             self.ownbox.content = None
 
-        for i in range(len(boxes)): # xxx duplication
-            box = boxes[i]
+        for box in boxes:
             if not box.genvar:
-                gv_vinfo1 = builder.genop_call(typedesc.vinfo_get_vinfo_token,
-                                               typedesc.gv_vinfo_get_vinfo_ptr,
-                                               [gv_vinfo, builder.rgenop.genconst(i)])
                 assert isinstance(box, rvalue.PtrRedBox)
                 content = box.content
                 assert isinstance(content, VirtualStruct) # xxx for now
-                content.reshape(jitstate, gv_vinfo1, shapemask, memo)        
+                content.reshape(jitstate, shapemask, memo)        
         
 
-
-class VirtualInfo(object):
-
-    def __init__(self, RGenOp, bitmask):
-        self.RGenOp = RGenOp
-        self.vinfos = []
-        self.s = lltype.nullptr(llmemory.GCREF.TO)
-        self.bitmask = bitmask
-        
-    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)
-        return vinfo.get_forced(fielddesc, base)
-    read_field._annspecialcase_ = "specialize:arg(1)"
-
-    def get_forced(self, fielddesc, base):
-        T = fielddesc.RESTYPE
-        assert isinstance(T, lltype.Ptr)
-        if self.s:
-            return lltype.cast_opaque_ptr(T, self.s)
-        S = T.TO
-        s = lltype.malloc(S)
-        self.s = lltype.cast_opaque_ptr(llmemory.GCREF, s)
-        fielddesc.fill_into(s, base, self)
-        return s
-    get_forced._annspecialcase_ = "specialize:arg(1)"
-
-    def read_forced(self):
-        assert self.s
-        return self.s
-    
-    def get_shape(self):
-        if self.s:
-            return self.bitmask
-        else:
-            return 0
-
 class VirtualizableStruct(VirtualStruct):
 
     def force_runtime_container(self, jitstate):
@@ -619,6 +649,7 @@
 
     def store_back(self, jitstate):
         typedesc = self.typedesc
+        assert isinstance(typedesc, VirtualizableStructTypeDesc)
         boxes = self.content_boxes
         gv_outside = boxes[-1].genvar
         for fielddesc, i in typedesc.redirected_fielddescs:
@@ -628,6 +659,7 @@
 
     def load_from(self, jitstate, gv_outside):
         typedesc = self.typedesc
+        assert isinstance(typedesc, VirtualizableStructTypeDesc)
         boxes = self.content_boxes
         boxes[-1].genvar = gv_outside
         builder = jitstate.curbuilder
@@ -638,98 +670,109 @@
             boxes[i] = fielddesc.generate_get(jitstate, gv_outside)
         jitstate.add_virtualizable(self.ownbox)
 
-    def prepare_for_residual_call(self, jitstate, gv_base, memo):
+    def make_rti(self, jitstate, memo):
         typedesc = self.typedesc
+        gv_outside = self.content_boxes[-1].genvar
+        if gv_outside is typedesc.gv_null:
+            return None
+        try:
+            return memo.containers[self]
+        except KeyError:
+            pass
+        assert isinstance(typedesc, VirtualizableStructTypeDesc)        
+        rgenop = jitstate.curbuilder.rgenop
+        vable_rti = rvirtualizable.VirtualizableRTI(rgenop, 0)
+        memo.containers[self] = vable_rti
+        
+        vars_gv = memo.framevars_gv
+        vars_gv.append(gv_outside)
+        getset_rti = (memo.frameindex,
+                      typedesc.get_rti_ptr,
+                      typedesc.set_rti_ptr)
+        memo.vable_getset_rtis.append(getset_rti)
+        memo.frameindex += 1
+        varindexes = vable_rti.varindexes
+        vrtis = vable_rti.vrtis
+        boxes = self.content_boxes
+        j = -1
+        for _, i in typedesc.redirected_fielddescs:
+            box = boxes[i]
+            if box.genvar:
+                varindexes.append(memo.frameindex)
+                memo.frameindex += 1
+                vars_gv.append(box.genvar)
+            else:
+                varindexes.append(j)
+                assert isinstance(box, rvalue.PtrRedBox)
+                content = box.content
+                assert isinstance(content, VirtualStruct) # XXX for now
+                vrtis.append(content.make_rti(jitstate, memo))
+                j -= 1
+        return vable_rti
+
+    def prepare_for_residual_call(self, jitstate, gv_base, vable_rti):
+        typedesc = self.typedesc
+        assert isinstance(typedesc, VirtualizableStructTypeDesc)        
         builder = jitstate.curbuilder
         gv_outside = self.content_boxes[-1].genvar
-        if gv_outside is not typedesc.gv_null:
-            if self in memo.containers:
-                return
-            base_desc = typedesc.base_desc
-            base_token = base_desc.fieldtoken
-            builder.genop_setfield(base_token, gv_outside, gv_base)
-            # xxx aliasing
-            boxes = self.content_boxes
-            vars_gv = []
-            n = len(boxes)
-            gv_zeromask = builder.rgenop.genconst(0)
-            gv_vinfo = builder.genop_call(typedesc.make_vinfo_token,
-                               typedesc.gv_make_vinfo_ptr,
-                               [gv_zeromask])
-            memo.containers[self] = gv_vinfo
-            
-            for _, i in typedesc.redirected_fielddescs:
-                box = boxes[i]
-                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, memo)
-                    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(access_token, gv_outside,
-                                   typedesc.gv_access)
+        base_desc = typedesc.base_desc
+        base_token = base_desc.fieldtoken
+        builder.genop_setfield(base_token, gv_outside, gv_base)
+        vable_rti_ptr = cast_instance_to_base_ptr(vable_rti)
+        gv_vable_rti = builder.rgenop.genconst(vable_rti_ptr)
+        rti_token = typedesc.rti_desc.fieldtoken
+        builder.genop_setfield(rti_token, gv_outside, gv_vable_rti)
+        access_token = typedesc.access_desc.fieldtoken
+        builder.genop_setfield(access_token, gv_outside, typedesc.gv_access)
 
-    def after_residual_call(self, jitstate):
+    def after_residual_call(self, jitstate, gv_shape):
         typedesc = self.typedesc
         builder = jitstate.curbuilder
         gv_outside = self.content_boxes[-1].genvar
-        if gv_outside is not typedesc.gv_null:
-            base_desc = typedesc.base_desc
-            base_token = typedesc.base_desc.fieldtoken
-            info_token = typedesc.info_desc.fieldtoken
-            access_token = typedesc.access_desc.fieldtoken
-            gv_base_null = typedesc.base_desc.gv_default
-            gv_access_null = typedesc.access_desc.gv_default
-            builder.genop_setfield(base_token, gv_outside, gv_base_null)
-            builder.genop_setfield(access_token, gv_outside, gv_access_null)
+        if gv_outside is typedesc.gv_null:
+            return gv_shape
+        assert isinstance(typedesc, VirtualizableStructTypeDesc)
+        access_token = typedesc.access_desc.fieldtoken            
+        gv_access_null = typedesc.access_desc.gv_default
+        builder.genop_setfield(access_token, gv_outside, gv_access_null)
+        if gv_shape is None:
+            rti_token = typedesc.rti_desc.fieldtoken                
+            gv_vable_rti = builder.genop_getfield(rti_token, gv_outside)
+            tok = typedesc.vrti_get_global_shape_token
+            fn = typedesc.gv_vrti_get_global_shape_ptr
+            gv_shape = builder.genop_call(tok, fn, [gv_vable_rti])
+        return gv_shape
 
-    def reshape(self, jitstate, gv_vinfo, shapemask, memo):
+
+    def reshape(self, jitstate, shapemask, memo):
         typedesc = self.typedesc
         builder = jitstate.curbuilder
         gv_outside = self.content_boxes[-1].genvar
-        if gv_outside is not typedesc.gv_null:
-            info_desc = typedesc.info_desc
-            if self in memo.containers:
-                return
-            # xxx we can avoid traversing the full tree
-            memo.containers[self] = None
+        if gv_outside is typedesc.gv_null:
+            return
+        if self in memo.containers:
+            return
+        memo.containers[self] = None
+        assert isinstance(typedesc, VirtualizableStructTypeDesc)
+        gv_vable_rti = memo.gv_vable_rti
+        if gv_vable_rti is None:
+            rti_token = typedesc.rti_desc.fieldtoken
+            gv_vable_rti = builder.genop_getfield(rti_token, gv_outside)
+            memo.gv_vable_rti = gv_vable_rti
+        boxes = self.content_boxes
+        for _, i in typedesc.redirected_fielddescs:
+            box = boxes[i]
+            if not box.genvar:
+                assert isinstance(box, rvalue.PtrRedBox)
+                content = box.content
+                assert isinstance(content, VirtualStruct) # xxx for now
+                content.reshape(jitstate, shapemask, memo)
+
+# patching VirtualStructCls
+StructTypeDesc.VirtualStructCls = VirtualStruct
+VirtualizableStructTypeDesc.VirtualStructCls = VirtualizableStruct
+
 
-            assert gv_vinfo is None # xxx
-            info_token = info_desc.fieldtoken
-            gv_vinfo = builder.genop_getfield(info_token, gv_outside)            
-            boxes = self.content_boxes
-            j = 0
-            for _, i in typedesc.redirected_fielddescs:
-                box = boxes[i]
-                if not box.genvar:
-                    gv_vinfo1 = builder.genop_call(typedesc.vinfo_get_vinfo_token,
-                                                   typedesc.gv_vinfo_get_vinfo_ptr,
-                                                   [gv_vinfo, builder.rgenop.genconst(j)])
-                    assert isinstance(box, rvalue.PtrRedBox)
-                    content = box.content
-                    assert isinstance(content, VirtualStruct) # xxx for now
-                    content.reshape(jitstate, gv_vinfo1, shapemask, memo)
-                j += 1
-                    
 # ____________________________________________________________
 
 class FrozenPartialDataStruct(AbstractContainer):

Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Wed Jan 24 23:33:53 2007
@@ -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, rcontainer
+from pypy.jit.timeshifter import rvalue, rcontainer, rvirtualizable
 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
@@ -901,49 +901,58 @@
     def prepare_for_residual_call(self):
         virtualizables = self.virtualizables
         if virtualizables:
-            builder = self.curbuilder            
-            gv_base = builder.get_frame_base()
+            builder = self.curbuilder
             memo = rvalue.make_vinfo_memo()
             memo.bitcount = 0
+            memo.frameindex = 0
+            memo.framevars_gv = []
+            memo.vable_getset_rtis = []
+            vable_rtis = []
             for virtualizable_box in virtualizables:
                 content = virtualizable_box.content
                 assert isinstance(content, rcontainer.VirtualizableStruct)
-                content.prepare_for_residual_call(self, gv_base, memo)
+                vable_rtis.append(content.make_rti(self, memo))
             assert memo.bitcount < 32
-            self.make_vinfo_memo = memo
+            gv_base = builder.genop_get_frame_base()
+            frameinfo = builder.get_frame_info(memo.framevars_gv)
+            vable_getset_rtis = memo.vable_getset_rtis
+            for i in range(len(virtualizables)):
+                vable_rti = vable_rtis[i]
+                if vable_rti is None:
+                    continue
+                assert isinstance(vable_rti, rvirtualizable.VirtualizableRTI)
+                vable_rti.frameinfo = frameinfo
+                vable_rti.vable_getset_rtis = vable_getset_rtis
+                virtualizable_box = virtualizables[i]
+                content = virtualizable_box.content
+                assert isinstance(content, rcontainer.VirtualizableStruct)
+                content.prepare_for_residual_call(self, gv_base, vable_rti)
                 
     def after_residual_call(self):
         virtualizables = self.virtualizables
         builder = self.curbuilder
-        gv_shape = builder.rgenop.genconst(0)
+        gv_shape = None
         if virtualizables:
             for virtualizable_box in virtualizables:
                 content = virtualizable_box.content
                 assert isinstance(content, rcontainer.VirtualizableStruct)
-                content.after_residual_call(self)
-            memo = self.make_vinfo_memo
-            self.make_vinfo_memo = None
-            for container, gv_vinfo in memo.containers.iteritems():
-                if isinstance(container, rcontainer.VirtualizableStruct):
-                    continue
-                assert isinstance(container, rcontainer.VirtualStruct)
-                typedesc = container.typedesc # xxx
-                gv_new_shape = builder.genop_call(typedesc.vinfo_get_shape_token,
-                                                  typedesc.gv_vinfo_get_shape_ptr,
-                                                  [gv_vinfo])
-                gv_shape = builder.genop2('int_or', gv_shape, gv_new_shape)
-        return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Signed), gv_shape)
+                gv_shape = content.after_residual_call(self, gv_shape)
+        if gv_shape is None:
+            gv_shape = builder.rgenop.genconst(0)
+        return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Signed),
+                                gv_shape)
 
     def reshape(self, shapemask):
         virtualizables = self.virtualizables
         builder = self.curbuilder
         if virtualizables and shapemask:
             memo = rvalue.make_vinfo_memo()
-            memo.bitcount = 0            
+            memo.bitcount = 0
+            memo.gv_vable_rti = None
             for virtualizable_box in virtualizables:
                 content = virtualizable_box.content
                 assert isinstance(content, rcontainer.VirtualizableStruct)
-                content.reshape(self, None, shapemask, memo) # xxx gv_vinfo argument
+                content.reshape(self, shapemask, memo)
                 
     def freeze(self, memo):
         result = FrozenJITState()
@@ -967,7 +976,7 @@
             assert isinstance(new_virtualizable_box, rvalue.PtrRedBox)
             self.virtualizables[i] = new_virtualizable_box
             
-    def get_locals_gv(self): # xxx
+    def get_locals_gv(self):
         # get all the genvars that are "alive", i.e. stored in the JITState
         # or the VirtualFrames
         incoming = []

Added: pypy/dist/pypy/jit/timeshifter/rvirtualizable.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/timeshifter/rvirtualizable.py	Wed Jan 24 23:33:53 2007
@@ -0,0 +1,91 @@
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+
+class VirtualRTI(object):
+    __slots__ = 'rgenop varindexes vrtis bitmask'.split()
+    def __init__(self, rgenop, bitmask):
+        self.rgenop = rgenop
+        self.varindexes = []
+        self.vrtis = []
+        self.bitmask = bitmask
+
+    def _read_field(self, vablerti, fielddesc, base, index):
+        T = fielddesc.RESTYPE
+        frameindex = self.varindexes[index]
+        if frameindex >= 0:
+            return vablerti.read_frame_var(T, base, frameindex)
+        index = -frameindex-1
+        assert index >= 0
+        vinfo = self.vrtis[index]
+        assert isinstance(T, lltype.Ptr)
+        assert fielddesc.canbevirtual
+        return vinfo.get_forced(vablerti, fielddesc, base)
+    _read_field._annspecialcase_ = "specialize:arg(2)"
+
+    def get_forced(self, vablerti, fielddesc, base):
+        T = fielddesc.RESTYPE
+        assert isinstance(T, lltype.Ptr)
+        forcestate = vablerti.getforcestate(base)
+        bitmask = self.bitmask
+        if bitmask in forcestate:
+            s = forcestate[bitmask] 
+            return lltype.cast_opaque_ptr(T, s)
+        S = T.TO
+        s = lltype.malloc(S)
+        forcestate[bitmask] = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+        fielddesc.fill_into(vablerti, s, base, self)
+        return s
+    get_forced._annspecialcase_ = "specialize:arg(2)"
+
+class VirtualizableRTI(VirtualRTI):
+    __slots__ = "frameinfo vable_getset_rtis".split()
+            
+    def get_global_shape(self):
+        return 0
+
+    def read_frame_var(self, T, base, frameindex):
+        return self.rgenop.read_frame_var(T, base, self.frameinfo, frameindex)
+    read_frame_var._annspecialcase_ = "specialize:arg(1)"
+
+    def read_field(self, fielddesc, base, index):
+        return self._read_field(self, fielddesc, base, index)
+    read_field._annspecialcase_ = "specialize:arg(1)"
+
+    def getforcestate(self, base):
+        state = {}
+        for i, get, set in self.vable_getset_rtis:
+            p = get(base, self.frameinfo, i)
+            vablerti = cast_base_ptr_to_instance(VirtualizableRTI, p)
+            # xxx see below
+            wforcestate = WithForcedStateVirtualizableRTI(vablerti, state) 
+            p = cast_instance_to_base_ptr(wforcestate)
+            set(base, self.frameinfo, i, p)
+        return state
+
+class WithForcedStateVirtualizableRTI(VirtualizableRTI):
+    __slots__ = "state".split()
+
+    def __init__(self, vablerti, state):
+        self.rgenop = vablerti.rgenop
+        self.varindexes = vablerti.varindexes
+        self.vrtis = vablerti.vrtis # xxx what if these contain virtualizables 
+        self.frameinfo = vablerti.frameinfo
+        self.bitmask = vablerti.bitmask
+        self.state = state
+        
+    def getforcestate(self, base):
+        return self.state
+
+    def get_global_shape(self):
+        bitmask = 0
+        for bitkey in self.state:
+            bitmask |= bitkey
+        return bitmask
+
+    def read_forced(self, bitkey):
+        return self.state[bitkey]
+
+
+class VirtualStructRTI(VirtualRTI):
+    pass

Modified: pypy/dist/pypy/jit/timeshifter/test/test_portal.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_portal.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_portal.py	Wed Jan 24 23:33:53 2007
@@ -10,6 +10,7 @@
 
 import py.test
 
+
 class PortalTest(object):
     from pypy.jit.codegen.llgraph.rgenop import RGenOp
 
@@ -108,6 +109,17 @@
         for opname, count in counts.items():
             assert self.insns.get(opname, 0) == count
 
+
+    def count_direct_calls(self):
+        residual_graph = self.get_residual_graph()
+        calls = {}
+        for block in residual_graph.iterblocks():
+            for op in block.operations:
+                if op.opname == 'direct_call':
+                    graph = getattr(op.args[0].value._obj, 'graph', None)
+                    calls[graph] = calls.get(graph, 0) + 1
+        return calls
+        
 class TestPortal(PortalTest):
             
     def test_simple(self):

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	Wed Jan 24 23:33:53 2007
@@ -1,7 +1,7 @@
 from pypy.jit.hintannotator.annotator import HintAnnotatorPolicy
 from pypy.jit.timeshifter.test.test_portal import PortalTest, P_OOPSPEC
 from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.jit.timeshifter.rcontainer import VABLEINFOPTR
+from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR
 from pypy.rlib.objectmodel import hint
 import py
 
@@ -58,7 +58,7 @@
 
 XY.become(lltype.GcStruct('xy',
                           ('vable_base', llmemory.Address),
-                          ('vable_info', VABLEINFOPTR),
+                          ('vable_rti', VABLERTIPTR),
                           ('vable_access', lltype.Ptr(XY_ACCESS)),
                           ('x', lltype.Signed),
                           ('y', lltype.Signed),
@@ -74,7 +74,7 @@
 
 XP.become(lltype.GcStruct('xp',
                           ('vable_base', llmemory.Address),
-                          ('vable_info', VABLEINFOPTR),                     
+                          ('vable_rti', VABLERTIPTR),                     
                           ('vable_access', lltype.Ptr(XP_ACCESS)),
                           ('x', lltype.Signed),
                           ('p', PS),
@@ -99,7 +99,7 @@
 
 PQ.become(lltype.GcStruct('pq',
                           ('vable_base', llmemory.Address),
-                          ('vable_info', VABLEINFOPTR),                     
+                          ('vable_rti', VABLERTIPTR),                     
                           ('vable_access', lltype.Ptr(PQ_ACCESS)),
                           ('p', PS),
                           ('q', PS),
@@ -114,14 +114,18 @@
 
 
 
-class StopAtGPolicy(HintAnnotatorPolicy):
-    def __init__(self):
+class StopAtXPolicy(HintAnnotatorPolicy):
+    def __init__(self, *funcs):
         HintAnnotatorPolicy.__init__(self, novirtualcontainer=True,
                                      oopspec=True)
+        self.funcs = funcs
 
     def look_inside_graph(self, graph):
-        if graph.name == 'g':
-            return False
+        try:
+            if graph.func in self.funcs:
+                return False
+        except AttributeError:
+            pass
         return True
 
 
@@ -434,8 +438,12 @@
             y = xy_get_y(xy)
             newy = 2*y
             xy_set_y(xy, newy)
+            if y:
+                dummy = 0
+            else:
+                dummy = 1
             g(e)
-            return 0
+            return dummy
             
         def main(x, y):
             xy = lltype.malloc(XY)
@@ -448,7 +456,7 @@
             return e.w
 
         res = self.timeshift_from_portal(main, f, [0, 21],
-                                         policy=StopAtGPolicy())
+                                         policy=StopAtXPolicy(g))
         assert res == 42
 
     def test_residual_red_call(self):
@@ -477,7 +485,7 @@
             return v+e.w
 
         res = self.timeshift_from_portal(main, f, [2, 20],
-                                         policy=StopAtGPolicy())
+                                         policy=StopAtXPolicy(g))
         assert res == 42
 
     def test_force_in_residual_red_call(self):
@@ -515,7 +523,7 @@
             return e.w
 
         res = self.timeshift_from_portal(main, f, [2, 20, 10],
-                                         policy=StopAtGPolicy())
+                                         policy=StopAtXPolicy(g))
         assert res == 42
 
     def test_force_multiple_reads_residual_red_call(self):
@@ -550,7 +558,7 @@
             return e.w
 
         res = self.timeshift_from_portal(main, f, [2, 20, 10],
-                                         policy=StopAtGPolicy())
+                                         policy=StopAtXPolicy(g))
         assert res == 1
 
 
@@ -588,7 +596,7 @@
             return e.w
 
         res = self.timeshift_from_portal(main, f, [2, 20, 10],
-                                         policy=StopAtGPolicy())
+                                         policy=StopAtXPolicy(g))
         assert res == 1
 
     def test_force_aliased_residual_red_call(self):
@@ -621,7 +629,7 @@
             return e.w
 
         res = self.timeshift_from_portal(main, f, [2, 20, 10],
-                                         policy=StopAtGPolicy())
+                                         policy=StopAtXPolicy(g))
         assert res == 1
 
     def test_force_in_residual_red_call_with_more_use(self):
@@ -659,7 +667,7 @@
             return e.w + xp.p.a + xp.p.b
 
         res = self.timeshift_from_portal(main, f, [2, 20, 10],
-                                         policy=StopAtGPolicy())
+                                         policy=StopAtXPolicy(g))
         assert res == 42 + 140 + 10
 
 
@@ -710,3 +718,55 @@
         res = self.timeshift_from_portal(main, f, [20, 22], policy=P_OOPSPEC)
         assert res == 42
         self.check_insns(getfield=0)
+
+    def test_simple_interpreter_with_frame(self):
+        class Log:
+            acc = 0
+        log = Log()
+        class Frame(object):
+            _virtualizable_ = True
+            def __init__(self, code, acc, y):
+                self.code = code
+                self.pc = 0
+                self.acc = acc
+                self.y = y
+
+            def run(self):
+                self.plus_minus(self.code)
+                return self.acc
+
+            def plus_minus(self, s):
+                n = len(s)
+                pc = 0
+                while pc < n:
+                    hint(None, global_merge_point=True)
+                    self.pc = pc
+                    op = s[pc]
+                    op = hint(op, concrete=True)
+                    if op == '+':
+                        self.acc += self.y
+                    elif op == '-':
+                        self.acc -= self.y
+                    elif op == 'd':
+                        self.debug()
+                    pc += 1
+                return 0
+
+            def debug(self):
+                log.acc = self.acc
+            
+        def main(x, y):
+            code = '+d+-+'
+            f = Frame(code, x, y)
+            return f.run(), log.acc
+        
+        res = self.timeshift_from_portal(main, Frame.plus_minus.im_func,
+                            [0, 2],
+                            policy=StopAtXPolicy(Frame.debug.im_func))
+
+        assert res.item0 == 4
+        assert res.item1 == 2
+        calls = self.count_direct_calls()
+        call_count = sum([count for graph, count in calls.iteritems()
+                          if not graph.name.startswith('rpyexc_')])
+        assert call_count == 3

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Wed Jan 24 23:33:53 2007
@@ -865,11 +865,9 @@
     def op_get_frame_base(self):
         return llmemory.fakeaddress(self)
 
-    def op_get_frame_info(self, *vars):
-        return lltype.opaqueptr(llmemory.GCREF.TO,
-                                'frame_info',
-                                vars=vars)
-    op_get_frame_info.specialform = True
+    def op_frame_info(self, *vars):
+        pass
+    op_frame_info.specialform = True
  
     #Operation of ootype
 

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Wed Jan 24 23:33:53 2007
@@ -431,7 +431,7 @@
 
     # _____ read frame var support ___
     'get_frame_base':       LLOp(),
-    'get_frame_info':       LLOp(),
+    'frame_info':           LLOp(),
 }
 # ***** Run test_lloperation after changes. *****
 

Modified: pypy/dist/pypy/rpython/lltypesystem/rvirtualizable.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rvirtualizable.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rvirtualizable.py	Wed Jan 24 23:33:53 2007
@@ -4,7 +4,7 @@
 from pypy.rpython.lltypesystem.rclass import OBJECTPTR, InstanceRepr
 from pypy.rpython.annlowlevel import cachedtype
 
-VABLEINFOPTR = OBJECTPTR
+VABLERTIPTR = OBJECTPTR
 
 class VirtualizableInstanceRepr(InstanceRepr):
 
@@ -26,7 +26,7 @@
         ACCESS = lltype.ForwardReference()
         if self.top_of_virtualizable_hierarchy:
             llfields.append(('vable_base',   llmemory.Address))
-            llfields.append(('vable_info',   VABLEINFOPTR))
+            llfields.append(('vable_rti',   VABLERTIPTR))
             llfields.append(('vable_access', lltype.Ptr(ACCESS)))
         InstanceRepr._setup_repr(self, llfields,
                                  hints = {'virtualizable': True},
@@ -71,7 +71,7 @@
                 vinst = llops.genop('cast_pointer', [vinst], resulttype=self)
             for name, llvalue in (('access', lltype.nullptr(self.ACCESS)),
                                   ('base',   llmemory.NULL),
-                                  ('info',   lltype.nullptr(VABLEINFOPTR.TO))):
+                                  ('rti',    lltype.nullptr(VABLERTIPTR.TO))):
                 cname = inputconst(lltype.Void, 'vable_'+name)
                 vvalue = inputconst(lltype.typeOf(llvalue), llvalue)
                 llops.genop('setfield', [vinst, cname, vvalue])



More information about the Pypy-commit mailing list