[pypy-svn] r21005 - in pypy/dist/pypy/jit: . test
arigo at codespeak.net
arigo at codespeak.net
Sat Dec 10 16:35:25 CET 2005
Author: arigo
Date: Sat Dec 10 16:35:23 2005
New Revision: 21005
Modified:
pypy/dist/pypy/jit/llabstractinterp.py
pypy/dist/pypy/jit/test/test_llabstractinterp.py
Log:
(pedronis, mwh, arigo)
First shot at substructures. For now, just enough to pass the test.
Modified: pypy/dist/pypy/jit/llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp.py (original)
+++ pypy/dist/pypy/jit/llabstractinterp.py Sat Dec 10 16:35:23 2005
@@ -49,7 +49,7 @@
def maybe_get_constant(self):
return const(self.value)
- def with_fresh_variables(self, to_be_stored_into):
+ def with_fresh_variables(self, memo):
return self
def match(self, other):
@@ -62,9 +62,14 @@
if isinstance(orig_v, Variable):
self.copy_v = Variable(orig_v)
self.copy_v.concretetype = orig_v.concretetype
- else:
+ elif isinstance(orig_v, Constant):
# we can share the Constant()
self.copy_v = orig_v
+ elif isinstance(orig_v, lltype.LowLevelType):
+ # hackish interface :-( we accept a type too
+ self.copy_v = newvar(orig_v)
+ else:
+ raise TypeError(repr(orig_v))
def __repr__(self):
return '<runtime %r>' % (self.copy_v,)
@@ -84,8 +89,8 @@
else:
return None
- def with_fresh_variables(self, to_be_stored_into):
- return LLRuntimeValue(orig_v=to_be_stored_into)
+ def with_fresh_variables(self, memo):
+ return LLRuntimeValue(self.getconcretetype())
def match(self, other):
if isinstance(other, LLRuntimeValue):
@@ -100,52 +105,122 @@
class VirtualStruct(object):
+ parent = None
+ parentindex = None
+
def __init__(self, STRUCT):
self.T = STRUCT
self.fields = {}
+ def setparent(self, parent, parentindex):
+ self.parent = parent
+ self.parentindex = parentindex
+
+ def topmostparent(self):
+ obj = self
+ while obj.parent is not None:
+ obj = obj.parent
+ return obj
+
def getfield(self, name):
try:
return self.fields[name]
except KeyError:
T = getattr(self.T, name)
- return LLRuntimeValue(const(T._defl()))
+ if isinstance(T, lltype.ContainerType):
+ # reading a substructure
+ substr = VirtualStruct(T)
+ substr.setparent(self, name)
+ a_result = LLVirtualPtr(substr)
+ self.fields[name] = a_result
+ return a_result
+ else:
+ # no value ever set, return a default
+ return LLRuntimeValue(const(T._defl()))
def setfield(self, name, value):
self.fields[name] = value
- def copy(self):
- result = VirtualStruct(self.T)
- for name, a_value in self.fields.items():
- v = newvar(a_value.getconcretetype())
- result.fields[name] = a_value.with_fresh_variables(v)
- return result
+ def copy(self, memo):
+ if self in memo:
+ return memo[self] # already seen
+ else:
+ result = VirtualStruct(self.T)
+ memo[self] = result
+ if self.parent is not None:
+ # build the parent first -- note that parent.copy() will pick
+ # up 'result' again, because it is already in the memo
+ result.setparent(self.parent.copy(memo), self.parentindex)
+
+ for name, a_value in self.fields.items():
+ a = a_value.with_fresh_variables(memo)
+ result.fields[name] = a
+ return result
def force(self, builder):
v_result = newvar(lltype.Ptr(self.T))
- op = SpaceOperation('malloc', [const(self.T, lltype.Void)], v_result)
- print 'force:', op
- builder.residual_operations.append(op)
- # initialize all fields by relying on the assumption that the
- # structure is initialized to zeros
+ if self.parent is not None:
+ v_parent = self.parent.force(builder)
+ op = SpaceOperation('getsubstruct', [v_parent,
+ const(self.parentindex,
+ lltype.Void)],
+ v_result)
+ print 'force:', op
+ builder.residual_operations.append(op)
+ else:
+ op = SpaceOperation('malloc', [const(self.T, lltype.Void)], v_result)
+ print 'force:', op
+ builder.residual_operations.append(op)
+ self.buildcontent(builder, v_result)
+ return v_result
+
+ def buildcontent(self, builder, v_target):
+ # initialize all fields
for name in self.T._names:
if name in self.fields:
- v_value = self.fields[name].forcevarorconst(builder)
- op = SpaceOperation('setfield', [v_result,
- const(name, lltype.Void),
- v_value],
- newvar(lltype.Void))
- print 'force:', op
- builder.residual_operations.append(op)
- return v_result
+ a_value = self.fields[name]
+ T = getattr(self.T, name)
+ if isinstance(T, lltype.ContainerType):
+ # initialize the substructure
+ v_subptr = newvar(lltype.Ptr(T))
+ op = SpaceOperation('getsubstruct',
+ [v_target, const(name, lltype.Void)],
+ v_subptr)
+ print 'force:', op
+ builder.residual_operations.append(op)
+ assert isinstance(a_value, LLVirtualPtr)
+ a_value.containerobj.buildcontent(builder, v_subptr)
+ else:
+ v_value = a_value.forcevarorconst(builder)
+ op = SpaceOperation('setfield', [v_target,
+ const(name, lltype.Void),
+ v_value],
+ newvar(lltype.Void))
+ print 'force:', op
+ builder.residual_operations.append(op)
+
+ def rec_fields(self):
+ # enumerate all the fields of this structure and each of
+ # its substructures
+ for name in self.T._names:
+ a_value = self.getfield(name)
+ T = getattr(self.T, name)
+ if isinstance(T, lltype.ContainerType):
+ assert isinstance(a_value, LLVirtualPtr)
+ for obj, fld in a_value.containerobj.rec_fields():
+ yield obj, fld
+ else:
+ yield self, name
def getruntimevars(self):
result = []
- for name in self.T._names:
- result.extend(self.getfield(name).getruntimevars())
+ for obj, name in self.topmostparent().rec_fields():
+ result.extend(obj.getfield(name).getruntimevars())
return result
def match(self, other):
+ if self is other:
+ return True
assert self.T == other.T
for name in self.T._names:
a1 = self.getfield(name)
@@ -176,8 +251,8 @@
def maybe_get_constant(self):
return None
- def with_fresh_variables(self, to_be_stored_into):
- return LLVirtualPtr(self.containerobj.copy())
+ def with_fresh_variables(self, memo):
+ return LLVirtualPtr(self.containerobj.copy(memo))
def match(self, other):
if isinstance(other, LLVirtualPtr):
@@ -349,8 +424,12 @@
origblock = state.origblock
builder = BlockBuilder(self.interp)
newinputargs = []
+ memo = {}
for v, a in zip(origblock.inputargs, state.args_a):
- a = a.with_fresh_variables(to_be_stored_into=v)
+ a = a.with_fresh_variables(memo)
+ # try to preserve the name
+ if isinstance(a, LLRuntimeValue) and isinstance(a.copy_v, Variable):
+ a.copy_v.rename(v)
builder.bindings[v] = a
newinputargs.extend(a.getruntimevars())
print
@@ -438,9 +517,7 @@
if any_concrete:
return LLConcreteValue(concreteresult)
else:
- c = Constant(concreteresult)
- c.concretetype = typeOf(concreteresult)
- return LLRuntimeValue(c)
+ return LLRuntimeValue(const(concreteresult))
def residual(self, opname, args_a, a_result):
v_result = a_result.forcevarorconst(self)
@@ -542,9 +619,7 @@
ARGS, lltype.typeOf(origfptr).TO.RESULT)
fptr = lltype.functionptr(
TYPE, graphstate.copygraph.name, graph=graphstate.copygraph)
- fconst = Constant(fptr)
- fconst.concretetype = lltype.typeOf(fptr)
- a_func = LLRuntimeValue(fconst)
+ a_func = LLRuntimeValue(const(fptr))
self.residual("direct_call", [a_func] + list(args_a), a_result)
return a_result
@@ -560,6 +635,11 @@
return self.residualize(op, [a_ptr, a_attrname], constant_op)
def op_getsubstruct(self, op, a_ptr, a_attrname):
+ if isinstance(a_ptr, LLVirtualPtr):
+ c_attrname = a_attrname.maybe_get_constant()
+ assert c_attrname is not None
+ # this should return a new LLVirtualPtr
+ return a_ptr.containerobj.getfield(c_attrname.value)
return self.residualize(op, [a_ptr, a_attrname], getattr)
def op_getarraysize(self, op, a_ptr):
Modified: pypy/dist/pypy/jit/test/test_llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/test/test_llabstractinterp.py (original)
+++ pypy/dist/pypy/jit/test/test_llabstractinterp.py Sat Dec 10 16:35:23 2005
@@ -192,3 +192,14 @@
return l+1
graph2, insns = abstrinterp(ll_function, [7], [0])
assert insns == {}
+
+def test_inlined_substructure():
+ S = lltype.Struct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+ def ll_function(k):
+ t = lltype.malloc(T)
+ t.s.n = k
+ l = t.s.n
+ return l
+ graph2, insns = abstrinterp(ll_function, [7], [0])
+ assert insns == {}
More information about the Pypy-commit
mailing list