[pypy-svn] r48198 - in pypy/dist/pypy/jit: codegen/i386 codegen/llgraph codegen/test hintannotator hintannotator/test timeshifter timeshifter/test
arigo at codespeak.net
arigo at codespeak.net
Tue Oct 30 14:46:51 CET 2007
Author: arigo
Date: Tue Oct 30 14:46:50 2007
New Revision: 48198
Modified:
pypy/dist/pypy/jit/codegen/i386/operation.py
pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
pypy/dist/pypy/jit/codegen/test/rgenop_tests.py
pypy/dist/pypy/jit/hintannotator/model.py
pypy/dist/pypy/jit/hintannotator/test/test_annotator.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_timeshift.py
Log:
Attempt to fix the JIT. This adds support for the new interior pointer
operations (and for int_add_nonneg_ovf).
Modified: pypy/dist/pypy/jit/codegen/i386/operation.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/operation.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/operation.py Tue Oct 30 14:46:50 2007
@@ -198,7 +198,7 @@
self.emit(allocator.mc, dstop, op2)
class OpIntAdd(BinaryOp):
- opname = 'int_add', 'uint_add', 'int_add_ovf'
+ opname = 'int_add', 'uint_add', 'int_add_ovf', 'int_add_nonneg_ovf'
emit = staticmethod(I386CodeBuilder.ADD)
commutative = True
ccexcflag = Conditions['O']
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 Tue Oct 30 14:46:50 2007
@@ -244,6 +244,114 @@
return isinstance(c, flowmodel.Constant)
+# ____________________________________________________________
+# Interior access helpers
+
+class InteriorPtrVariable(object):
+ def __init__(self, base_and_offsets_gv):
+ self.base_and_offsets_gv = base_and_offsets_gv
+
+def gengetsubstruct(block, gv_ptr, gv_PTRTYPE, gv_fieldname):
+ v_ptr = from_opaque_object(gv_ptr)
+ # don't generate any operation for an interior getsubstruct,
+ # but just return a special pseudo-variable
+ if isinstance(v_ptr, InteriorPtrVariable):
+ # a nested getsubstruct
+ v = InteriorPtrVariable(v_ptr.base_and_offsets_gv + [gv_fieldname])
+ return to_opaque_object(v)
+ # in all other cases we need a proper cast
+ gv_ptr = cast(block, gv_PTRTYPE, gv_ptr)
+ PTRTYPE = from_opaque_object(gv_PTRTYPE).value
+ if PTRTYPE.TO._gckind == 'gc':
+ # reading from a GcStruct requires returning an interior pointer
+ # pseudo-variable
+ v = InteriorPtrVariable([gv_ptr, gv_fieldname])
+ return to_opaque_object(v)
+ else:
+ vars_gv = [gv_ptr, gv_fieldname]
+ c_fieldname = from_opaque_object(gv_fieldname)
+ RESULTTYPE = lltype.Ptr(getattr(PTRTYPE.TO, c_fieldname.value))
+ return genop(block, "getsubstruct", vars_gv, RESULTTYPE)
+
+def gengetarraysubstruct(block, gv_ptr, gv_index):
+ v_ptr = from_opaque_object(gv_ptr)
+ # don't generate any operation for an interior getarraysubstruct,
+ # but just return a special pseudo-variable
+ if isinstance(v_ptr, InteriorPtrVariable):
+ # a nested getarraysubstruct
+ v = InteriorPtrVariable(v_ptr.base_and_offsets_gv + [gv_index])
+ return to_opaque_object(v)
+ PTRTYPE = v_ptr.concretetype
+ if PTRTYPE.TO._gckind == 'gc':
+ # reading from a GcArray requires returning an interior pointer
+ # pseudo-variable
+ v = InteriorPtrVariable([gv_ptr, gv_index])
+ return to_opaque_object(v)
+ else:
+ vars_gv = [gv_ptr, gv_index]
+ RESULTTYPE = lltype.Ptr(PTRTYPE.TO.OF)
+ return genop(block, "getarraysubstruct", vars_gv, RESULTTYPE)
+
+def gensetfield(block, gv_ptr, gv_PTRTYPE, gv_fieldname, gv_value):
+ v_ptr = from_opaque_object(gv_ptr)
+ if isinstance(v_ptr, InteriorPtrVariable):
+ # this is really a setinteriorfield
+ vars_gv = v_ptr.base_and_offsets_gv + [gv_fieldname, gv_value]
+ genop(block, "setinteriorfield", vars_gv, lltype.Void)
+ else:
+ # for setfield we need a proper cast (for setinteriorfield, the
+ # top-level cast was already inserted by gengetsubstruct)
+ gv_ptr = cast(block, gv_PTRTYPE, gv_ptr)
+ vars_gv = [gv_ptr, gv_fieldname, gv_value]
+ genop(block, "setfield", vars_gv, lltype.Void)
+
+def gengetfield(block, gv_ptr, gv_PTRTYPE, gv_fieldname):
+ PTRTYPE = from_opaque_object(gv_PTRTYPE).value
+ c_fieldname = from_opaque_object(gv_fieldname)
+ RESULTTYPE = getattr(PTRTYPE.TO, c_fieldname.value)
+ v_ptr = from_opaque_object(gv_ptr)
+ if isinstance(v_ptr, InteriorPtrVariable):
+ # this is really a getinteriorfield
+ vars_gv = v_ptr.base_and_offsets_gv + [gv_fieldname]
+ return genop(block, "getinteriorfield", vars_gv, RESULTTYPE)
+ else:
+ # for getfield we need a proper cast (for getinteriorfield, the
+ # top-level cast was already inserted by gengetsubstruct)
+ gv_ptr = cast(block, gv_PTRTYPE, gv_ptr)
+ vars_gv = [gv_ptr, gv_fieldname]
+ return genop(block, "getfield", vars_gv, RESULTTYPE)
+
+def gensetarrayitem(block, gv_ptr, gv_index, gv_value):
+ v_ptr = from_opaque_object(gv_ptr)
+ if isinstance(v_ptr, InteriorPtrVariable):
+ # this is really a setinteriorfield
+ vars_gv = v_ptr.base_and_offsets_gv + [gv_index, gv_value]
+ genop(block, "setinteriorfield", vars_gv, lltype.Void)
+ else:
+ vars_gv = [gv_ptr, gv_index, gv_value]
+ genop(block, "setarrayitem", vars_gv, lltype.Void)
+
+def gengetarrayitem(block, gv_ITEMTYPE, gv_ptr, gv_index):
+ ITEMTYPE = from_opaque_object(gv_ITEMTYPE).value
+ v_ptr = from_opaque_object(gv_ptr)
+ if isinstance(v_ptr, InteriorPtrVariable):
+ # this is really a getinteriorfield
+ vars_gv = v_ptr.base_and_offsets_gv + [gv_index]
+ return genop(block, "getinteriorfield", vars_gv, ITEMTYPE)
+ else:
+ vars_gv = [gv_ptr, gv_index]
+ return genop(block, "getarrayitem", vars_gv, ITEMTYPE)
+
+def gengetarraysize(block, gv_ptr):
+ v_ptr = from_opaque_object(gv_ptr)
+ if isinstance(v_ptr, InteriorPtrVariable):
+ # this is really a getinteriorarraysize
+ vars_gv = v_ptr.base_and_offsets_gv
+ return genop(block, "getinteriorarraysize", vars_gv, lltype.Signed)
+ else:
+ vars_gv = [gv_ptr]
+ return genop(block, "getarraysize", vars_gv, lltype.Signed)
+
# XXX
# temporary interface; it's unclear if genop itself should change to
# ease dinstinguishing Void special args from the rest. Or there
@@ -503,6 +611,8 @@
consttypeinfo = declareptrtype(flowmodel.Constant, "ConstOrVar")
vartypeinfo = declareptrtype(flowmodel.Variable, "ConstOrVar")
vartypeinfo.set_lltype(consttypeinfo.get_lltype()) # force same lltype
+interiorptrvartypeinfo = declareptrtype(InteriorPtrVariable, "ConstOrVar")
+interiorptrvartypeinfo.set_lltype(vartypeinfo.get_lltype()) # force same lltype
linktypeinfo = declareptrtype(flowmodel.Link, "Link")
graphtypeinfo = declareptrtype(flowmodel.FunctionGraph, "FunctionGraph")
@@ -566,6 +676,13 @@
setannotation(geninputarg, s_ConstOrVar)
setannotation(getinputarg, s_ConstOrVar)
setannotation(genop, s_ConstOrVar)
+setannotation(gengetsubstruct, s_ConstOrVar)
+setannotation(gengetarraysubstruct, s_ConstOrVar)
+setannotation(gensetfield, None)
+setannotation(gengetfield, s_ConstOrVar)
+setannotation(gensetarrayitem, None)
+setannotation(gengetarrayitem, s_ConstOrVar)
+setannotation(gengetarraysize, s_ConstOrVar)
setannotation(end, None)
setannotation(genconst, s_ConstOrVar)
setannotation(genzeroconst, s_ConstOrVar)
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 Tue Oct 30 14:46:50 2007
@@ -159,53 +159,63 @@
def genop_getfield(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr):
debug_assert(self.rgenop.currently_writing is self,
"genop_getfield: bad currently_writing")
- vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v]
- return LLVar(llimpl.genop(self.b, 'getfield', vars_gv,
- gv_FIELDTYPE.v))
+ return LLVar(llimpl.gengetfield(self.b, gv_ptr.v,
+ gv_PTRTYPE.v, gv_name.v))
+ #vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v]
+ #return LLVar(llimpl.genop(self.b, 'getfield', vars_gv,
+ # gv_FIELDTYPE.v))
def genop_setfield(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr,
gv_value):
debug_assert(self.rgenop.currently_writing is self,
"genop_setfield: bad currently_writing")
- vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v),
- gv_name.v,
- llimpl.cast(self.b, gv_FIELDTYPE.v, gv_value.v)]
- return LLVar(llimpl.genop(self.b, 'setfield', vars_gv,
- gv_Void.v))
+ v_value = llimpl.cast(self.b, gv_FIELDTYPE.v, gv_value.v)
+ llimpl.gensetfield(self.b, gv_ptr.v, gv_PTRTYPE.v, gv_name.v, v_value)
+ #vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v),
+ # gv_name.v,
+ # llimpl.cast(self.b, gv_FIELDTYPE.v, gv_value.v)]
+ #return LLVar(llimpl.genop(self.b, 'setfield', vars_gv,
+ # gv_Void.v))
def genop_getsubstruct(self, (gv_name, gv_PTRTYPE, gv_FIELDTYPE), gv_ptr):
debug_assert(self.rgenop.currently_writing is self,
"genop_getsubstruct: bad currently_writing")
- vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v]
- return LLVar(llimpl.genop(self.b, 'getsubstruct', vars_gv,
- gv_FIELDTYPE.v))
+ return LLVar(llimpl.gengetsubstruct(self.b, gv_ptr.v,
+ gv_PTRTYPE.v, gv_name.v))
+ #vars_gv = [llimpl.cast(self.b, gv_PTRTYPE.v, gv_ptr.v), gv_name.v]
+ #return LLVar(llimpl.genop(self.b, 'getsubstruct', vars_gv,
+ # gv_FIELDTYPE.v))
def genop_getarrayitem(self, gv_ITEMTYPE, gv_ptr, gv_index):
debug_assert(self.rgenop.currently_writing is self,
"genop_getarrayitem: bad currently_writing")
- vars_gv = [gv_ptr.v, gv_index.v]
- return LLVar(llimpl.genop(self.b, 'getarrayitem', vars_gv,
- gv_ITEMTYPE.v))
+ return LLVar(llimpl.gengetarrayitem(self.b, gv_ITEMTYPE.v,
+ gv_ptr.v, gv_index.v))
+ #vars_gv = [gv_ptr.v, gv_index.v]
+ #return LLVar(llimpl.genop(self.b, 'getarrayitem', vars_gv,
+ # gv_ITEMTYPE.v))
def genop_getarraysubstruct(self, gv_ITEMTYPE, gv_ptr, gv_index):
debug_assert(self.rgenop.currently_writing is self,
"genop_getarraysubstruct: bad currently_writing")
- vars_gv = [gv_ptr.v, gv_index.v]
- return LLVar(llimpl.genop(self.b, 'getarraysubstruct', vars_gv,
- gv_ITEMTYPE.v))
+ return LLVar(llimpl.gengetarraysubstruct(self.b, gv_ptr.v, gv_index.v))
+ #vars_gv = [gv_ptr.v, gv_index.v]
+ #return LLVar(llimpl.genop(self.b, 'getarraysubstruct', vars_gv,
+ # gv_ITEMTYPE.v))
def genop_setarrayitem(self, gv_ITEMTYPE, gv_ptr, gv_index, gv_value):
debug_assert(self.rgenop.currently_writing is self,
"genop_setarrayitem: bad currently_writing")
- vars_gv = [gv_ptr.v, gv_index.v, gv_value.v]
- return LLVar(llimpl.genop(self.b, 'setarrayitem', vars_gv,
- gv_Void.v))
+ llimpl.gensetarrayitem(self.b, gv_ptr.v, gv_index.v, gv_value.v)
+ #vars_gv = [gv_ptr.v, gv_index.v, gv_value.v]
+ #llimpl.genop(self.b, 'setarrayitem', vars_gv, gv_Void.v)
def genop_getarraysize(self, gv_ITEMTYPE, gv_ptr):
debug_assert(self.rgenop.currently_writing is self,
"genop_getarraysize: bad currently_writing")
- return LLVar(llimpl.genop(self.b, 'getarraysize', [gv_ptr.v],
- gv_Signed.v))
+ return LLVar(llimpl.gengetarraysize(self.b, gv_ptr.v))
+ #return LLVar(llimpl.genop(self.b, 'getarraysize', [gv_ptr.v],
+ # gv_Signed.v))
def genop_malloc_fixedsize(self, (gv_TYPE, gv_PTRTYPE)):
debug_assert(self.rgenop.currently_writing is self,
Modified: pypy/dist/pypy/jit/codegen/test/rgenop_tests.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/test/rgenop_tests.py (original)
+++ pypy/dist/pypy/jit/codegen/test/rgenop_tests.py Tue Oct 30 14:46:50 2007
@@ -2075,3 +2075,40 @@
x |= 1
result = fnptr(x)
assert result == expected(x)
+
+ def test_interior_access(self):
+ # for assembler backends, the 'interior' lloperations can be
+ # simply expressed as a sequence of genop_getsubstruct and
+ # genop_getarraysubstruct. So we put magic in the llgraph
+ # backend to recognize and rebuild the expected 'interior'
+ # lloperation in the llgraphs.
+ T = lltype.Struct('T', ('x', lltype.Signed))
+ A = lltype.Array(T)
+ S = lltype.GcStruct('S', ('a', A))
+ rgenop = self.RGenOp()
+ sigtoken = rgenop.sigToken(FUNC)
+ builder, gv_fn, [gv_x] = rgenop.newgraph(sigtoken, "interior_access")
+ builder.start_writing()
+ gv_s = builder.genop_malloc_varsize(rgenop.varsizeAllocToken(S),
+ rgenop.genconst(5))
+ # generate an expanded 'setinteriorfield'
+ gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s)
+ gv_t1 = builder.genop_getarraysubstruct(rgenop.arrayToken(A),
+ gv_a1, rgenop.genconst(3))
+ builder.genop_setfield(rgenop.fieldToken(T, 'x'), gv_t1, gv_x)
+ # generate an expanded 'getinteriorfield'
+ gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s)
+ gv_t1 = builder.genop_getarraysubstruct(rgenop.arrayToken(A),
+ gv_a1, rgenop.genconst(3))
+ gv_y = builder.genop_getfield(rgenop.fieldToken(T, 'x'), gv_t1)
+ # generate an expanded 'getinteriorarraysize'
+ gv_a1 = builder.genop_getsubstruct(rgenop.fieldToken(S, 'a'), gv_s)
+ gv_z = builder.genop_getarraysize(rgenop.arrayToken(A), gv_a1)
+ # return
+ gv_result = builder.genop2("int_add", gv_y, gv_z)
+ builder.finish_and_return(sigtoken, gv_result)
+ builder.end()
+
+ fnptr = self.cast(gv_fn, 1)
+ result = fnptr(42)
+ assert result == 47
Modified: pypy/dist/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/model.py (original)
+++ pypy/dist/pypy/jit/hintannotator/model.py Tue Oct 30 14:46:50 2007
@@ -4,6 +4,7 @@
from pypy.rpython.lltypesystem import lltype, lloperation
UNARY_OPERATIONS = """same_as hint getfield setfield getsubstruct getarraysize
+ getinteriorfield getinteriorarraysize setinteriorfield
cast_pointer
direct_call
indirect_call
@@ -24,7 +25,7 @@
BINARY_OPERATIONS = """int_add int_sub int_mul int_mod int_and int_rshift
int_lshift int_floordiv int_xor int_or
int_add_ovf int_sub_ovf int_mul_ovf int_mod_ovf
- int_floordiv_ovf int_lshift_ovf
+ int_floordiv_ovf int_lshift_ovf int_add_nonneg_ovf
uint_add uint_sub uint_mul uint_mod uint_and
uint_lshift uint_rshift uint_floordiv
char_gt char_lt char_le char_ge char_eq char_ne
@@ -346,6 +347,35 @@
FIELD_TYPE = getattr(S, hs_fieldname.const)
return SomeLLAbstractVariable(lltype.Ptr(FIELD_TYPE), hs_v1.deepfrozen)
+ def _getinterior(hs_v1, *offsets_hs):
+ hs_container = hs_v1
+ for hs_offset in offsets_hs:
+ if hs_offset.concretetype is lltype.Signed:
+ hs_container = pair(hs_container,hs_offset).getarraysubstruct()
+ else:
+ hs_container = hs_container.getsubstruct(hs_offset)
+ return hs_container
+
+ def getinteriorfield(hs_v1, *offsets_hs):
+ hs_container = hs_v1._getinterior(*offsets_hs[:-1])
+ hs_lastofs = offsets_hs[-1]
+ if hs_lastofs.concretetype is lltype.Signed:
+ return pair(hs_container, hs_lastofs).getarrayitem()
+ else:
+ return hs_container.getfield(hs_lastofs)
+
+ def getinteriorarraysize(hs_v1, *offsets_hs):
+ return hs_v1._getinterior(*offsets_hs).getarraysize()
+
+ def setinteriorfield(hs_v1, *offsets_and_val_hs):
+ hs_inner = hs_v1._getinterior(*offsets_and_val_hs[:-2])
+ hs_lastofs = offsets_and_val_hs[-2]
+ hs_value = offsets_and_val_hs[-1]
+ if hs_lastofs.concretetype is lltype.Signed:
+ pair(hs_inner, hs_lastofs).setarrayitem(hs_value)
+ else:
+ hs_inner.setfield(hs_lastofs, hs_value)
+
def cast_pointer(hs_v1):
RESTYPE = getbookkeeper().current_op_concretetype()
return SomeLLAbstractVariable(RESTYPE, hs_v1.deepfrozen)
Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original)
+++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Tue Oct 30 14:46:50 2007
@@ -144,7 +144,9 @@
res = hint(res, variable=True)
return res
- hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL)
+ # must backendoptimize to remove the mallocs related to the interior ptrs
+ hs = hannotate(ll_function, [int, int], policy=P_NOVIRTUAL,
+ backendoptimize=True)
assert hs.concretetype == lltype.Signed
@@ -428,6 +430,7 @@
assert hs1.contentdef.degenerated
def test_degenerated_merge_cross_substructure():
+ py.test.skip("no longer a valid test")
from pypy.rlib import objectmodel
S = lltype.Struct('S', ('n', lltype.Signed))
T = lltype.GcStruct('T', ('s', S), ('s1', S), ('n', lltype.Float))
Modified: pypy/dist/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/hrtyper.py (original)
+++ pypy/dist/pypy/jit/timeshifter/hrtyper.py Tue Oct 30 14:46:50 2007
@@ -880,6 +880,100 @@
ts.s_RedBox)
+ def _getinteriordesc(self, hop, PTRTYPE, nb_offsets):
+ path = []
+ CONTAINER = PTRTYPE.TO
+ indices_v = []
+ for i in range(1, 1 + nb_offsets):
+ T = originalconcretetype(hop.args_s[i])
+ if T is lltype.Void:
+ fieldname = hop.args_v[i].value
+ CONTAINER = getattr(CONTAINER, fieldname)
+ path.append(fieldname)
+ else:
+ assert T is lltype.Signed
+ CONTAINER = CONTAINER.OF
+ path.append(None) # placeholder for 'array index'
+ v_index = hop.inputarg(self.getredrepr(lltype.Signed), arg=i)
+ indices_v.append(v_index)
+ if CONTAINER is lltype.Void: # Void field
+ return None, None
+ else:
+ return (rcontainer.InteriorDesc(self, PTRTYPE.TO, tuple(path)),
+ indices_v)
+
+ def translate_op_getinteriorfield(self, hop):
+ ts = self
+ # no virtualizable access read here
+ PTRTYPE = originalconcretetype(hop.args_s[0])
+ assert not PTRTYPE.TO._hints.get('virtualizable', False)
+
+ # non virtual case
+ interiordesc, indices_v = self._getinteriordesc(hop, PTRTYPE,
+ hop.nb_args - 1)
+ if interiordesc is None: # Void field
+ return None
+ v_argbox = hop.inputarg(self.getredrepr(PTRTYPE), arg=0)
+ v_argbox = hop.llops.as_ptrredbox(v_argbox)
+ c_deepfrozen = inputconst(lltype.Bool, hop.args_s[0].deepfrozen)
+ c_interiordesc = inputconst(lltype.Void, interiordesc)
+ s_interiordesc = ts.rtyper.annotator.bookkeeper.immutablevalue(
+ interiordesc)
+ v_jitstate = hop.llops.getjitstate()
+ return hop.llops.genmixlevelhelpercall(
+ rtimeshift.ll_gengetinteriorfield,
+ [ts.s_JITState, annmodel.s_Bool, s_interiordesc, ts.s_PtrRedBox]
+ + [ts.s_RedBox]*len(indices_v),
+ [v_jitstate , c_deepfrozen , c_interiordesc, v_argbox ]
+ + indices_v,
+ ts.s_RedBox)
+
+ def translate_op_setinteriorfield(self, hop):
+ ts = self
+ PTRTYPE = originalconcretetype(hop.args_s[0])
+ # non virtual case
+ interiordesc, indices_v = self._getinteriordesc(hop, PTRTYPE,
+ hop.nb_args - 2)
+ if interiordesc is None: # Void field
+ return None
+ v_destbox = hop.inputarg(self.getredrepr(PTRTYPE), arg=0)
+ v_valuebox = hop.inputarg(self.getredrepr(interiordesc.VALUETYPE),
+ arg = hop.nb_args - 1)
+ v_destbox = hop.llops.as_ptrredbox(v_destbox)
+ c_interiordesc = inputconst(lltype.Void, interiordesc)
+ s_interiordesc = ts.rtyper.annotator.bookkeeper.immutablevalue(
+ interiordesc)
+ v_jitstate = hop.llops.getjitstate()
+ return hop.llops.genmixlevelhelpercall(
+ rtimeshift.ll_gensetinteriorfield,
+ [ts.s_JITState, s_interiordesc, ts.s_PtrRedBox, ts.s_RedBox]
+ + [ts.s_RedBox]*len(indices_v),
+ [v_jitstate, c_interiordesc, v_destbox, v_valuebox]
+ + indices_v,
+ annmodel.s_None)
+
+ def translate_op_getinteriorarraysize(self, hop):
+ ts = self
+ PTRTYPE = originalconcretetype(hop.args_s[0])
+ # non virtual case
+ interiordesc, indices_v = self._getinteriordesc(hop, PTRTYPE,
+ hop.nb_args - 1)
+ assert interiordesc is not None
+ v_argbox = hop.inputarg(self.getredrepr(PTRTYPE), arg=0)
+ v_argbox = hop.llops.as_ptrredbox(v_argbox)
+ c_interiordesc = inputconst(lltype.Void, interiordesc)
+ s_interiordesc = ts.rtyper.annotator.bookkeeper.immutablevalue(
+ interiordesc)
+ v_jitstate = hop.llops.getjitstate()
+ return hop.llops.genmixlevelhelpercall(
+ rtimeshift.ll_gengetinteriorarraysize,
+ [ts.s_JITState, s_interiordesc, ts.s_PtrRedBox]
+ + [ts.s_RedBox]*len(indices_v),
+ [v_jitstate, c_interiordesc, v_argbox ]
+ + indices_v,
+ ts.s_RedBox)
+
+
def translate_op_cast_pointer(self, hop):
FROM_TYPE = originalconcretetype(hop.args_s[0])
[v_argbox] = hop.inputargs(self.getredrepr(FROM_TYPE))
Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Tue Oct 30 14:46:50 2007
@@ -349,6 +349,147 @@
content.content_boxes.append(outsidebox)
return vstructbox
+
+class InteriorDesc(object):
+ __metaclass__ = cachedtype
+
+ def __init__(self, hrtyper, TOPCONTAINER, path):
+ self.TOPCONTAINER = TOPCONTAINER
+ self.path = path
+ PTRTYPE = lltype.Ptr(TOPCONTAINER)
+ TYPE = TOPCONTAINER
+ fielddescs = []
+ for offset in path:
+ LASTCONTAINER = TYPE
+ if offset is None: # array substruct
+ fielddescs.append(ArrayFieldDesc(hrtyper, TYPE))
+ TYPE = TYPE.OF
+ else:
+ fielddescs.append(NamedFieldDesc(hrtyper, lltype.Ptr(TYPE),
+ offset))
+ TYPE = getattr(TYPE, offset)
+ unroll_path = unrolling_iterable(path)
+ self.VALUETYPE = TYPE
+
+ if not isinstance(TYPE, lltype.ContainerType):
+ lastoffset = path[-1]
+ lastfielddesc = fielddescs[-1]
+ immutable = LASTCONTAINER._hints.get('immutable', False)
+ getinterior_initial = make_interior_getter(fielddescs[:-1])
+
+ def gengetinteriorfield(jitstate, deepfrozen, argbox, *indexboxes):
+ if (immutable or deepfrozen) and argbox.is_constant():
+ ptr = rvalue.ll_getvalue(argbox, PTRTYPE)
+ if ptr: # else don't constant-fold the segfault...
+ i = 0
+ for offset in unroll_path:
+ if offset is None: # array substruct
+ indexbox = indexboxes[i]
+ i += 1
+ if not indexbox.is_constant():
+ break # non-constant array index
+ index = rvalue.ll_getvalue(indexbox,
+ lltype.Signed)
+ ptr = ptr[index]
+ else:
+ ptr = getattr(ptr, offset)
+ else:
+ # constant-folding: success
+ assert i == len(indexboxes)
+ return rvalue.ll_fromvalue(jitstate, ptr)
+ argbox = getinterior_initial(jitstate, argbox, *indexboxes)
+ if lastoffset is None: # getarrayitem
+ indexbox = indexboxes[-1]
+ genvar = jitstate.curbuilder.genop_getarrayitem(
+ lastfielddesc.arraytoken,
+ argbox.getgenvar(jitstate),
+ indexbox.getgenvar(jitstate))
+ return lastfielddesc.makebox(jitstate, genvar)
+ else: # getfield
+ return argbox.op_getfield(jitstate, lastfielddesc)
+
+ def gensetinteriorfield(jitstate, destbox, valuebox, *indexboxes):
+ destbox = getinterior_initial(jitstate, destbox, *indexboxes)
+ if lastoffset is None: # setarrayitem
+ indexbox = indexboxes[-1]
+ genvar = jitstate.curbuilder.genop_setarrayitem(
+ lastfielddesc.arraytoken,
+ destbox.getgenvar(jitstate),
+ indexbox.getgenvar(jitstate),
+ valuebox.getgenvar(jitstate)
+ )
+ else: # setfield
+ destbox.op_setfield(jitstate, lastfielddesc, valuebox)
+
+ self.gengetinteriorfield = gengetinteriorfield
+ self.gensetinteriorfield = gensetinteriorfield
+
+ else:
+ assert isinstance(TYPE, lltype.Array)
+ arrayfielddesc = ArrayFieldDesc(hrtyper, TYPE)
+ getinterior_all = make_interior_getter(fielddescs)
+
+ def gengetinteriorarraysize(jitstate, argbox, *indexboxes):
+ if argbox.is_constant():
+ ptr = rvalue.ll_getvalue(argbox, PTRTYPE)
+ if ptr: # else don't constant-fold the segfault...
+ i = 0
+ for offset in unroll_path:
+ if offset is None: # array substruct
+ indexbox = indexboxes[i]
+ i += 1
+ if not indexbox.is_constant():
+ break # non-constant array index
+ index = rvalue.ll_getvalue(indexbox,
+ lltype.Signed)
+ ptr = ptr[index]
+ else:
+ ptr = getattr(ptr, offset)
+ else:
+ # constant-folding: success
+ assert i == len(indexboxes)
+ return rvalue.ll_fromvalue(jitstate, len(ptr))
+ argbox = getinterior_all(jitstate, argbox, *indexboxes)
+ genvar = jitstate.curbuilder.genop_getarraysize(
+ arrayfielddesc.arraytoken,
+ argbox.getgenvar(jitstate))
+ return rvalue.IntRedBox(arrayfielddesc.indexkind, genvar)
+
+ self.gengetinteriorarraysize = gengetinteriorarraysize
+
+ def _freeze_(self):
+ return True
+
+
+def make_interior_getter(fielddescs, _cache={}):
+ # returns a 'getinterior(jitstate, argbox, *indexboxes)' function
+ key = tuple(fielddescs)
+ try:
+ return _cache[key]
+ except KeyError:
+ unroll_fielddescs = unrolling_iterable([
+ (fielddesc, isinstance(fielddesc, ArrayFieldDesc))
+ for fielddesc in fielddescs])
+
+ def getinterior(jitstate, argbox, *indexboxes):
+ i = 0
+ for fielddesc, is_array in unroll_fielddescs:
+ if is_array: # array substruct
+ indexbox = indexboxes[i]
+ i += 1
+ genvar = jitstate.curbuilder.genop_getarraysubstruct(
+ fielddesc.arraytoken,
+ argbox.getgenvar(jitstate),
+ indexbox.getgenvar(jitstate))
+ argbox = fielddesc.makebox(jitstate, genvar)
+ else: # getsubstruct
+ argbox = argbox.op_getsubstruct(jitstate, fielddesc)
+ assert isinstance(argbox, rvalue.PtrRedBox)
+ return argbox
+
+ _cache[key] = getinterior
+ return getinterior
+
# ____________________________________________________________
# XXX basic field descs for now
Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Tue Oct 30 14:46:50 2007
@@ -11,6 +11,7 @@
FOLDABLE_GREEN_OPS = dict.fromkeys(lloperation.enum_foldable_ops())
FOLDABLE_GREEN_OPS['getfield'] = None
FOLDABLE_GREEN_OPS['getarrayitem'] = None
+FOLDABLE_GREEN_OPS['getinteriorfield'] = None
NULL_OBJECT = base_ptr_lltype()._defl()
@@ -211,6 +212,20 @@
argbox.getgenvar(jitstate))
return rvalue.IntRedBox(fielddesc.indexkind, genvar)
+
+def ll_gengetinteriorfield(jitstate, deepfrozen, interiordesc,
+ argbox, *indexboxes):
+ return interiordesc.gengetinteriorfield(jitstate, deepfrozen,
+ argbox, *indexboxes)
+
+def ll_gensetinteriorfield(jitstate, interiordesc, destbox,
+ valuebox, *indexboxes):
+ interiordesc.gensetinteriorfield(jitstate, destbox, valuebox, *indexboxes)
+
+def ll_gengetinteriorarraysize(jitstate, interiordesc, argbox, *indexboxes):
+ return interiordesc.gengetinteriorarraysize(jitstate, argbox, *indexboxes)
+
+
def ll_genptrnonzero(jitstate, argbox, reverse):
if argbox.is_constant():
addr = rvalue.ll_getvalue(argbox, llmemory.Address)
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 Tue Oct 30 14:46:50 2007
@@ -196,10 +196,16 @@
s = ["aaaaaaaaaab", "aaaa"][gets]
return recognizetable(dfatable, s, final_states)
- res = self.timeshift_from_portal(main, recognizetable, [0], policy=P_NOVIRTUAL)
+ # must backendoptimize to remove the mallocs related
+ # to the interior ptrs
+ res = self.timeshift_from_portal(main, recognizetable, [0],
+ policy=P_NOVIRTUAL,
+ backendoptimize=True)
assert res
- res = self.timeshift_from_portal(main, recognizetable, [1], policy=P_NOVIRTUAL)
+ res = self.timeshift_from_portal(main, recognizetable, [1],
+ policy=P_NOVIRTUAL,
+ backendoptimize=True)
assert not res
def test_dfa_compile2(self):
@@ -210,11 +216,17 @@
s = ["aaaaaaaaaab", "aaaa"][gets]
return recognizeparts(alltrans, final_states, s)
- res = self.timeshift_from_portal(main, recognizeparts, [0, 0], policy=P_NOVIRTUAL)
+ # must backendoptimize to remove the mallocs related
+ # to the interior ptrs
+ res = self.timeshift_from_portal(main, recognizeparts, [0, 0],
+ policy=P_NOVIRTUAL,
+ backendoptimize=True)
assert res
# XXX unfortunately we have to create a new version each time - because of pbc
- res = self.timeshift_from_portal(main, recognizeparts, [1, 0], policy=P_NOVIRTUAL)
+ res = self.timeshift_from_portal(main, recognizeparts, [1, 0],
+ policy=P_NOVIRTUAL,
+ backendoptimize=True)
assert not res
def test_dfa_compile3(self):
Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Tue Oct 30 14:46:50 2007
@@ -59,8 +59,7 @@
auto_inlining(t, threshold=inline)
if backendoptimize:
from pypy.translator.backendopt.all import backend_optimizations
- if inline is not None:
- backend_optimizations(t, inline_threshold=inline)
+ backend_optimizations(t, inline_threshold=inline or 0)
if portal is None:
portal = func
if hasattr(policy, "seetranslator"):
@@ -809,16 +808,14 @@
policy=P_NOVIRTUAL)
assert res == 42
self.check_insns({'malloc_varsize': 1,
- 'getarraysubstruct': 3,
- 'setfield': 2, 'getfield': 1,
+ 'setinteriorfield': 2, 'getinteriorfield': 1,
'getarraysize': 1, 'int_mul': 1})
res = self.timeshift(ll_function, [21, -21, 1], [],
policy=P_NOVIRTUAL)
assert res == -42
self.check_insns({'malloc_varsize': 1,
- 'getarraysubstruct': 3,
- 'setfield': 2, 'getfield': 1,
+ 'setinteriorfield': 2, 'getinteriorfield': 1,
'getarraysize': 1, 'int_mul': 1})
@@ -835,12 +832,14 @@
res = self.timeshift(ll_function, [21, -21, 0], [],
policy=P_NOVIRTUAL)
assert res == 42
- self.check_insns(malloc_varsize=1)
+ self.check_insns(malloc_varsize=1,
+ getinteriorarraysize=1)
res = self.timeshift(ll_function, [21, -21, 1], [],
policy=P_NOVIRTUAL)
assert res == -42
- self.check_insns(malloc_varsize=1)
+ self.check_insns(malloc_varsize=1,
+ getinteriorarraysize=1)
def test_array_of_voids(self):
A = lltype.GcArray(lltype.Void)
More information about the Pypy-commit
mailing list