[pypy-svn] pypy default: (fijal, arigo)
arigo
commits-noreply at bitbucket.org
Sat Mar 12 22:36:43 CET 2011
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r42539:0646aa086da7
Date: 2011-03-12 15:52 -0500
http://bitbucket.org/pypy/pypy/changeset/0646aa086da7/
Log: (fijal, arigo)
Improve on the previous check-in to detect fresh mallocs as long as
they are in the same graph. That's probably good enough.
diff --git a/pypy/translator/backendopt/test/test_writeanalyze.py b/pypy/translator/backendopt/test/test_writeanalyze.py
--- a/pypy/translator/backendopt/test/test_writeanalyze.py
+++ b/pypy/translator/backendopt/test/test_writeanalyze.py
@@ -63,6 +63,69 @@
result = wa.analyze_direct_call(fgraph)
assert not result
+ def test_write_to_new_struct_2(self):
+ class A(object):
+ pass
+ def f(x):
+ a = A()
+ # a few extra blocks
+ i = 10
+ while i > 0:
+ i -= 1
+ # done
+ a.baz = x # writes to a fresh new struct are ignored
+ return a
+ t, wa = self.translate(f, [int])
+ fgraph = graphof(t, f)
+ result = wa.analyze_direct_call(fgraph)
+ assert not result
+
+ def test_write_to_new_struct_3(self):
+ class A(object):
+ pass
+ prebuilt = A()
+ def f(x):
+ if x > 5:
+ a = A()
+ else:
+ a = A()
+ a.baz = x
+ return a
+ t, wa = self.translate(f, [int])
+ fgraph = graphof(t, f)
+ result = wa.analyze_direct_call(fgraph)
+ assert not result
+
+ def test_write_to_new_struct_4(self):
+ class A(object):
+ pass
+ prebuilt = A()
+ def f(x):
+ if x > 5:
+ a = A()
+ else:
+ a = prebuilt
+ a.baz = x
+ return a
+ t, wa = self.translate(f, [int])
+ fgraph = graphof(t, f)
+ result = wa.analyze_direct_call(fgraph)
+ assert len(result) == 1 and 'baz' in list(result)[0][-1]
+
+ def test_write_to_new_struct_5(self):
+ class A(object):
+ baz = 123
+ def f(x):
+ if x:
+ a = A()
+ else:
+ a = A()
+ a.baz += 1
+ t, wa = self.translate(f, [int])
+ fgraph = graphof(t, f)
+ result = wa.analyze_direct_call(fgraph)
+ assert not result
+
def test_method(self):
class A(object):
def f(self):
diff --git a/pypy/translator/backendopt/writeanalyze.py b/pypy/translator/backendopt/writeanalyze.py
--- a/pypy/translator/backendopt/writeanalyze.py
+++ b/pypy/translator/backendopt/writeanalyze.py
@@ -1,3 +1,4 @@
+from pypy.objspace.flow.model import Variable
from pypy.translator.backendopt import graphanalyze
from pypy.rpython.ootypesystem import ootype
@@ -27,13 +28,13 @@
return result is top_set
def analyze_simple_operation(self, op, graphinfo):
- if graphinfo and op.args[0] in graphinfo:
- return empty_set
if op.opname in ("setfield", "oosetfield"):
- return frozenset([
- ("struct", op.args[0].concretetype, op.args[1].value)])
+ if graphinfo is None or not graphinfo.is_fresh_malloc(op.args[0]):
+ return frozenset([
+ ("struct", op.args[0].concretetype, op.args[1].value)])
elif op.opname == "setarrayitem":
- return self._array_result(op.args[0].concretetype)
+ if graphinfo is None or not graphinfo.is_fresh_malloc(op.args[0]):
+ return self._array_result(op.args[0].concretetype)
return empty_set
def _array_result(self, TYPE):
@@ -49,16 +50,43 @@
return graphanalyze.GraphAnalyzer.analyze_external_method(self, op, TYPE, meth)
def compute_graph_info(self, graph):
- newstructs = set()
- for block in graph.iterblocks():
+ return FreshMallocs(graph)
+
+
+class FreshMallocs(object):
+ def __init__(self, graph):
+ self.nonfresh = set(graph.getargs())
+ pendingblocks = list(graph.iterblocks())
+ self.allvariables = set()
+ for block in pendingblocks:
+ self.allvariables.update(block.inputargs)
+ pendingblocks.reverse()
+ while pendingblocks:
+ block = pendingblocks.pop()
for op in block.operations:
+ self.allvariables.add(op.result)
if (op.opname == 'malloc' or op.opname == 'malloc_varsize'
or op.opname == 'new'):
- newstructs.add(op.result)
+ continue
elif op.opname in ('cast_pointer', 'same_as'):
- if op.args[0] in newstructs:
- newstructs.add(op.result)
- return newstructs
+ if self.is_fresh_malloc(op.args[0]):
+ continue
+ self.nonfresh.add(op.result)
+ for link in block.exits:
+ self.nonfresh.update(link.getextravars())
+ self.allvariables.update(link.getextravars())
+ prevlen = len(self.nonfresh)
+ for v1, v2 in zip(link.args, link.target.inputargs):
+ if not self.is_fresh_malloc(v1):
+ self.nonfresh.add(v2)
+ if len(self.nonfresh) > prevlen:
+ pendingblocks.append(link.target)
+
+ def is_fresh_malloc(self, v):
+ if not isinstance(v, Variable):
+ return False
+ assert v in self.allvariables
+ return v not in self.nonfresh
class ReadWriteAnalyzer(WriteAnalyzer):
More information about the Pypy-commit
mailing list