[pypy-svn] r36743 - in pypy/dist/pypy/jit/timeshifter: . test
ac at codespeak.net
ac at codespeak.net
Sun Jan 14 17:24:16 CET 2007
Author: ac
Date: Sun Jan 14 17:24:15 2007
New Revision: 36743
Modified:
pypy/dist/pypy/jit/timeshifter/hrtyper.py
pypy/dist/pypy/jit/timeshifter/rcontainer.py
pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py
Log:
(pedronis, arre) Small support for lazy forcing of virtual structures in
virtualizable structures. Much more to be fixed such as aliasing and doing
the right thing after a residual call that resulted in forcing of one or more
structures.
Modified: pypy/dist/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/hrtyper.py (original)
+++ pypy/dist/pypy/jit/timeshifter/hrtyper.py Sun Jan 14 17:24:15 2007
@@ -8,6 +8,8 @@
from pypy.annotation import listdef
from pypy.annotation.pairtype import pair, pairtype
from pypy.rpython.annlowlevel import PseudoHighLevelCallable
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
from pypy.rlib.unroll import unrolling_iterable
from pypy.rpython import annlowlevel
from pypy.rpython.rtyper import RPythonTyper, LowLevelOpList, TyperError
@@ -154,6 +156,68 @@
self.v_queue = varoftype(self.r_Queue.lowleveltype, 'queue')
#self.void_red_repr = VoidRedRepr(self)
+ annhelper = self.annhelper
+ def make_vinfo():
+ vinfo = rcontainer.VirtualInfo(RGenOp)
+ return cast_instance_to_base_ptr(vinfo)
+
+ s_vableinfoptr = annmodel.lltype_to_annotation(rcontainer.VABLEINFOPTR)
+ s_info = annmodel.lltype_to_annotation(llmemory.GCREF)
+
+ make_vinfo_ptr = annhelper.delayedfunction(make_vinfo, [],
+ s_vableinfoptr,
+ needtype=True)
+ self.gv_make_vinfo_ptr = RGenOp.constPrebuiltGlobal(make_vinfo_ptr)
+ self.make_vinfo_token = RGenOp.sigToken(
+ lltype.typeOf(make_vinfo_ptr).TO)
+
+ def vinfo_set_info(vinfo, info):
+ vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
+ vinfo)
+ vinfo.info = info
+
+ vinfo_set_info_ptr = annhelper.delayedfunction(vinfo_set_info,
+ [s_vableinfoptr, s_info],
+ annmodel.s_None,
+ needtype=True)
+ self.gv_vinfo_set_info_ptr = RGenOp.constPrebuiltGlobal(
+ vinfo_set_info_ptr)
+ self.vinfo_set_info_token = RGenOp.sigToken(
+ lltype.typeOf(vinfo_set_info_ptr).TO)
+
+
+ def vinfo_append_vinfo(vinfo, vinfo1):
+ vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
+ vinfo)
+ vinfo1 = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
+ vinfo1)
+ vinfo.vinfos.append(vinfo1)
+
+ vinfo_append_vinfo_ptr = annhelper.delayedfunction(vinfo_append_vinfo,
+ [s_vableinfoptr, s_vableinfoptr],
+ annmodel.s_None,
+ needtype=True)
+ self.gv_vinfo_append_vinfo_ptr = RGenOp.constPrebuiltGlobal(
+ vinfo_append_vinfo_ptr)
+ self.vinfo_append_vinfo_token = RGenOp.sigToken(
+ lltype.typeOf(vinfo_append_vinfo_ptr).TO)
+
+ def vinfo_skip_vinfo(vinfo):
+ vinfo = cast_base_ptr_to_instance(rcontainer.VirtualInfo,
+ vinfo)
+ vinfo.vinfos.append(None)
+
+ vinfo_skip_vinfo_ptr = annhelper.delayedfunction(vinfo_skip_vinfo,
+ [s_vableinfoptr],
+ annmodel.s_None,
+ needtype=True)
+ self.gv_vinfo_skip_vinfo_ptr = RGenOp.constPrebuiltGlobal(
+ vinfo_skip_vinfo_ptr)
+ self.vinfo_skip_vinfo_token = RGenOp.sigToken(
+ lltype.typeOf(vinfo_skip_vinfo_ptr).TO)
+
+
+
def specialize(self, origportalgraph=None, view=False):
"""
Driver for running the timeshifter.
Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Sun Jan 14 17:24:15 2007
@@ -1,12 +1,13 @@
import operator
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.annlowlevel import cachedtype
+from pypy.rpython.annlowlevel import cachedtype, cast_base_ptr_to_instance
+from pypy.rpython.annlowlevel import base_ptr_lltype, cast_instance_to_base_ptr
from pypy.jit.timeshifter import rvalue
from pypy.rlib.unroll import unrolling_iterable
from pypy.annotation import model as annmodel
-from pypy.rpython.lltypesystem import lloperation
+from pypy.rpython.lltypesystem import lloperation, llmemory
debug_print = lloperation.llop.debug_print
debug_pdb = lloperation.llop.debug_pdb
@@ -40,6 +41,7 @@
VABLEFIELDS = ('vable_base', 'vable_info', 'vable_access')
NVABLEFIELDS = len(VABLEFIELDS)
+VABLEINFOPTR = base_ptr_lltype()
class StructTypeDesc(object):
__metaclass__ = cachedtype
@@ -108,14 +110,16 @@
j = 0
def make_get_field(T, j):
def get_field(struc):
- return RGenOp.read_frame_var(T, struc.vable_base,
- struc.vable_info,
- j)
+ vable_info = struc.vable_info
+ vable_info = cast_base_ptr_to_instance(VirtualInfo,
+ vable_info)
+ return vable_info.read_field(fielddesc,
+ struc.vable_base, j)
return get_field
s_structtype = annmodel.lltype_to_annotation(self.PTRTYPE)
for i in range(NVABLEFIELDS, len(fielddescs)):
fielddesc = fielddescs[i]
- get_field = make_get_field(fielddesc.RESTYPE, j)
+ get_field = make_get_field(fielddesc, j)
j += 1
s_lltype = annmodel.lltype_to_annotation(fielddesc.RESTYPE)
get_field_ptr = annhelper.delayedfunction(get_field,
@@ -126,9 +130,10 @@
setattr(access, 'get_'+name, get_field_ptr)
else:
self.VStructCls = VirtualStruct
-
+
+ descs = unrolling_iterable(fielddescs)
if self.immutable and self.noidentity:
- descs = unrolling_iterable(fielddescs)
+
def materialize(rgenop, boxes):
s = lltype.malloc(TYPE)
i = 0
@@ -139,7 +144,25 @@
return rgenop.genconst(s)
self.materialize = materialize
-
+
+ def fill_into(s, base, vinfo):
+ i = 0
+ for desc in descs:
+ v = vinfo.read_field(desc, base, i)
+ i += 1
+ setattr(s, desc.fieldname, v)
+ self.fill_into = fill_into
+
+ self.gv_make_vinfo_ptr = hrtyper.gv_make_vinfo_ptr
+ self.make_vinfo_token = hrtyper.make_vinfo_token
+
+ self.gv_vinfo_set_info_ptr = hrtyper.gv_vinfo_set_info_ptr
+ self.vinfo_set_info_token = hrtyper.vinfo_set_info_token
+ self.gv_vinfo_append_vinfo_ptr = hrtyper.gv_vinfo_append_vinfo_ptr
+ self.vinfo_append_vinfo_token = hrtyper.vinfo_append_vinfo_token
+ self.gv_vinfo_skip_vinfo_ptr = hrtyper.gv_vinfo_skip_vinfo_ptr
+ self.vinfo_skip_vinfo_token = hrtyper.vinfo_skip_vinfo_token
+
def getfielddesc(self, name):
return self.fielddesc_by_name[name]
@@ -172,16 +195,20 @@
allow_void = False
virtualizable = False
gv_default = None
-
+
def __init__(self, hrtyper, PTRTYPE, RESTYPE):
RGenOp = hrtyper.RGenOp
self.PTRTYPE = PTRTYPE
+ T = None
if isinstance(RESTYPE, lltype.ContainerType):
+ T = RESTYPE
RESTYPE = lltype.Ptr(RESTYPE)
elif isinstance(RESTYPE, lltype.Ptr):
T = RESTYPE.TO
if hasattr(T, '_hints'):
self.virtualizable = T._hints.get('virtualizable', False)
+ if not isinstance(T, lltype.ContainerType):
+ T = None
self.RESTYPE = RESTYPE
self.ptrkind = RGenOp.kindToken(PTRTYPE)
self.kind = RGenOp.kindToken(RESTYPE)
@@ -190,9 +217,14 @@
if RESTYPE is lltype.Void and self.allow_void:
pass # no redboxcls at all
elif self.virtualizable:
- self.structdesc = StructTypeDesc(hrtyper, T)
+ pass
else:
self.redboxcls = rvalue.ll_redboxcls(RESTYPE)
+
+ if T is not None and isinstance(T, lltype.Struct): # xxx for now
+ self.structdesc = StructTypeDesc(hrtyper, T)
+ self.fill_into = self.structdesc.fill_into
+
self.immutable = PTRTYPE.TO._hints.get('immutable', False)
def _freeze_(self):
@@ -212,6 +244,7 @@
return structbox
return self.redboxcls(self.kind, gvar)
+
class NamedFieldDesc(FieldDesc):
def __init__(self, hrtyper, PTRTYPE, name):
@@ -390,6 +423,60 @@
def op_getsubstruct(self, jitstate, fielddesc):
return self.ownbox
+ def make_vinfo(self, jitstate):
+ # xxx aliasing
+ typedesc = self.typedesc
+ assert typedesc is not None
+ builder = jitstate.curbuilder
+ gv_vinfo = builder.genop_call(typedesc.make_vinfo_token,
+ typedesc.gv_make_vinfo_ptr,
+ [])
+ vars_gv = []
+ for box in self.content_boxes:
+ if box.genvar:
+ vars_gv.append(box.genvar)
+ builder.genop_call(typedesc.vinfo_skip_vinfo_token,
+ typedesc.gv_vinfo_skip_vinfo_ptr,
+ [gv_vinfo])
+
+ else:
+ vars_gv.append(None)
+ assert isinstance(box, rvalue.PtrRedBox)
+ content = box.content
+ assert isinstance(content, VirtualStruct) # XXX for now
+ gv_vinfo1 = content.make_vinfo(jitstate)
+ builder.genop_call(typedesc.vinfo_append_vinfo_token,
+ typedesc.gv_vinfo_append_vinfo_ptr,
+ [gv_vinfo, gv_vinfo1])
+
+
+ gv_info = builder.get_frame_info(vars_gv)
+ builder.genop_call(typedesc.vinfo_set_info_token,
+ typedesc.gv_vinfo_set_info_ptr,
+ [gv_vinfo, gv_info])
+ return gv_vinfo
+
+class VirtualInfo(object):
+
+ def __init__(self, RGenOp):
+ self.RGenOp = RGenOp
+ self.vinfos = []
+
+ def read_field(self, fielddesc, base, index):
+ T = fielddesc.RESTYPE
+ vinfo = self.vinfos[index]
+ if vinfo is None:
+ return self.RGenOp.read_frame_var(T, base,
+ self.info, index)
+ assert isinstance(T, lltype.Ptr)
+ S = T.TO
+ s = lltype.malloc(S)
+ # xxx remember that s has been forced
+ fielddesc.fill_into(s, base, vinfo)
+ return s
+
+ read_field._annspecialcase_ = "specialize:arg(1)"
+
class VirtualizableStruct(VirtualStruct):
def force_runtime_container(self, jitstate):
@@ -434,19 +521,42 @@
assert base_desc is not None
base_token = base_desc.fieldtoken
builder.genop_setfield(base_token, gv_outside, gv_base)
- # xxx recursive and virtual stuff
+ # xxx aliasing
boxes = self.content_boxes
vars_gv = []
n = len(boxes)
+ gv_vinfo = builder.genop_call(typedesc.make_vinfo_token,
+ typedesc.gv_make_vinfo_ptr,
+ [])
for i in range(NVABLEFIELDS, n-1):
box = boxes[i]
- assert box.genvar
- vars_gv.append(box.genvar)
+ if box.genvar:
+ vars_gv.append(box.genvar)
+ builder.genop_call(typedesc.vinfo_skip_vinfo_token,
+ typedesc.gv_vinfo_skip_vinfo_ptr,
+ [gv_vinfo])
+
+ else:
+ vars_gv.append(None)
+ assert isinstance(box, rvalue.PtrRedBox)
+ content = box.content
+ assert isinstance(content, VirtualStruct) # XXX for now
+ gv_vinfo1 = content.make_vinfo(jitstate)
+ builder.genop_call(typedesc.vinfo_append_vinfo_token,
+ typedesc.gv_vinfo_append_vinfo_ptr,
+ [gv_vinfo, gv_vinfo1])
+
+
gv_info = builder.get_frame_info(vars_gv)
+ builder.genop_call(typedesc.vinfo_set_info_token,
+ typedesc.gv_vinfo_set_info_ptr,
+ [gv_vinfo, gv_info])
info_token = typedesc.info_desc.fieldtoken
+ builder.genop_setfield(info_token, gv_outside,
+ gv_vinfo)
access_token = typedesc.access_desc.fieldtoken
- builder.genop_setfield(info_token, gv_outside, gv_info)
- builder.genop_setfield(access_token, gv_outside, typedesc.gv_access)
+ builder.genop_setfield(access_token, gv_outside,
+ typedesc.gv_access)
def after_residual_call(self, jitstate):
typedesc = self.typedesc
Modified: pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_virtualizable.py Sun Jan 14 17:24:15 2007
@@ -1,7 +1,7 @@
from pypy.jit.hintannotator.annotator import HintAnnotatorPolicy
from pypy.jit.timeshifter.test.test_portal import PortalTest, P_NOVIRTUAL
from pypy.rpython.lltypesystem import lltype, llmemory
-
+from pypy.jit.timeshifter.rcontainer import VABLEINFOPTR
import py
S = lltype.GcStruct('s', ('a', lltype.Signed), ('b', lltype.Signed))
@@ -38,7 +38,7 @@
XY.become(lltype.GcStruct('xy',
('vable_base', llmemory.Address),
- ('vable_info', llmemory.GCREF),
+ ('vable_info', VABLEINFOPTR),
('vable_access', lltype.Ptr(XY_ACCESS)),
('x', lltype.Signed),
('y', lltype.Signed),
@@ -50,13 +50,16 @@
XP.become(lltype.GcStruct('xp',
('vable_base', llmemory.Address),
- ('vable_info', llmemory.GCREF),
+ ('vable_info', VABLEINFOPTR),
('vable_access', lltype.Ptr(XP_ACCESS)),
('x', lltype.Signed),
('p', PS),
hints = {'virtualizable': True}
))
+E2 = lltype.GcStruct('e', ('xp', lltype.Ptr(XP)),
+ ('w', lltype.Signed))
+
class TestVirtualizable(PortalTest):
@@ -506,7 +509,8 @@
class StopAtGPolicy(HintAnnotatorPolicy):
- novirtualcontainer = True
+ def __init__(self):
+ HintAnnotatorPolicy.__init__(self, novirtualcontainer=True)
def look_inside_graph(self, graph):
if graph.name == 'g':
@@ -556,7 +560,8 @@
class StopAtGPolicy(HintAnnotatorPolicy):
- novirtualcontainer = True
+ def __init__(self):
+ HintAnnotatorPolicy.__init__(self, novirtualcontainer=True)
def look_inside_graph(self, graph):
if graph.name == 'g':
@@ -566,3 +571,70 @@
res = self.timeshift_from_portal(main, f, [2, 20],
policy=StopAtGPolicy())
assert res == 42
+
+ def test_explicit_force_in_residual_red_call(self):
+
+ def g(e):
+ xp = e.xp
+ xp_access = xp.vable_access
+ if xp_access:
+ p = xp_access.get_p(xp)
+ else:
+ p = xp.p
+ xp_access = xp.vable_access
+ if xp_access:
+ x = xp_access.get_x(xp)
+ else:
+ x = xp.x
+
+ e.w = p.a + p.b + x
+
+ def f(e, a, b):
+ xp = e.xp
+ s = lltype.malloc(S)
+ s.a = a
+ s.b = b
+ xp_access = xp.vable_access
+ if xp_access:
+ xp_access.set_p(xp, s)
+ else:
+ xp.p = s
+ xp_access = xp.vable_access
+
+ xp_access = xp.vable_access
+ if xp_access:
+ x = xp_access.get_x(xp)
+ else:
+ x = xp.x
+ xp_access = xp.vable_access
+ newx = 2*x
+ if xp_access:
+ xp_access.set_x(xp, newx)
+ else:
+ xp.x = newx
+ g(e)
+ return xp.x
+
+ def main(a, b, x):
+ xp = lltype.malloc(XP)
+ xp.vable_access = lltype.nullptr(XP_ACCESS)
+ xp.x = x
+ xp.p = lltype.nullptr(S)
+ e = lltype.malloc(E2)
+ e.xp = xp
+ f(e, a, b)
+ return e.w
+
+
+ class StopAtGPolicy(HintAnnotatorPolicy):
+ def __init__(self):
+ HintAnnotatorPolicy.__init__(self, novirtualcontainer=True)
+
+ def look_inside_graph(self, graph):
+ if graph.name == 'g':
+ return False
+ return True
+
+ res = self.timeshift_from_portal(main, f, [2, 20, 10],
+ policy=StopAtGPolicy())
+ assert res == 42
More information about the pypy-svn
mailing list