[pypy-svn] r47815 - in pypy/dist/pypy/rpython/memory/gctransform: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Wed Oct 24 13:15:38 CEST 2007
Author: cfbolz
Date: Wed Oct 24 13:15:37 2007
New Revision: 47815
Modified:
pypy/dist/pypy/rpython/memory/gctransform/framework.py
pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py
pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py
Log:
a small heuristic to find initializing stores (basically stores that happen
directly after mallocs without any operation in between that can cause a
malloc). Those stores don't need a write barrier for the generational GC.
Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Wed Oct 24 13:15:37 2007
@@ -28,6 +28,64 @@
flags = op.args[1].value
return flags['flavor'] == 'gc' and not flags.get('nocollect', False)
+def find_initializing_stores(collect_analyzer, graph):
+ from pypy.objspace.flow.model import mkentrymap
+ entrymap = mkentrymap(graph)
+ # a bit of a hackish analysis: if a block contains a malloc and check that
+ # the result is not zero, then the block following the True link will
+ # usually initialize the newly allocated object
+ result = {}
+ def find_in_block(block, mallocvars):
+ for i, op in enumerate(block.operations):
+ if op.opname in ("cast_pointer", "same_as"):
+ if op.args[0] in mallocvars:
+ mallocvars[op.result] = True
+ elif op.opname in ("setfield", "setarrayitem", "setinteriorfield"):
+ if (op.args[0] in mallocvars and
+ op.args[-1].concretetype.TO._gckind == "gc"):
+ result[op] = True
+ else:
+ if collect_analyzer.analyze(op):
+ return
+ for exit in block.exits:
+ if len(entrymap[exit.target]) != 1:
+ continue
+ newmallocvars = {}
+ for i, var in enumerate(exit.args):
+ if var in mallocvars:
+ newmallocvars[exit.target.inputargs[i]] = True
+ if newmallocvars:
+ find_in_block(exit.target, newmallocvars)
+ mallocnum = 0
+ blockset = set(graph.iterblocks())
+ while blockset:
+ block = blockset.pop()
+ if len(block.operations) < 2:
+ continue
+ mallocop = block.operations[-2]
+ checkop = block.operations[-1]
+ if not (mallocop.opname == "malloc" and
+ checkop.opname == "ptr_nonzero" and
+ mallocop.result is checkop.args[0] and
+ block.exitswitch is checkop.result):
+ continue
+ exits = [exit for exit in block.exits if exit.llexitcase]
+ if len(exits) != 1:
+ continue
+ exit = exits[0]
+ if len(entrymap[exit.target]) != 1:
+ continue
+ try:
+ index = exit.args.index(mallocop.result)
+ except ValueError:
+ continue
+ target = exit.target
+ mallocvars = {target.inputargs[index]: True}
+ mallocnum += 1
+ find_in_block(target, mallocvars)
+ print graph.name, mallocnum, len(result)
+ return result
+
ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
class FrameworkGCTransformer(GCTransformer):
@@ -439,6 +497,14 @@
for typeid, TYPE in all:
f.write("%s %s\n" % (typeid, TYPE))
+ def transform_graph(self, graph):
+ if self.write_barrier_ptr:
+ self.initializing_stores = find_initializing_stores(
+ self.collect_analyzer, graph)
+ super(FrameworkGCTransformer, self).transform_graph(graph)
+ if self.write_barrier_ptr:
+ self.initializing_stores = None
+
def gct_direct_call(self, hop):
if self.collect_analyzer.analyze(hop.spaceop):
livevars = self.push_roots(hop)
@@ -603,7 +669,8 @@
# ok
if (self.write_barrier_ptr is not None
and not isinstance(v_newvalue, Constant)
- and v_struct.concretetype.TO._gckind == "gc"):
+ and v_struct.concretetype.TO._gckind == "gc"
+ and hop.spaceop not in self.initializing_stores):
self.write_barrier_calls += 1
v_oldvalue = hop.genop('g' + opname[1:],
hop.inputargs()[:-1],
Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py Wed Oct 24 13:15:37 2007
@@ -1,14 +1,17 @@
from pypy.objspace.flow.model import Constant, SpaceOperation
from pypy.annotation.model import SomeInteger
from pypy.rpython.memory.gc.marksweep import MarkSweepGC
-from pypy.rpython.memory.gctransform.test.test_transform import rtype
+from pypy.rpython.memory.gctransform.test.test_transform import rtype, \
+ rtype_and_transform
from pypy.rpython.memory.gctransform.transform import GcHighLevelOp
-from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer, CollectAnalyzer
+from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer, \
+ CollectAnalyzer, find_initializing_stores
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.rtyper import LowLevelOpList
from pypy.translator.c.gc import FrameworkGcPolicy
from pypy.translator.translator import TranslationContext, graphof
from pypy.translator.unsimplify import varoftype
+from pypy.translator.exceptiontransform import ExceptionTransformer
from pypy import conftest
import py
@@ -119,3 +122,45 @@
[varoftype(ARRAYPTR2), varoftype(lltype.Signed),
Constant('b', lltype.Void), varoftype(PTR_TYPE2)],
varoftype(lltype.Void)))
+
+def test_find_initializing_stores():
+
+ class A(object):
+ pass
+ class B(object):
+ pass
+ def f():
+ a = A()
+ b = B()
+ b.a = a
+ t = rtype(f, [])
+ etrafo = ExceptionTransformer(t)
+ graphs = etrafo.transform_completely()
+ collect_analyzer = CollectAnalyzer(t)
+ init_stores = find_initializing_stores(collect_analyzer, t.graphs[0])
+ assert len(init_stores) == 1
+
+def test_find_initializing_stores_across_blocks():
+
+ class A(object):
+ pass
+ class B(object):
+ pass
+ def f(x):
+ a1 = A()
+ a2 = A()
+ a = A()
+ b = B()
+ b.a = a
+ if x:
+ b.b = a1
+ b.c = a2
+ else:
+ b.c = a1
+ b.b = a2
+ t = rtype(f, [int])
+ etrafo = ExceptionTransformer(t)
+ graphs = etrafo.transform_completely()
+ collect_analyzer = CollectAnalyzer(t)
+ init_stores = find_initializing_stores(collect_analyzer, t.graphs[0])
+ assert len(init_stores) == 5
Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform/test/test_transform.py Wed Oct 24 13:15:37 2007
@@ -149,6 +149,8 @@
t.buildannotator().build_types(func, inputtypes)
if specialize:
t.buildrtyper().specialize()
+ if conftest.option.view:
+ t.view()
return t
def rtype_and_transform(func, inputtypes, transformcls, specialize=True, check=True):
More information about the Pypy-commit
mailing list