[pypy-svn] r40452 - in pypy/branch/jit-virtual-world/pypy/jit: . hintannotator hintannotator/test timeshifter timeshifter/test
arigo at codespeak.net
arigo at codespeak.net
Tue Mar 13 20:42:43 CET 2007
Author: arigo
Date: Tue Mar 13 20:42:39 2007
New Revision: 40452
Modified:
pypy/branch/jit-virtual-world/pypy/jit/TODO.txt
pypy/branch/jit-virtual-world/pypy/jit/hintannotator/annotator.py
pypy/branch/jit-virtual-world/pypy/jit/hintannotator/bookkeeper.py
pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py
pypy/branch/jit-virtual-world/pypy/jit/hintannotator/test/test_annotator.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vlist.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
Log:
(pedronis, arigo)
* a more elegant approach to indirect calls: make a ts stub
for the functions that shouldn't be looked in.
* timeshift support for green oopspec calls, done by having
general support for green calls that can raise.
Modified: pypy/branch/jit-virtual-world/pypy/jit/TODO.txt
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/TODO.txt (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/TODO.txt Tue Mar 13 20:42:39 2007
@@ -36,5 +36,5 @@
- share code between the machine code backends (MachineCodeBlock,
possibly register allocation)
-- more green vars in the hintannotator: for y=frozen_list[x]
- and for y=hint(x, deepfreeze=True) if x is green
+- more green vars in the hintannotator: for y=hint(x, deepfreeze=True)
+ if x is green
Modified: pypy/branch/jit-virtual-world/pypy/jit/hintannotator/annotator.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/hintannotator/annotator.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/hintannotator/annotator.py Tue Mar 13 20:42:39 2007
@@ -20,14 +20,6 @@
def look_inside_graph(self, graph):
return True
- def look_inside_graphs(self, graph_list):
- if not graph_list:
- return False # cannot follow indirect call with no known targets
- for graph in graph_list:
- if not self.look_inside_graph(graph):
- return False
- return True
-
class StopAtXPolicy(HintAnnotatorPolicy):
"""Useful for tests."""
Modified: pypy/branch/jit-virtual-world/pypy/jit/hintannotator/bookkeeper.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/hintannotator/bookkeeper.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/hintannotator/bookkeeper.py Tue Mar 13 20:42:39 2007
@@ -2,10 +2,12 @@
from pypy.tool.tls import tlsobject
from pypy.tool.ansi_print import ansi_log
from pypy.objspace.flow.model import copygraph, SpaceOperation, Constant
+from pypy.objspace.flow.model import Variable, Block, Link, FunctionGraph
from pypy.annotation import model as annmodel
from pypy.rpython.lltypesystem import lltype, lloperation
from pypy.tool.algo.unionfind import UnionFind
from pypy.translator.backendopt import graphanalyze
+from pypy.translator.unsimplify import copyvar
TLS = tlsobject()
@@ -42,7 +44,10 @@
return self._cache[key]
except KeyError:
bk = self.bookkeeper
- graph = copygraph(self.origgraph)
+ if bk.annotator.policy.look_inside_graph(self.origgraph):
+ graph = copygraph(self.origgraph)
+ else:
+ graph = self.build_callback_graph(self.origgraph)
graph.tag = 'timeshifted'
try:
etrafo = bk.annotator.exceptiontransformer
@@ -58,6 +63,20 @@
log(str(graph))
return graph
+ def build_callback_graph(self, graph):
+ args_v = [copyvar(None, v) for v in graph.getargs()]
+ v_res = copyvar(None, graph.getreturnvar())
+ rtyper = self.bookkeeper.annotator.base_translator.rtyper # fish
+ fnptr = rtyper.getcallable(graph)
+ v_ptr = Constant(fnptr, lltype.typeOf(fnptr))
+ newstartblock = Block(args_v)
+ newstartblock.operations.append(
+ SpaceOperation('direct_call', [v_ptr] + args_v, v_res))
+ newgraph = FunctionGraph(graph.name, newstartblock)
+ newgraph.getreturnvar().concretetype = v_res.concretetype
+ newstartblock.closeblock(Link([v_res], newgraph.returnblock))
+ return newgraph
+
class TsGraphCallFamily:
def __init__(self, tsgraph):
Modified: pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py Tue Mar 13 20:42:39 2007
@@ -105,16 +105,6 @@
deps.append(v)
-class PureCallOpOriginFlags(CallOpOriginFlags):
-
- def record_dependencies(self, greenorigindependencies,
- callreturndependencies):
- OriginFlags.record_dependencies(self, greenorigindependencies,
- callreturndependencies)
- CallOpOriginFlags.record_dependencies(self, greenorigindependencies,
- callreturndependencies)
-
-
class InputArgOriginFlags(OriginFlags):
def __init__(self, bookkeeper, graph, i):
@@ -351,14 +341,11 @@
args_hs = args_hs[:-1]
assert hs_graph_list.is_constant()
graph_list = hs_graph_list.const
+ if graph_list is None:
+ # cannot follow indirect calls to unknown targets
+ return variableoftype(hs_v1.concretetype.TO.RESULT)
bookkeeper = getbookkeeper()
- if not bookkeeper.annotator.policy.look_inside_graphs(graph_list):
- # cannot follow
- return cannot_follow_call(bookkeeper, graph_list,
- (hs_v1,) + args_hs,
- hs_v1.concretetype.TO.RESULT)
-
myorigin = bookkeeper.myorigin()
myorigin.__class__ = CallOpOriginFlags # thud
fixed = myorigin.read_fixed()
@@ -418,7 +405,7 @@
if not hasattr(fnobj, 'graph'):
raise NotImplementedError("XXX call to externals or primitives")
if not bookkeeper.annotator.policy.look_inside_graph(fnobj.graph):
- return cannot_follow_call(bookkeeper, [fnobj.graph], args_hs,
+ return cannot_follow_call(bookkeeper, fnobj.graph, args_hs,
lltype.typeOf(fnobj).RESULT)
# recursive call from the entry point to itself: ignore them and
@@ -654,13 +641,17 @@
# Exception: an operation on a frozen container is constant-foldable.
RESULT = bookkeeper.current_op_concretetype()
if '.' in operation_name and args_hs[0].deepfrozen:
- myorigin = bookkeeper.myorigin()
- d = newset({myorigin: True}, *[hs_c.origins for hs_c in args_hs])
- return SomeLLAbstractConstant(RESULT, d,
- eager_concrete = False, # probably
- myorigin = myorigin)
- else:
- return variableoftype(RESULT)
+ for hs_v in args_hs:
+ if not isinstance(hs_v, SomeLLAbstractConstant):
+ break
+ else:
+ myorigin = bookkeeper.myorigin()
+ d = newset({myorigin: True}, *[hs_c.origins
+ for hs_c in args_hs])
+ return SomeLLAbstractConstant(RESULT, d,
+ eager_concrete = False, # probably
+ myorigin = myorigin)
+ return variableoftype(RESULT)
# --- the code below is not used any more except by test_annotator.py ---
if operation_name == 'newlist':
@@ -684,17 +675,9 @@
hs_result = handler(*args_hs) # which may raise NotImplementedError
return hs_result
-def cannot_follow_call(bookkeeper, graph_list, args_hs, RESTYPE):
+def cannot_follow_call(bookkeeper, graph, args_hs, RESTYPE):
# the policy prevents us from following the call
- if not graph_list: # no known target, give up
- return variableoftype(RESTYPE)
- pure_call = True
- for graph in graph_list:
- if not bookkeeper.is_pure_graph(graph):
- # it's not calling pure graphs either, so the result
- # is entierely unknown
- pure_call = False
- break
+ pure_call = bookkeeper.is_pure_graph(graph)
# when calling pure graphs, consider the call as an operation.
for hs in args_hs:
if not isinstance(hs, SomeLLAbstractConstant):
@@ -707,26 +690,8 @@
h_res = SomeLLAbstractConstant(RESTYPE, d,
eager_concrete = False, # probably
myorigin = myorigin)
- fixed = myorigin.read_fixed()
else:
h_res = variableoftype(RESTYPE)
- fixed = False
-
- look_inside_graph = bookkeeper.annotator.policy.look_inside_graph
- followable_graphs = [graph for graph in graph_list
- if look_inside_graph(graph)]
- if followable_graphs:
- # we can still follow this graph, even if we cannot follow all of them
- tsgraphs_accum = []
- bookkeeper.graph_family_call(followable_graphs, fixed, args_hs[1:],
- tsgraphs_accum)
- myorigin = bookkeeper.myorigin()
- myorigin.any_called_graph = tsgraphs_accum[0]
- if pure_call:
- myorigin.__class__ = PureCallOpOriginFlags # thud
- else:
- myorigin.__class__ = CallOpOriginFlags # thud
-
return h_res
# ____________________________________________________________
Modified: pypy/branch/jit-virtual-world/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/hintannotator/test/test_annotator.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/hintannotator/test/test_annotator.py Tue Mar 13 20:42:39 2007
@@ -818,6 +818,7 @@
return h(x)
P = StopAtXPolicy(h1)
+ P.oopspec = True
P.entrypoint_returns_red = False
hs, hannotator = hannotate(f, [int, int], policy=P, annotator=True)
assert not hs.is_green()
@@ -841,6 +842,7 @@
return z
P = StopAtXPolicy(h1)
+ P.oopspec = True
P.entrypoint_returns_red = False
hs, hannotator = hannotate(f, [int, int], policy=P, annotator=True)
assert hs.is_green()
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py Tue Mar 13 20:42:39 2007
@@ -1321,9 +1321,33 @@
for r_arg in hop.args_r:
assert isinstance(r_arg, GreenRepr)
assert isinstance(hop.r_result, GreenRepr)
+
+ FUNC = hop.args_v[0].concretetype
+ calldesc = rtimeshift.CallDesc(self.RGenOp, FUNC.TO)
+ args_v = hop.args_v
+ args_s = [annmodel.lltype_to_annotation(v.concretetype)
+ for v in args_v]
+ s_result = annmodel.lltype_to_annotation(FUNC.TO.RESULT)
+ v_jitstate = hop.llops.getjitstate()
+ return hop.llops.genmixlevelhelpercall(calldesc.green_call,
+ [self.s_JITState] + args_s,
+ [v_jitstate ] + args_v,
+ s_result)
+
+ def translate_op_green_call_noexc(self, hop):
+ for r_arg in hop.args_r:
+ assert isinstance(r_arg, GreenRepr)
+ assert isinstance(hop.r_result, GreenRepr)
v = hop.genop('direct_call', hop.args_v, hop.r_result.lowleveltype)
return v
+ def translate_op_green_indirect_call_noexc(self, hop):
+ for r_arg in hop.args_r[:-1]:
+ assert isinstance(r_arg, GreenRepr)
+ assert isinstance(hop.r_result, GreenRepr)
+ v = hop.genop('indirect_call', hop.args_v, hop.r_result.lowleveltype)
+ return v
+
def translate_op_red_call(self, hop):
bk = self.annotator.bookkeeper
v_jitstate = hop.llops.getjitstate()
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py Tue Mar 13 20:42:39 2007
@@ -500,6 +500,15 @@
self.result_kind = RGenOp.kindToken(FUNCTYPE.RESULT)
# xxx what if the result is virtualizable?
self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
+ whatever_return_value = FUNCTYPE.RESULT._defl()
+ def green_call(jitstate, fnptr, *args):
+ try:
+ result = fnptr(*args)
+ except Exception, e:
+ jitstate.residual_exception(e)
+ result = whatever_return_value
+ return result
+ self.green_call = green_call
def _freeze_(self):
return True
@@ -532,6 +541,7 @@
else:
gv_flags = builder.genop2("int_or", gv_flags, gv_flag)
else:
+ assert gv_flags is None
exceptiondesc.fetch_global_excdata(jitstate)
if gv_flags is None:
gv_flags = builder.rgenop.constPrebuiltGlobal(0)
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py Tue Mar 13 20:42:39 2007
@@ -1,6 +1,7 @@
import py
from pypy.translator.translator import TranslationContext, graphof
from pypy.jit.hintannotator.annotator import HintAnnotator, HintAnnotatorPolicy
+from pypy.jit.hintannotator.annotator import StopAtXPolicy
from pypy.jit.hintannotator.bookkeeper import HintBookkeeper
from pypy.jit.hintannotator.model import *
from pypy.jit.timeshifter.hrtyper import HintRTyper, originalconcretetype
@@ -348,21 +349,6 @@
assert count == expected_count
-class StopAtXPolicy(HintAnnotatorPolicy):
- def __init__(self, *funcs):
- HintAnnotatorPolicy.__init__(self, novirtualcontainer=True,
- oopspec=True)
- self.funcs = funcs
-
- def look_inside_graph(self, graph):
- try:
- if graph.func in self.funcs:
- return False
- except AttributeError:
- pass
- return True
-
-
class TestTimeshift(TimeshiftingTests):
def test_simple_fixed(self):
@@ -1466,22 +1452,47 @@
assert res == f(4,113)
self.check_insns({'int_sub': 1})
- def test_indirect_sometimes_residual_red_call(self):
- py.test.skip("in-progress")
+ def test_indirect_sometimes_residual_pure_red_call(self):
def h1(x):
return x-2
def h2(x):
return x*4
l = [h1, h2]
def f(n, x):
+ hint(None, global_merge_point=True)
+ hint(n, concrete=True)
frozenl = hint(l, deepfreeze=True)
h = frozenl[n&1]
return h(x)
P = StopAtXPolicy(h1)
- res = self.timeshift(f, [7, 3], [0], policy=P)
+ P.oopspec = True
+ res = self.timeshift(f, [7, 3], [], policy=P)
assert res == f(7,3)
self.check_insns({'int_mul': 1})
- res = self.timeshift(f, [4, 113], [0], policy=P)
+ res = self.timeshift(f, [4, 113], [], policy=P)
assert res == f(4,113)
self.check_insns({'direct_call': 1})
+
+ def test_indirect_sometimes_residual_pure_but_fixed_red_call(self):
+ def h1(x):
+ return x-2
+ def h2(x):
+ return x*4
+ l = [h1, h2]
+ def f(n, x):
+ hint(None, global_merge_point=True)
+ frozenl = hint(l, deepfreeze=True)
+ h = frozenl[n&1]
+ z = h(x)
+ hint(z, concrete=True)
+ return z
+
+ P = StopAtXPolicy(h1)
+ P.oopspec = True
+ res = self.timeshift(f, [7, 3], [], policy=P)
+ assert res == f(7,3)
+ self.check_insns({})
+ res = self.timeshift(f, [4, 113], [], policy=P)
+ assert res == f(4,113)
+ self.check_insns({})
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vlist.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vlist.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_vlist.py Tue Mar 13 20:42:39 2007
@@ -129,3 +129,30 @@
res = self.timeshift(ll_function, [3, 4], [0, 1], policy=P_OOPSPEC)
assert res == 5
self.check_insns({})
+
+ def test_frozen_list(self):
+ lst = [5, 7, 9]
+ def ll_function(x):
+ mylist = hint(lst, deepfreeze=True)
+ z = mylist[x]
+ hint(z, concrete=True)
+ return z
+
+ res = self.timeshift(ll_function, [1], policy=P_OOPSPEC)
+ assert res == 7
+ self.check_insns({})
+
+ def test_frozen_list_indexerror(self):
+ lst = [5, 7, 9]
+ def ll_function(x):
+ mylist = hint(lst, deepfreeze=True)
+ try:
+ z = mylist[x]
+ except IndexError:
+ return -42
+ hint(z, concrete=True)
+ return z
+
+ res = self.timeshift(ll_function, [4], policy=P_OOPSPEC)
+ assert res == -42
+ self.check_insns({})
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py Tue Mar 13 20:42:39 2007
@@ -492,11 +492,19 @@
args_v = spaceop.args[1:]
elif spaceop.opname == 'indirect_call':
graphs = spaceop.args[-1].value
+ if graphs is None:
+ return # cannot follow at all
args_v = spaceop.args[1:-1]
else:
raise AssertionError(spaceop.opname)
- if not self.hannotator.policy.look_inside_graphs(graphs):
- return # cannot follow this call
+ # if the graph - or all the called graphs - are marked as "don't
+ # follow", directly return None as a special case. (This is only
+ # an optimization for the indirect_call case.)
+ for graph in graphs:
+ if self.hannotator.policy.look_inside_graph(graph):
+ break
+ else:
+ return
for graph in graphs:
tsgraph = self.timeshifted_graph_of(graph, args_v, spaceop.result)
yield graph, tsgraph
@@ -511,6 +519,10 @@
self.hannotator.policy.oopspec):
if fnobj._callable.oopspec.startswith('vable.'):
return 'vable', None
+ hs_result = self.hannotator.binding(spaceop.result)
+ if (hs_result.is_green() and
+ hs_result.concretetype is not lltype.Void):
+ return 'green', self.can_raise(spaceop)
return 'oopspec', self.can_raise(spaceop)
if self.hannotator.bookkeeper.is_green_call(spaceop):
return 'green', None
@@ -726,12 +738,20 @@
op.opname = 'rpyexc_raise'
op.args = op.args[1:]
- def handle_green_call(self, block, pos):
- # green-returning call, for now (XXX) we assume it's an
- # all-green function that we can just call
+ def handle_green_call(self, block, pos, withexc=False):
+ # an all-green function that we can just call
op = block.operations[pos]
- assert op.opname == 'direct_call'
- op.opname = 'green_call'
+ if op.opname == 'indirect_call':
+ if withexc:
+ op.args.pop() # remove the graph list
+ op.opname = 'green_call'
+ else:
+ op.opname = 'green_indirect_call_noexc'
+ else:
+ if withexc:
+ op.opname = 'green_call'
+ else:
+ op.opname = 'green_call_noexc'
def handle_yellow_call(self, block, pos, withexc):
self.handle_red_call(block, pos, color='yellow', withexc=withexc)
@@ -804,6 +824,8 @@
else:
promoteblock = block
v_flags2 = v_flags
+ # if there is no global merge point, this 'promote' will actually
+ # always see a constant red box
v_finished_flag = self.genop(promoteblock, 'promote', [v_flags2],
resulttype = lltype.Bool)
self.go_to_dispatcher_if(promoteblock, v_finished_flag)
More information about the Pypy-commit
mailing list