[pypy-svn] r68694 - in pypy/trunk/pypy: rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/test translator/backendopt translator/backendopt/test
arigo at codespeak.net
arigo at codespeak.net
Wed Oct 21 18:34:54 CEST 2009
Author: arigo
Date: Wed Oct 21 18:34:53 2009
New Revision: 68694
Modified:
pypy/trunk/pypy/rpython/lltypesystem/lloperation.py
pypy/trunk/pypy/rpython/lltypesystem/opimpl.py
pypy/trunk/pypy/rpython/lltypesystem/test/test_lloperation.py
pypy/trunk/pypy/rpython/memory/gctypelayout.py
pypy/trunk/pypy/rpython/memory/test/test_gctypelayout.py
pypy/trunk/pypy/translator/backendopt/mallocv.py
pypy/trunk/pypy/translator/backendopt/test/test_constfold.py
Log:
Improve support of 'immutable_fields' wherever 'immutable'
is supported, notably in optimizations. Add tests.
(merge r68679 to r68681)
Modified: pypy/trunk/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/trunk/pypy/rpython/lltypesystem/lloperation.py Wed Oct 21 18:34:53 2009
@@ -84,12 +84,17 @@
return op_impl
fold = roproperty(get_fold_impl)
- def is_pure(self, *ARGTYPES):
+ def is_pure(self, args_v):
return (self.canfold or # canfold => pure operation
self is llop.debug_assert or # debug_assert is pure enough
# reading from immutable
(self in (llop.getfield, llop.getarrayitem) and
- ARGTYPES[0].TO._hints.get('immutable'))) # XXX: what about ootype immutable arrays?
+ args_v[0].concretetype.TO._hints.get('immutable')) or
+ (self is llop.getfield and # reading from immutable_field
+ 'immutable_fields' in args_v[0].concretetype.TO._hints and
+ args_v[1].value in args_v[0].concretetype.TO
+ ._hints['immutable_fields'].fields))
+ # XXX: what about ootype immutable arrays?
def __repr__(self):
return '<LLOp %s>' % (getattr(self, 'opname', '?'),)
Modified: pypy/trunk/pypy/rpython/lltypesystem/opimpl.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/opimpl.py (original)
+++ pypy/trunk/pypy/rpython/lltypesystem/opimpl.py Wed Oct 21 18:34:53 2009
@@ -142,7 +142,12 @@
# we can constant-fold this if the innermost structure from which we
# read the final field is immutable.
T = lltype.typeOf(innermostcontainer).TO
- if not T._hints.get('immutable'):
+ if T._hints.get('immutable'):
+ pass
+ elif ('immutable_fields' in T._hints and
+ offsets[-1] in T._hints['immutable_fields'].fields):
+ pass
+ else:
raise TypeError("cannot fold getinteriorfield on mutable struct")
assert not isinstance(ob, lltype._interior_ptr)
return ob
@@ -390,7 +395,13 @@
def op_getfield(p, name):
checkptr(p)
- if not lltype.typeOf(p).TO._hints.get('immutable'):
+ TYPE = lltype.typeOf(p).TO
+ if TYPE._hints.get('immutable'):
+ pass
+ elif ('immutable_fields' in TYPE._hints and
+ name in TYPE._hints['immutable_fields'].fields):
+ pass
+ else:
raise TypeError("cannot fold getfield on mutable struct")
return getattr(p, name)
Modified: pypy/trunk/pypy/rpython/lltypesystem/test/test_lloperation.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/test/test_lloperation.py (original)
+++ pypy/trunk/pypy/rpython/lltypesystem/test/test_lloperation.py Wed Oct 21 18:34:53 2009
@@ -4,6 +4,7 @@
from pypy.rpython.ootypesystem import ootype, ooopimpl
from pypy.rpython.llinterp import LLFrame
from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython import rclass
LL_INTERP_OPERATIONS = [name[3:] for name in LLFrame.__dict__.keys()
if name.startswith('op_')]
@@ -50,7 +51,72 @@
return s.x + s.y
res = interpret(llf, [], policy=LowLevelAnnotatorPolicy())
assert res == 5
-
+
+def test_is_pure():
+ from pypy.objspace.flow.model import Variable, Constant
+ assert llop.bool_not.is_pure([Variable()])
+ assert llop.debug_assert.is_pure([Variable()])
+ assert not llop.int_add_ovf.is_pure([Variable(), Variable()])
+ #
+ S1 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed))
+ v_s1 = Variable()
+ v_s1.concretetype = lltype.Ptr(S1)
+ assert not llop.setfield.is_pure([v_s1, Constant('x'), Variable()])
+ assert not llop.getfield.is_pure([v_s1, Constant('y')])
+ #
+ A1 = lltype.GcArray(lltype.Signed)
+ v_a1 = Variable()
+ v_a1.concretetype = lltype.Ptr(A1)
+ assert not llop.setarrayitem.is_pure([v_a1, Variable(), Variable()])
+ assert not llop.getarrayitem.is_pure([v_a1, Variable()])
+ assert llop.getarraysize.is_pure([v_a1])
+ #
+ S2 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
+ hints={'immutable': True})
+ v_s2 = Variable()
+ v_s2.concretetype = lltype.Ptr(S2)
+ assert not llop.setfield.is_pure([v_s2, Constant('x'), Variable()])
+ assert llop.getfield.is_pure([v_s2, Constant('y')])
+ #
+ A2 = lltype.GcArray(lltype.Signed, hints={'immutable': True})
+ v_a2 = Variable()
+ v_a2.concretetype = lltype.Ptr(A2)
+ assert not llop.setarrayitem.is_pure([v_a2, Variable(), Variable()])
+ assert llop.getarrayitem.is_pure([v_a2, Variable()])
+ assert llop.getarraysize.is_pure([v_a2])
+ #
+ accessor = rclass.FieldListAccessor()
+ S3 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
+ hints={'immutable_fields': accessor})
+ accessor.initialize(S3, ['x'])
+ v_s3 = Variable()
+ v_s3.concretetype = lltype.Ptr(S3)
+ assert not llop.setfield.is_pure([v_s3, Constant('x'), Variable()])
+ assert not llop.setfield.is_pure([v_s3, Constant('y'), Variable()])
+ assert llop.getfield.is_pure([v_s3, Constant('x')])
+ assert not llop.getfield.is_pure([v_s3, Constant('y')])
+
+def test_getfield_pure():
+ S1 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed))
+ S2 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
+ hints={'immutable': True})
+ accessor = rclass.FieldListAccessor()
+ S3 = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed),
+ hints={'immutable_fields': accessor})
+ accessor.initialize(S3, ['x'])
+ #
+ s1 = lltype.malloc(S1); s1.x = 45
+ py.test.raises(TypeError, llop.getfield, lltype.Signed, s1, 'x')
+ s2 = lltype.malloc(S2); s2.x = 45
+ assert llop.getfield(lltype.Signed, s2, 'x') == 45
+ s3 = lltype.malloc(S3); s3.x = 46; s3.y = 47
+ assert llop.getfield(lltype.Signed, s3, 'x') == 46
+ py.test.raises(TypeError, llop.getfield, lltype.Signed, s3, 'y')
+ #
+ py.test.raises(TypeError, llop.getinteriorfield, lltype.Signed, s1, 'x')
+ assert llop.getinteriorfield(lltype.Signed, s2, 'x') == 45
+ assert llop.getinteriorfield(lltype.Signed, s3, 'x') == 46
+ py.test.raises(TypeError, llop.getinteriorfield, lltype.Signed, s3, 'y')
# ___________________________________________________________________________
# This tests that the LLInterpreter and the LL_OPERATIONS tables are in sync.
Modified: pypy/trunk/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/trunk/pypy/rpython/memory/gctypelayout.py Wed Oct 21 18:34:53 2009
@@ -350,11 +350,16 @@
def gc_pointers_inside(v, adr, mutable_only=False):
t = lltype.typeOf(v)
if isinstance(t, lltype.Struct):
- if mutable_only and t._hints.get('immutable'):
- return
+ skip = ()
+ if mutable_only:
+ if t._hints.get('immutable'):
+ return
+ if 'immutable_fields' in t._hints:
+ skip = t._hints['immutable_fields'].fields
for n, t2 in t._flds.iteritems():
if isinstance(t2, lltype.Ptr) and t2.TO._gckind == 'gc':
- yield adr + llmemory.offsetof(t, n)
+ if n not in skip:
+ yield adr + llmemory.offsetof(t, n)
elif isinstance(t2, (lltype.Array, lltype.Struct)):
for a in gc_pointers_inside(getattr(v, n),
adr + llmemory.offsetof(t, n),
Modified: pypy/trunk/pypy/rpython/memory/test/test_gctypelayout.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/test/test_gctypelayout.py (original)
+++ pypy/trunk/pypy/rpython/memory/test/test_gctypelayout.py Wed Oct 21 18:34:53 2009
@@ -1,7 +1,8 @@
import py
from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder, GCData
from pypy.rpython.memory.gctypelayout import offsets_to_gc_pointers
-from pypy.rpython.lltypesystem import lltype, rclass
+from pypy.rpython.memory.gctypelayout import gc_pointers_inside
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass
from pypy.rpython.test.test_llinterp import get_interpreter
from pypy.objspace.flow.model import Constant
@@ -90,3 +91,31 @@
interp, graph = get_interpreter(f, [], backendopt=True)
assert interp.eval_graph(graph, []) == 11001
assert graph.startblock.exits[0].args == [Constant(11001, lltype.Signed)]
+
+def test_gc_pointers_inside():
+ from pypy.rpython import rclass
+ PT = lltype.Ptr(lltype.GcStruct('T'))
+ S1 = lltype.GcStruct('S', ('x', PT), ('y', PT))
+ S2 = lltype.GcStruct('S', ('x', PT), ('y', PT),
+ hints={'immutable': True})
+ accessor = rclass.FieldListAccessor()
+ S3 = lltype.GcStruct('S', ('x', PT), ('y', PT),
+ hints={'immutable_fields': accessor})
+ accessor.initialize(S3, ['x'])
+ #
+ s1 = lltype.malloc(S1)
+ adr = llmemory.cast_ptr_to_adr(s1)
+ lst = list(gc_pointers_inside(s1._obj, adr, mutable_only=True))
+ expected = [adr + llmemory.offsetof(S1, 'x'),
+ adr + llmemory.offsetof(S1, 'y')]
+ assert lst == expected or lst == expected[::-1]
+ #
+ s2 = lltype.malloc(S2)
+ adr = llmemory.cast_ptr_to_adr(s2)
+ lst = list(gc_pointers_inside(s2._obj, adr, mutable_only=True))
+ assert lst == []
+ #
+ s3 = lltype.malloc(S3)
+ adr = llmemory.cast_ptr_to_adr(s3)
+ lst = list(gc_pointers_inside(s3._obj, adr, mutable_only=True))
+ assert lst == [adr + llmemory.offsetof(S3, 'y')]
Modified: pypy/trunk/pypy/translator/backendopt/mallocv.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/mallocv.py (original)
+++ pypy/trunk/pypy/translator/backendopt/mallocv.py Wed Oct 21 18:34:53 2009
@@ -1046,7 +1046,7 @@
op = getattr(llop, opname)
except AttributeError:
return
- if not op.is_pure(*[v.concretetype for v in args_v]):
+ if not op.is_pure(args_v):
return
try:
result = op(RESTYPE, *args)
Modified: pypy/trunk/pypy/translator/backendopt/test/test_constfold.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/test/test_constfold.py (original)
+++ pypy/trunk/pypy/translator/backendopt/test/test_constfold.py Wed Oct 21 18:34:53 2009
@@ -4,6 +4,7 @@
from pypy.rpython.llinterp import LLInterpreter
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython import rclass
from pypy.rlib import objectmodel
from pypy.translator.backendopt.constfold import constant_fold_graph
from pypy import conftest
@@ -26,8 +27,10 @@
assert res == expected_result
-def test_simple():
- S1 = lltype.GcStruct('S1', ('x', lltype.Signed), hints={'immutable': True})
+def test_simple(S1=None):
+ if S1 is None:
+ S1 = lltype.GcStruct('S1', ('x', lltype.Signed),
+ hints={'immutable': True})
s1 = lltype.malloc(S1)
s1.x = 123
def g(y):
@@ -42,6 +45,14 @@
check_graph(graph, [], 124, t)
+def test_immutable_fields():
+ accessor = rclass.FieldListAccessor()
+ S2 = lltype.GcStruct('S2', ('x', lltype.Signed),
+ hints={'immutable_fields': accessor})
+ accessor.initialize(S2, ['x'])
+ test_simple(S2)
+
+
def test_along_link():
S1 = lltype.GcStruct('S1', ('x', lltype.Signed), hints={'immutable': True})
s1 = lltype.malloc(S1)
More information about the Pypy-commit
mailing list