[pypy-svn] r37560 - in pypy/dist/pypy: jit/hintannotator jit/hintannotator/test jit/timeshifter jit/timeshifter/test rpython/lltypesystem
arigo at codespeak.net
arigo at codespeak.net
Mon Jan 29 19:06:52 CET 2007
Author: arigo
Date: Mon Jan 29 19:06:48 2007
New Revision: 37560
Modified:
pypy/dist/pypy/jit/hintannotator/bookkeeper.py
pypy/dist/pypy/jit/hintannotator/model.py
pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
pypy/dist/pypy/jit/timeshifter/test/test_portal.py
pypy/dist/pypy/jit/timeshifter/transform.py
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
Log:
Detect green calls in compute_at_fixpoint() already. This allows helper
functions like isinstance() to return a green result for green arguments,
as expected.
Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original)
+++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Mon Jan 29 19:06:48 2007
@@ -3,8 +3,9 @@
from pypy.tool.ansi_print import ansi_log
from pypy.objspace.flow.model import copygraph, SpaceOperation, Constant
from pypy.annotation import model as annmodel
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, lloperation
from pypy.tool.algo.unionfind import UnionFind
+from pypy.translator.backendopt import graphanalyze
TLS = tlsobject()
@@ -66,6 +67,20 @@
self.tsgraphs.update(other.tsgraphs)
+class ImpurityAnalyzer(graphanalyze.GraphAnalyzer):
+ """An impure graph has side-effects or depends on state that
+ can be mutated. A pure graph always gives the same answer for
+ given arguments."""
+
+ def analyze_exceptblock(self, block, seen=None):
+ raise AssertionError("graphs here should be exception-transformed")
+
+ def operation_is_true(self, op):
+ operation = lloperation.LL_OPERATIONS[op.opname]
+ ARGTYPES = [v.concretetype for v in op.args]
+ return not operation.is_pure(*ARGTYPES)
+
+
class HintBookkeeper(object):
def __init__(self, hannotator):
@@ -143,15 +158,34 @@
hs_red = hintmodel.variableoftype(v.concretetype)
self.annotator.setbinding(v, hs_red)
+ # is_green_call() is only meaningful at fixpoint,
+ # so initialize the state here
+ t = self.annotator.base_translator
+ self.impurity_analyzer = ImpurityAnalyzer(t)
+
# propagate the green/red constraints
log.event("Computing maximal green set...")
greenorigindependencies = {}
+ callreturndependencies = {}
for origin in self.originflags.values():
origin.greenargs = True
- origin.record_dependencies(greenorigindependencies)
+ origin.record_dependencies(greenorigindependencies,
+ callreturndependencies)
while True:
progress = False
+ # check all calls to see if they are green calls or not
+ for origin, graphs in callreturndependencies.items():
+ if self.is_green_call(origin.spaceop):
+ pass # green call => don't force spaceop.result to red
+ else:
+ # non-green calls: replace the dependency with a regular
+ # dependency from graph.getreturnvar() to spaceop.result
+ del callreturndependencies[origin]
+ retdeps = greenorigindependencies.setdefault(origin, [])
+ for graph in graphs:
+ retdeps.append(graph.getreturnvar())
+ # propagate normal dependencies
for origin, deps in greenorigindependencies.items():
for v in deps:
if not binding(v).is_green():
@@ -185,6 +219,17 @@
ha.binding(tsgraph.getreturnvar()))
self.tsgraphsigs[tsgraph] = sig_hs
+ def is_green_call(self, callop):
+ "Is the given call operation completely computable at compile-time?"
+ for v in callop.args:
+ hs_arg = self.annotator.binding(v)
+ if not hs_arg.is_green():
+ return False
+ # all-green arguments. Note that we can return True even if the
+ # result appears to be red; it's not a real red result then.
+ impure = self.impurity_analyzer.analyze(callop)
+ return not impure
+
def immutableconstant(self, const):
res = hintmodel.SomeLLAbstractConstant(const.concretetype, {})
res.const = const.value
Modified: pypy/dist/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/model.py (original)
+++ pypy/dist/pypy/jit/hintannotator/model.py Mon Jan 29 19:06:48 2007
@@ -68,14 +68,16 @@
for p in self.read_positions:
annotator.reflowfromposition(p)
- def record_dependencies(self, greenorigindependencies):
+ def record_dependencies(self, greenorigindependencies,
+ callreturndependencies):
deps = greenorigindependencies.setdefault(self, [])
deps.extend(self.spaceop.args)
class CallOpOriginFlags(OriginFlags):
- def record_dependencies(self, greenorigindependencies):
+ def record_dependencies(self, greenorigindependencies,
+ callreturndependencies):
bk = self.bookkeeper
if self.spaceop.opname == 'direct_call':
args = self.spaceop.args[1:]
@@ -89,9 +91,9 @@
_, repgraph, callfamily = call_families.find(graph)
# record the argument and return value dependencies
- retdeps = greenorigindependencies.setdefault(self, [])
+ retdeps = callreturndependencies.setdefault(self, [])
for graph in callfamily.tsgraphs:
- retdeps.append(graph.getreturnvar())
+ retdeps.append(graph)
for i, v in enumerate(args):
argorigin = bk.myinputargorigin(graph, i)
deps = greenorigindependencies.setdefault(argorigin, [])
@@ -111,7 +113,8 @@
def __repr__(self):
return '<%s %s>' % (self.getarg(), self.reprstate())
- def record_dependencies(self, greenorigindependencies):
+ def record_dependencies(self, greenorigindependencies,
+ callreturndependencies):
bk = self.bookkeeper
call_families = bk.tsgraph_maximal_call_families
_, repgraph, callfamily = call_families.find(self.graph)
Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py (original)
+++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py Mon Jan 29 19:06:48 2007
@@ -688,3 +688,17 @@
return o.m()
hs = hannotate(f, [bool], policy=P_OOPSPEC_NOVIRTUAL)
+
+
+def test_green_isinstance():
+ class Base(object):
+ pass
+ class Concrete(Base):
+ pass
+
+ def f(o):
+ hint(o, concrete=True)
+ return isinstance(o, Concrete)
+
+ hs = hannotate(f, [Base], policy=P_OOPSPEC_NOVIRTUAL)
+ assert hs.is_green()
Modified: pypy/dist/pypy/jit/timeshifter/test/test_portal.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_portal.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_portal.py Mon Jan 29 19:06:48 2007
@@ -401,7 +401,6 @@
assert res == 11
def test_isinstance(self):
- py.test.skip("(cfbolz) don't get it")
class Base(object):
pass
class Int(Base):
@@ -426,5 +425,5 @@
res = self.timeshift_from_portal(ll_main, ll_function, [5], policy=P_NOVIRTUAL)
- assert res == 10
+ assert res is False
Modified: pypy/dist/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/transform.py (original)
+++ pypy/dist/pypy/jit/timeshifter/transform.py Mon Jan 29 19:06:48 2007
@@ -3,30 +3,14 @@
from pypy.annotation import model as annmodel
from pypy.jit.hintannotator import model as hintmodel
from pypy.jit.hintannotator.model import originalconcretetype
-from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
+from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.rmodel import inputconst
from pypy.translator.unsimplify import varoftype, copyvar
from pypy.translator.unsimplify import split_block, split_block_at_start
-#from pypy.translator.simplify import rec_op_has_side_effects
-from pypy.translator.backendopt import graphanalyze
from pypy.translator.backendopt.ssa import SSA_to_SSI
from pypy.translator.unsimplify import split_block
-class HasSideeffects(graphanalyze.GraphAnalyzer):
-
- EXCEPTIONS = ('debug_assert',)
-
- def analyze_exceptblock(self, block, seen=None):
- # graphs explicitly raising have side-effects
- return True
-
- def operation_is_true(self, op):
- opname = op.opname
- return (lloperation.LL_OPERATIONS[opname].sideeffects and
- opname not in self.EXCEPTIONS)
-
-
class MergePointFamily(object):
def __init__(self, tsgraph):
self.tsgraph = tsgraph
@@ -63,13 +47,8 @@
self.c_mpfamily = inputconst(lltype.Void, self.mergepointfamily)
self.tsgraphs_seen = []
- t = self.hannotator.base_translator
- self.sideeffects_analyzer = HasSideeffects(t)
self.raise_analyzer = hannotator.exceptiontransformer.raise_analyzer
- def has_sideeffects(self, op):
- return self.sideeffects_analyzer.analyze(op)
-
def can_raise(self, op):
return self.raise_analyzer.analyze(op)
@@ -496,18 +475,8 @@
if fnobj._callable.oopspec.startswith('vable.'):
return 'vable'
return 'oopspec'
-
- for v in spaceop.args:
- hs_arg = self.hannotator.binding(v)
- if not hs_arg.is_green():
- break
- else:
- hs_res = self.hannotator.binding(spaceop.result)
- if hs_res.is_green():
- # all-green arguments and result.
- # Does the function have side-effects?
- if not self.has_sideeffects(spaceop):
- return 'green'
+ if self.hannotator.bookkeeper.is_green_call(spaceop):
+ return 'green'
colors = {}
for graph, tsgraph in self.graphs_from(spaceop):
color = self.graph_calling_color(tsgraph)
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Mon Jan 29 19:06:48 2007
@@ -80,6 +80,13 @@
return op_impl
fold = roproperty(get_fold_impl)
+ def is_pure(self, *ARGTYPES):
+ 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')))
+
def enum_ops_without_sideeffects(raising_is_ok=False):
"""Enumerate operations that have no side-effects
More information about the Pypy-commit
mailing list