[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