[pypy-svn] r21052 - in pypy/dist/pypy/jit: . test
arigo at codespeak.net
arigo at codespeak.net
Sun Dec 11 18:05:59 CET 2005
Author: arigo
Date: Sun Dec 11 18:05:57 2005
New Revision: 21052
Modified:
pypy/dist/pypy/jit/llabstractinterp.py
pypy/dist/pypy/jit/test/test_llabstractinterp.py
Log:
Virtual arrays.
Modified: pypy/dist/pypy/jit/llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp.py (original)
+++ pypy/dist/pypy/jit/llabstractinterp.py Sun Dec 11 18:05:57 2005
@@ -101,15 +101,16 @@
ll_no_return_value = LLRuntimeValue(const(None, lltype.Void))
-class LLVirtualStruct(LLAbstractValue):
- """Stands for a pointer to a malloc'ed structure; the structure is not
- malloc'ed so far, but we record which fields have which value.
- """
+class LLVirtualContainer(LLAbstractValue):
+
parent = None
parentindex = None
- def __init__(self, STRUCT):
- self.T = STRUCT
+ def __init__(self, T, a_length=None):
+ assert (a_length is not None) == T._is_varsize()
+ self.T = T
+ self.a_length = a_length
+ self.names = self.getnames()
self.fields = {}
def getconcretetype(self):
@@ -132,13 +133,17 @@
try:
return self.fields[name]
except KeyError:
- T = getattr(self.T, name)
+ T = self.fieldtype(name)
if isinstance(T, lltype.ContainerType):
# reading a substructure
- a_substr = LLVirtualStruct(T)
- a_substr.setparent(self, name)
- self.fields[name] = a_substr
- return a_substr
+ if T._is_varsize():
+ a_length = self.a_length
+ else:
+ a_length = None
+ a_sub = virtualcontainer(T, a_length)
+ a_sub.setparent(self, name)
+ self.fields[name] = a_sub
+ return a_sub
else:
# no value ever set, return a default
return LLRuntimeValue(const(T._defl()))
@@ -150,7 +155,7 @@
if self in memo:
return memo[self] # already seen
else:
- result = LLVirtualStruct(self.T)
+ result = virtualcontainer(self.T, self.a_length)
memo[self] = result
if self.parent is not None:
# build the parent first -- note that
@@ -161,7 +166,7 @@
# cannot keep lazy fields around: the copy is expected to have
# only variables, not constants
- for name in self.T._names:
+ for name in self.names:
a = self.getfield(name).with_fresh_variables(memo)
result.fields[name] = a
return result
@@ -177,7 +182,14 @@
print 'force:', op
builder.residual_operations.append(op)
else:
- op = SpaceOperation('malloc', [const(self.T, lltype.Void)], v_result)
+ if self.T._is_varsize():
+ op = SpaceOperation('malloc_varsize', [
+ const(self.T, lltype.Void),
+ self.a_length.forcevarorconst(builder)],
+ v_result)
+ else:
+ op = SpaceOperation('malloc', [const(self.T, lltype.Void)],
+ v_result)
print 'force:', op
builder.residual_operations.append(op)
self.buildcontent(builder, v_result)
@@ -187,12 +199,12 @@
def buildcontent(self, builder, v_target):
# initialize all fields
- for name in self.T._names:
+ for name in self.names:
if name in self.fields:
a_value = self.fields[name]
- T = getattr(self.T, name)
+ T = self.fieldtype(name)
if isinstance(T, lltype.ContainerType):
- # initialize the substructure
+ # initialize the substructure/subarray
v_subptr = newvar(lltype.Ptr(T))
op = SpaceOperation('getsubstruct',
[v_target, const(name, lltype.Void)],
@@ -203,39 +215,22 @@
a_value.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))
+ op = self.setop(v_target, name, v_value)
print 'force:', op
builder.residual_operations.append(op)
- def rec_fields(self):
- # -- not used at the moment --
- # 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, LLVirtualStruct)
- for obj, fld in a_value.rec_fields():
- yield obj, fld
- else:
- yield self, name
-
def getruntimevars(self, memo):
result = []
if self not in memo:
memo[self] = True
if self.parent is not None:
result.extend(self.parent.getruntimevars(memo))
- for name in self.T._names:
+ for name in self.names:
result.extend(self.getfield(name).getruntimevars(memo))
return result
def match(self, other, memo):
- if not isinstance(other, LLVirtualStruct):
+ if self.__class__ is not other.__class__:
return False
if (False, self) in memo:
return other is memo[False, self]
@@ -244,7 +239,10 @@
memo[False, self] = other
memo[True, other] = self
assert self.T == other.T
- for name in self.T._names:
+ if self.a_length is not None:
+ if not self.a_length.match(other.a_length, memo):
+ return False
+ for name in self.names:
a1 = self.getfield(name)
a2 = other.getfield(name)
if not a1.match(a2, memo):
@@ -252,6 +250,51 @@
else:
return True
+
+class LLVirtualStruct(LLVirtualContainer):
+ """Stands for a pointer to a malloc'ed structure; the structure is not
+ malloc'ed so far, but we record which fields have which value.
+ """
+ def getnames(self):
+ return self.T._names
+
+ def fieldtype(self, name):
+ return getattr(self.T, name)
+
+ def setop(self, v_target, name, v_value):
+ return SpaceOperation('setfield', [v_target,
+ const(name, lltype.Void),
+ v_value],
+ newvar(lltype.Void))
+
+class LLVirtualArray(LLVirtualContainer):
+ """Stands for a pointer to a malloc'ed array; the array is not
+ malloc'ed so far, but we record which fields have which value -- here
+ a field is an item, indexed by an integer instead of a string field name.
+ """
+ def getnames(self):
+ c = self.a_length.maybe_get_constant()
+ assert c is not None
+ return range(c.value)
+
+ def fieldtype(self, index):
+ return self.T.OF
+
+ def setop(self, v_target, name, v_value):
+ return SpaceOperation('setarrayitem', [v_target,
+ const(name, lltype.Signed),
+ v_value],
+ newvar(lltype.Void))
+
+def virtualcontainer(T, a_length=None):
+ if isinstance(T, lltype.Struct):
+ cls = LLVirtualStruct
+ elif isinstance(T, lltype.Array):
+ cls = LLVirtualArray
+ else:
+ raise TypeError("unsupported container type %r" % (T,))
+ return cls(T, a_length)
+
# ____________________________________________________________
class BlockState(object):
@@ -656,17 +699,23 @@
return self.residualize(op, [a_ptr, a_attrname], constant_op)
def op_getsubstruct(self, op, a_ptr, a_attrname):
- if isinstance(a_ptr, LLVirtualStruct):
+ if isinstance(a_ptr, LLVirtualContainer):
c_attrname = a_attrname.maybe_get_constant()
assert c_attrname is not None
- # this should return new LLVirtualStruct as well
+ # this should return new LLVirtualContainer as well
return a_ptr.getfield(c_attrname.value)
return self.residualize(op, [a_ptr, a_attrname], getattr)
def op_getarraysize(self, op, a_ptr):
+ if isinstance(a_ptr, LLVirtualArray):
+ return a_ptr.a_length
return self.residualize(op, [a_ptr], len)
def op_getarrayitem(self, op, a_ptr, a_index):
+ if isinstance(a_ptr, LLVirtualArray):
+ c_index = a_index.maybe_get_constant()
+ if c_index is not None:
+ return a_ptr.getfield(c_index.value)
constant_op = None
T = a_ptr.getconcretetype().TO
if T._hints.get('immutable', False):
@@ -679,6 +728,10 @@
return LLVirtualStruct(c_T.value)
def op_malloc_varsize(self, op, a_T, a_size):
+ if a_size.maybe_get_constant() is not None:
+ c_T = a_T.maybe_get_constant()
+ assert c_T is not None
+ return virtualcontainer(c_T.value, a_length=a_size)
return self.residualize(op, [a_T, a_size])
def op_setfield(self, op, a_ptr, a_attrname, a_value):
@@ -690,6 +743,11 @@
return self.residualize(op, [a_ptr, a_attrname, a_value])
def op_setarrayitem(self, op, a_ptr, a_index, a_value):
+ if isinstance(a_ptr, LLVirtualArray):
+ c_index = a_index.maybe_get_constant()
+ if c_index is not None:
+ a_ptr.setfield(c_index.value, a_value)
+ return ll_no_return_value
return self.residualize(op, [a_ptr, a_index, a_value])
def op_cast_pointer(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 Sun Dec 11 18:05:57 2005
@@ -295,3 +295,14 @@
# non-concrete values, so 'insns' should only see the residualized
# ll_function().
assert insns == {'direct_call': 1, 'int_add': 2}
+
+def test_virtual_array():
+ A = lltype.GcArray(lltype.Signed)
+ def ll_function(k, l):
+ a = lltype.malloc(A, 3)
+ a[0] = k
+ a[1] = 12
+ a[2] = l
+ return (a[0] + a[1]) + a[2]
+ graph2, insns = abstrinterp(ll_function, [7, 983], [0])
+ assert insns == {'int_add': 1}
More information about the Pypy-commit
mailing list