[pypy-commit] pypy default: Move the CollectAnalyzer to 'backendopt' and use it from the JIT codewriter
arigo
pypy.commits at gmail.com
Wed Jun 1 11:32:45 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r84861:211242489109
Date: 2016-06-01 15:37 +0200
http://bitbucket.org/pypy/pypy/changeset/211242489109/
Log: Move the CollectAnalyzer to 'backendopt' and use it from the JIT
codewriter
diff --git a/rpython/jit/codewriter/call.py b/rpython/jit/codewriter/call.py
--- a/rpython/jit/codewriter/call.py
+++ b/rpython/jit/codewriter/call.py
@@ -14,6 +14,7 @@
from rpython.translator.backendopt.canraise import RaiseAnalyzer
from rpython.translator.backendopt.writeanalyze import ReadWriteAnalyzer
from rpython.translator.backendopt.graphanalyze import DependencyTracker
+from rpython.translator.backendopt.collectanalyze import CollectAnalyzer
class CallControl(object):
@@ -37,9 +38,9 @@
self.virtualizable_analyzer = VirtualizableAnalyzer(translator)
self.quasiimmut_analyzer = QuasiImmutAnalyzer(translator)
self.randomeffects_analyzer = RandomEffectsAnalyzer(translator)
- self.seen = DependencyTracker(self.readwrite_analyzer)
- else:
- self.seen = None
+ self.collect_analyzer = CollectAnalyzer(translator)
+ self.seen_rw = DependencyTracker(self.readwrite_analyzer)
+ self.seen_gc = DependencyTracker(self.collect_analyzer)
#
for index, jd in enumerate(jitdrivers_sd):
jd.index = index
@@ -294,9 +295,9 @@
"but the function has no result" % (op, ))
#
effectinfo = effectinfo_from_writeanalyze(
- self.readwrite_analyzer.analyze(op, self.seen), self.cpu,
+ self.readwrite_analyzer.analyze(op, self.seen_rw), self.cpu,
extraeffect, oopspecindex, can_invalidate, call_release_gil_target,
- extradescr,
+ extradescr, self.collect_analyzer.analyze(op, self.seen_gc),
)
#
assert effectinfo is not None
diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -116,7 +116,8 @@
oopspecindex=OS_NONE,
can_invalidate=False,
call_release_gil_target=_NO_CALL_RELEASE_GIL_TARGET,
- extradescrs=None):
+ extradescrs=None,
+ can_collect=True):
readonly_descrs_fields = frozenset_or_none(readonly_descrs_fields)
readonly_descrs_arrays = frozenset_or_none(readonly_descrs_arrays)
readonly_descrs_interiorfields = frozenset_or_none(
@@ -133,7 +134,8 @@
write_descrs_interiorfields,
extraeffect,
oopspecindex,
- can_invalidate)
+ can_invalidate,
+ can_collect)
tgt_func, tgt_saveerr = call_release_gil_target
if tgt_func:
key += (object(),) # don't care about caching in this case
@@ -184,6 +186,7 @@
#
result.extraeffect = extraeffect
result.can_invalidate = can_invalidate
+ result.can_collect = can_collect
result.oopspecindex = oopspecindex
result.extradescrs = extradescrs
result.call_release_gil_target = call_release_gil_target
@@ -230,6 +233,9 @@
def check_can_invalidate(self):
return self.can_invalidate
+ def check_can_collect(self):
+ return self.can_collect
+
def check_is_elidable(self):
return (self.extraeffect == self.EF_ELIDABLE_CAN_RAISE or
self.extraeffect == self.EF_ELIDABLE_OR_MEMORYERROR or
@@ -268,7 +274,8 @@
can_invalidate=False,
call_release_gil_target=
EffectInfo._NO_CALL_RELEASE_GIL_TARGET,
- extradescr=None):
+ extradescr=None,
+ can_collect=True):
from rpython.translator.backendopt.writeanalyze import top_set
if effects is top_set or extraeffect == EffectInfo.EF_RANDOM_EFFECTS:
readonly_descrs_fields = None
@@ -343,6 +350,9 @@
else:
assert 0
#
+ if extraeffect >= EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE:
+ can_collect = True
+ #
return EffectInfo(readonly_descrs_fields,
readonly_descrs_arrays,
readonly_descrs_interiorfields,
@@ -353,7 +363,8 @@
oopspecindex,
can_invalidate,
call_release_gil_target,
- extradescr)
+ extradescr,
+ can_collect)
def consider_struct(TYPE, fieldname):
if fieldType(TYPE, fieldname) is lltype.Void:
diff --git a/rpython/jit/codewriter/test/test_call.py b/rpython/jit/codewriter/test/test_call.py
--- a/rpython/jit/codewriter/test/test_call.py
+++ b/rpython/jit/codewriter/test/test_call.py
@@ -334,3 +334,37 @@
assert call_op.opname == 'direct_call'
with py.test.raises(Exception):
call_descr = cc.getcalldescr(call_op)
+
+def test_can_or_cannot_collect():
+ from rpython.jit.backend.llgraph.runner import LLGraphCPU
+ prebuilts = [[5], [6]]
+ l = []
+ def f1(n):
+ if n > 1:
+ raise IndexError
+ return prebuilts[n] # cannot collect
+ f1._dont_inline_ = True
+
+ def f2(n):
+ return [n] # can collect
+ f2._dont_inline_ = True
+
+ def f(n):
+ a = f1(n)
+ b = f2(n)
+ return len(a) + len(b)
+
+ rtyper = support.annotate(f, [1])
+ jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
+ cc = CallControl(LLGraphCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
+ res = cc.find_all_graphs(FakePolicy())
+ [f_graph] = [x for x in res if x.func is f]
+ for index, expected in [
+ (0, False), # f1()
+ (1, True), # f2()
+ (2, False), # len()
+ (3, False)]: # len()
+ call_op = f_graph.startblock.operations[index]
+ assert call_op.opname == 'direct_call'
+ call_descr = cc.getcalldescr(call_op)
+ assert call_descr.extrainfo.check_can_collect() == expected
diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -5,7 +5,7 @@
from rpython.rlib.unroll import unrolling_iterable
from rpython.rtyper import rmodel, annlowlevel
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, llgroup
-from rpython.rtyper.lltypesystem.lloperation import LL_OPERATIONS, llop
+from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.memory import gctypelayout
from rpython.memory.gctransform.log import log
from rpython.memory.gctransform.support import get_rtti, ll_call_destructor
@@ -14,7 +14,7 @@
from rpython.memory.gctypelayout import ll_weakref_deref, WEAKREF, WEAKREFPTR
from rpython.memory.gctypelayout import FIN_TRIGGER_FUNC, FIN_HANDLER_ARRAY
from rpython.tool.sourcetools import func_with_new_name
-from rpython.translator.backendopt import graphanalyze
+from rpython.translator.backendopt.collectanalyze import CollectAnalyzer
from rpython.translator.backendopt.finalizer import FinalizerAnalyzer
from rpython.translator.backendopt.support import var_needsgc
import types
@@ -23,33 +23,6 @@
TYPE_ID = llgroup.HALFWORD
-class CollectAnalyzer(graphanalyze.BoolGraphAnalyzer):
-
- def analyze_direct_call(self, graph, seen=None):
- try:
- func = graph.func
- except AttributeError:
- pass
- else:
- if getattr(func, '_gctransformer_hint_cannot_collect_', False):
- return False
- if getattr(func, '_gctransformer_hint_close_stack_', False):
- return True
- return graphanalyze.BoolGraphAnalyzer.analyze_direct_call(self, graph,
- seen)
- def analyze_external_call(self, funcobj, seen=None):
- if funcobj.random_effects_on_gcobjs:
- return True
- return graphanalyze.BoolGraphAnalyzer.analyze_external_call(
- self, funcobj, seen)
- def analyze_simple_operation(self, op, graphinfo):
- if op.opname in ('malloc', 'malloc_varsize'):
- flags = op.args[1].value
- return flags['flavor'] == 'gc'
- else:
- return (op.opname in LL_OPERATIONS and
- LL_OPERATIONS[op.opname].canmallocgc)
-
def propagate_no_write_barrier_needed(result, block, mallocvars,
collect_analyzer, entrymap,
startindex=0):
diff --git a/rpython/translator/backendopt/collectanalyze.py b/rpython/translator/backendopt/collectanalyze.py
new file mode 100644
--- /dev/null
+++ b/rpython/translator/backendopt/collectanalyze.py
@@ -0,0 +1,33 @@
+from rpython.translator.backendopt import graphanalyze
+from rpython.rtyper.lltypesystem.lloperation import LL_OPERATIONS
+
+# NB. tests are in rpython/memory/gctransform/test/test_framework.py
+
+
+class CollectAnalyzer(graphanalyze.BoolGraphAnalyzer):
+
+ def analyze_direct_call(self, graph, seen=None):
+ try:
+ func = graph.func
+ except AttributeError:
+ pass
+ else:
+ if getattr(func, '_gctransformer_hint_cannot_collect_', False):
+ return False
+ if getattr(func, '_gctransformer_hint_close_stack_', False):
+ return True
+ return graphanalyze.BoolGraphAnalyzer.analyze_direct_call(self, graph,
+ seen)
+ def analyze_external_call(self, funcobj, seen=None):
+ if funcobj.random_effects_on_gcobjs:
+ return True
+ return graphanalyze.BoolGraphAnalyzer.analyze_external_call(
+ self, funcobj, seen)
+
+ def analyze_simple_operation(self, op, graphinfo):
+ if op.opname in ('malloc', 'malloc_varsize'):
+ flags = op.args[1].value
+ return flags['flavor'] == 'gc'
+ else:
+ return (op.opname in LL_OPERATIONS and
+ LL_OPERATIONS[op.opname].canmallocgc)
More information about the pypy-commit
mailing list