[pypy-svn] r32952 - in pypy/dist/pypy/jit/timeshifter: . test
pedronis at codespeak.net
pedronis at codespeak.net
Fri Oct 6 14:14:48 CEST 2006
Author: pedronis
Date: Fri Oct 6 14:14:40 2006
New Revision: 32952
Modified:
pypy/dist/pypy/jit/timeshifter/rtimeshift.py
pypy/dist/pypy/jit/timeshifter/rtyper.py
pypy/dist/pypy/jit/timeshifter/test/test_promotion.py
pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
pypy/dist/pypy/jit/timeshifter/transform.py
Log:
(arre, arigo, pedronis)
new slightly more complicated test we're fighting with since tuesday.
Some progress to get it at least thorugh the first compilation-time phase.
When a call cannot produce any return (compilation interrupted case) it should still
let the parent callers possibly exhaust their dispatch queues.
Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Fri Oct 6 14:14:40 2006
@@ -316,8 +316,7 @@
return jitstate_chain
# XXX obscurity++ above
-def dispatch_next(oldjitstate):
- dispatchqueue = oldjitstate.frame.dispatchqueue
+def dispatch_next(oldjitstate, dispatchqueue):
if dispatchqueue.split_chain is not None:
jitstate = dispatchqueue.split_chain
dispatchqueue.split_chain = jitstate.next
@@ -330,6 +329,12 @@
def getresumepoint(jitstate):
return jitstate.resumepoint
+def pickjitstate(oldjitstate, newjitstate):
+ if newjitstate is not None:
+ return newjitstate
+ else:
+ return oldjitstate
+
def save_locals(jitstate, *redboxes):
redboxes = list(redboxes)
assert None not in redboxes
@@ -782,10 +787,19 @@
self.exc_value_box = self.exc_value_box.replace(memo)
-def enter_graph(jitstate, DispatchQueueClass):
- dispatchqueue = DispatchQueueClass()
- enter_frame(jitstate, dispatchqueue)
-enter_graph._annspecialcase_ = 'specialize:arg(1)'
+def ensure_queue(jitstate, DispatchQueueClass):
+ return DispatchQueueClass()
+ensure_queue._annspecialcase_ = 'specialize:arg(1)'
+
+def portal_ensure_queue(jitstate, DispatchQueueClass):
+ resuming = jitstate.resuming
+ if resuming is None:
+ return DispatchQueueClass()
+ else:
+ dispatchqueue = jitstate.frame.dispatchqueue
+ assert isinstance(dispatchqueue, DispatchQueueClass)
+ return dispatchqueue
+portal_ensure_queue._annspecialcase_ = 'specialize:arg(1)'
def enter_frame(jitstate, dispatchqueue):
jitstate.frame = VirtualFrame(jitstate.frame, dispatchqueue)
@@ -806,12 +820,7 @@
parent_mergesleft = MC_CALL_NOT_TAKEN
dispatchqueue.mergecounter = parent_mergesleft
-
-class CompilationInterrupted(Exception):
- pass
-
-def merge_returning_jitstates(jitstate):
- dispatchqueue = jitstate.frame.dispatchqueue
+def merge_returning_jitstates(jitstate, dispatchqueue):
return_chain = dispatchqueue.return_chain
resuming = jitstate.resuming
return_cache = {}
@@ -824,34 +833,35 @@
if res is False: # not finished
jitstate.next = still_pending
still_pending = jitstate
- if still_pending is None:
- assert resuming is None
- raise CompilationInterrupted
most_general_jitstate = still_pending
- still_pending = still_pending.next
- while still_pending is not None:
- jitstate = still_pending
+ # if there are more than one jitstate still left, merge them forcefully
+ if still_pending is not None:
still_pending = still_pending.next
- res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
- return_marker)
- assert res is True # finished
+ while still_pending is not None:
+ jitstate = still_pending
+ still_pending = still_pending.next
+ res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
+ return_marker)
+ assert res is True # finished
if resuming is not None:
resuming.leave_call(dispatchqueue)
return most_general_jitstate
-def leave_graph_red(jitstate):
- jitstate = merge_returning_jitstates(jitstate)
- myframe = jitstate.frame
- leave_frame(jitstate)
- jitstate.returnbox = myframe.local_boxes[0]
- # ^^^ fetched by a 'fetch_return' operation
+def leave_graph_red(jitstate, dispatchqueue):
+ jitstate = merge_returning_jitstates(jitstate, dispatchqueue)
+ if jitstate is not None:
+ myframe = jitstate.frame
+ leave_frame(jitstate)
+ jitstate.returnbox = myframe.local_boxes[0]
+ # ^^^ fetched by a 'fetch_return' operation
return jitstate
-def leave_graph_gray(jitstate):
- jitstate = merge_returning_jitstates(jitstate)
- leave_frame(jitstate)
+def leave_graph_gray(jitstate, dispatchqueue):
+ jitstate = merge_returning_jitstates(jitstate, dispatchqueue)
+ if jitstate is not None:
+ leave_frame(jitstate)
return jitstate
def leave_frame(jitstate):
@@ -871,18 +881,12 @@
jitstate.promotion_path = node
-def leave_graph_yellow(jitstate):
- mydispatchqueue = jitstate.frame.dispatchqueue
- return_chain = mydispatchqueue.return_chain
+def leave_graph_yellow(jitstate, mydispatchqueue):
resuming = jitstate.resuming
- if return_chain is None:
- assert resuming is None
- raise CompilationInterrupted
if resuming is not None:
resuming.leave_call(mydispatchqueue)
+ return_chain = mydispatchqueue.return_chain
jitstate = return_chain
- if resuming is not None:
- resuming.leave_call(mydispatchqueue)
while jitstate is not None:
leave_frame(jitstate)
jitstate = jitstate.next
Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py Fri Oct 6 14:14:40 2006
@@ -1,5 +1,7 @@
import types
from pypy.objspace.flow import model as flowmodel
+from pypy.translator.unsimplify import varoftype
+from pypy.translator.backendopt.ssa import SSA_to_SSI
from pypy.annotation import model as annmodel
from pypy.annotation.pairtype import pair, pairtype
from pypy.rpython import annlowlevel
@@ -69,6 +71,8 @@
self.r_ConstOrVar) = self.s_r_instanceof(cgmodel.GenVarOrConst)
(self.s_Block,
self.r_Block) = self.s_r_instanceof(cgmodel.CodeGenBlock)
+ (self.s_Queue,
+ self.r_Queue) = self.s_r_instanceof(rtimeshift.BaseDispatchQueue)
self.etrafo = hannotator.exceptiontransformer
self.cexcdata = self.etrafo.cexcdata
@@ -140,6 +144,8 @@
jitstate.curbuilder.finish_and_return(graphsigtoken, gv_ret)
self.ll_finish_jitstate = ll_finish_jitstate
+ self.v_queue = varoftype(self.r_Queue.lowleveltype, 'queue')
+
def specialize(self, view=False):
"""
Driver for running the timeshifter.
@@ -177,6 +183,7 @@
# "normalize" the graphs by putting an explicit v_jitstate variable
# everywhere
self.insert_v_jitstate_everywhere(graph)
+ SSA_to_SSI(graph, annotator=self.annotator)
# the graph is now timeshifted, so it is *itself* no longer
# exception-transformed...
del graph.exceptiontransformed
@@ -309,7 +316,6 @@
return result
def insert_v_jitstate_everywhere(self, graph):
- from pypy.translator.unsimplify import varoftype
for block in graph.iterblocks():
v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate')
if block is graph.returnblock:
@@ -567,40 +573,56 @@
# special operations inserted by the HintGraphTransformer
- def translate_op_enter_graph(self, hop):
+
+ def translate_op_ensure_queue(self, hop, prefix=''):
mpfamily = hop.args_v[0].value
subclass = self.get_dispatch_subclass(mpfamily)
s_subclass = self.rtyper.annotator.bookkeeper.immutablevalue(subclass)
c_subclass = inputconst(lltype.Void, subclass)
v_jitstate = hop.llops.getjitstate()
- hop.llops.genmixlevelhelpercall(rtimeshift.enter_graph,
- [self.s_JITState, s_subclass],
- [v_jitstate , c_subclass],
+ ensure_queue = getattr(rtimeshift, prefix+'ensure_queue')
+ v_queue = hop.llops.genmixlevelhelpercall(ensure_queue,
+ [self.s_JITState, s_subclass],
+ [v_jitstate , c_subclass],
+ self.s_Queue)
+ hop.llops.append(flowmodel.SpaceOperation('same_as', [v_queue],
+ self.v_queue))
+
+
+ def translate_op_portal_ensure_queue(self, hop):
+ return self.translate_op_ensure_queue(hop, prefix='portal_')
+
+
+ def translate_op_enter_frame(self, hop):
+ v_jitstate = hop.llops.getjitstate()
+ hop.llops.genmixlevelhelpercall(rtimeshift.enter_frame,
+ [self.s_JITState, self.s_Queue],
+ [v_jitstate , self.v_queue],
annmodel.s_None)
def translate_op_leave_graph_red(self, hop):
v_jitstate = hop.llops.getjitstate()
v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_red,
- [self.s_JITState],
- [v_jitstate ],
- self.s_JITState)
+ [self.s_JITState, self.s_Queue],
+ [v_jitstate , self.v_queue],
+ self.s_JITState)
hop.llops.setjitstate(v_newjs)
def translate_op_leave_graph_gray(self, hop):
v_jitstate = hop.llops.getjitstate()
v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_gray,
- [self.s_JITState],
- [v_jitstate ],
- self.s_JITState)
+ [self.s_JITState, self.s_Queue],
+ [v_jitstate , self.v_queue],
+ self.s_JITState)
hop.llops.setjitstate(v_newjs)
def translate_op_leave_graph_yellow(self, hop):
v_jitstate = hop.llops.getjitstate()
- v_njs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_yellow,
- [self.s_JITState],
- [v_jitstate ],
- self.s_JITState)
- hop.llops.setjitstate(v_njs)
+ v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_yellow,
+ [self.s_JITState, self.s_Queue],
+ [v_jitstate , self.v_queue],
+ self.s_JITState)
+ hop.llops.setjitstate(v_newjs)
def translate_op_save_locals(self, hop):
v_jitstate = hop.llops.getjitstate()
@@ -792,11 +814,8 @@
def call_for_global_resuming(jitstate):
jitstate.frame.dispatchqueue = DispatchQueueSubclass()
jitstate.resumepoint = N
- try:
- finaljitstate = tsfn(jitstate, *dummy_args)
- except rtimeshift.CompilationInterrupted:
- pass
- else:
+ finaljitstate = tsfn(jitstate, *dummy_args)
+ if finaljitstate is not None:
ll_finish_jitstate(finaljitstate, residualSigToken)
return self.translate_op_merge_point(hop,
@@ -812,9 +831,9 @@
def translate_op_dispatch_next(self, hop):
v_jitstate = hop.llops.getjitstate()
v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.dispatch_next,
- [self.s_JITState],
- [v_jitstate ],
- self.s_JITState)
+ [self.s_JITState, self.s_Queue],
+ [v_jitstate , self.v_queue],
+ self.s_JITState)
hop.llops.setjitstate(v_newjs)
def translate_op_getresumepoint(self, hop):
@@ -909,7 +928,13 @@
args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate]
RESULT = lltype.typeOf(fnptr).TO.RESULT
v_newjitstate = hop.genop('direct_call', args_v, RESULT)
- hop.llops.setjitstate(v_newjitstate)
+ v_pickedjs = hop.llops.genmixlevelhelpercall(rtimeshift.pickjitstate,
+ [self.s_JITState, self.s_JITState],
+ [v_jitstate , v_newjitstate ],
+ self.s_JITState)
+ hop.llops.setjitstate(v_pickedjs)
+ return hop.genop('ptr_iszero', [v_newjitstate],
+ resulttype = lltype.Bool)
def translate_op_indirect_red_call(self, hop):
v_jitstate = hop.llops.getjitstate()
@@ -927,7 +952,13 @@
RESULT = v_tsfunc.concretetype.TO.RESULT
args_v.append(hop.inputconst(lltype.Void, graph2ts.values()))
v_newjitstate = hop.genop('indirect_call', args_v, RESULT)
- hop.llops.setjitstate(v_newjitstate)
+ v_pickedjs = hop.llops.genmixlevelhelpercall(rtimeshift.pickjitstate,
+ [self.s_JITState, self.s_JITState],
+ [v_jitstate , v_newjitstate ],
+ self.s_JITState)
+ hop.llops.setjitstate(v_pickedjs)
+ return hop.genop('ptr_iszero', [v_newjitstate],
+ resulttype = lltype.Bool)
translate_op_gray_call = translate_op_red_call
translate_op_indirect_gray_call = translate_op_indirect_red_call
Modified: pypy/dist/pypy/jit/timeshifter/test/test_promotion.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_promotion.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_promotion.py Fri Oct 6 14:14:40 2006
@@ -147,6 +147,43 @@
assert res == 340
self.check_insns(int_lt=1, int_mul=0)
+ def test_more_promotes(self):
+ py.test.skip("in-progress")
+ S = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed))
+ def ll_two(s, i, m):
+ if i < 4:
+ s.x += i
+ return 10
+ else:
+ s.y = i
+ return s.x + m
+ def ll_three(s, k):
+ k = hint(k, promote=True)
+ if s.x > 6:
+ k *= hint(s.y, promote=True)
+ return k
+ else:
+ return hint(1, concrete=True)
+ def ll_function(n, m):
+ s = lltype.malloc(S)
+ s.x = 0
+ s.y = 0
+ i = 0
+ while i < n:
+ k = ll_two(s, i, m)
+ if m & 1:
+ k *= 3
+ else:
+ s.y += 1
+ j = ll_three(s, k)
+ j = hint(j, variable=True)
+ i += j
+ return s.x + s.y * 17
+ ll_function._global_merge_points_ = True
+
+ res = self.timeshift(ll_function, [100, 2], [], policy=P_NOVIRTUAL)
+ assert res == ll_function(100, 2)
+
def test_method_call_nonpromote(self):
class Base(object):
Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Fri Oct 6 14:14:40 2006
@@ -175,12 +175,9 @@
timeshifted_entrypoint_args += (box,)
top_jitstate = fresh_jitstate(builder)
- try:
- top_jitstate = timeshifted_entrypoint(top_jitstate,
+ top_jitstate = timeshifted_entrypoint(top_jitstate,
*timeshifted_entrypoint_args)
- except rtimeshift.CompilationInterrupted:
- pass
- else:
+ if top_jitstate is not None:
finish_jitstate(top_jitstate, sigtoken)
gv_generated = rgenop.gencallableconst(sigtoken, "generated",
Modified: pypy/dist/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/transform.py (original)
+++ pypy/dist/pypy/jit/timeshifter/transform.py Fri Oct 6 14:14:40 2006
@@ -54,8 +54,9 @@
self.split_after_calls()
self.handle_hints()
self.insert_merge_points()
- self.insert_enter_graph()
+ self.insert_enter_frame()
self.insert_dispatcher()
+ self.insert_ensure_queue()
self.insert_leave_graph()
def compute_merge_points(self):
@@ -366,9 +367,17 @@
raise AssertionError(self.graph, self.graphcolor)
self.genop(block, 'save_return', [])
- def insert_enter_graph(self):
+ def insert_ensure_queue(self):
entryblock = self.before_start_block()
- self.genop(entryblock, 'enter_graph', [self.c_mpfamily])
+ if self.mergepointfamily.has_global_mergepoints():
+ prefix = 'portal_'
+ else:
+ prefix = ''
+ self.genop(entryblock, prefix+'ensure_queue', [self.c_mpfamily])
+
+ def insert_enter_frame(self):
+ entryblock = self.before_start_block()
+ self.genop(entryblock, 'enter_frame', [])
def insert_leave_graph(self):
block = self.before_return_block()
@@ -442,7 +451,9 @@
if len(targets) == 1:
[tsgraph] = targets.values()
c_tsgraph = inputconst(lltype.Void, tsgraph)
- self.genop(block, '%s_call' % (color,), [c_tsgraph] + args_v)
+ v_finished = self.genop(block, '%s_call' % (color,),
+ [c_tsgraph] + args_v,
+ resulttype = lltype.Bool)
# Void result, because the call doesn't return its redbox result,
# but only has the hidden side-effect of putting it in the jitstate
else:
@@ -454,7 +465,10 @@
v_greenfunc = self.genop(block, 'revealconst', [args_v[0]],
resulttype = originalconcretetype(hs_func))
args_v[0] = v_greenfunc
- self.genop(block, 'indirect_%s_call' % (color,), args_v)
+ v_finished = self.genop(block, 'indirect_%s_call' % (color,),
+ args_v,
+ resulttype = lltype.Bool)
+ self.go_to_dispatcher_if(block, v_finished)
def handle_red_call(self, block, pos, color='red'):
varsalive = self.variables_alive(block, pos+1)
@@ -486,19 +500,22 @@
constantblock.closeblock(Link([], nextblock))
nonconstantblock.closeblock(Link([], nextblock))
+ postconstantblock = self.naive_split_block(constantblock,
+ len(constantblock.operations))
+ blockset[postconstantblock] = False
self.make_call(constantblock, op, reds, color)
mapping = {}
for i, var in enumerate(reds):
c_index = Constant(i, concretetype=lltype.Signed)
- newvar = self.genop(constantblock, 'restore_local', [c_index],
+ newvar = self.genop(postconstantblock, 'restore_local', [c_index],
result_like = var)
mapping[var] = newvar
if uses_retval:
assert not self.hannotator.binding(op.result).is_green()
var = op.result
- newvar = self.genop(constantblock, 'fetch_return', [],
+ newvar = self.genop(postconstantblock, 'fetch_return', [],
result_like = var)
mapping[var] = newvar
@@ -515,7 +532,7 @@
oldvars = mapping.keys()
newvars = [mapping[v] for v in oldvars]
- constantblock.exits[0].args = newvars
+ postconstantblock.exits[0].args = newvars
nextblock.inputargs = newvars
mapping2 = dict([(v, copyvar(self.hannotator, v))
@@ -578,17 +595,20 @@
nextblock.inputargs.insert(0, v_result)
reds, greens = self.sort_by_color(varsalive)
+ postblock = self.naive_split_block(block, len(block.operations))
self.make_call(block, op, reds, 'yellow')
resumepoint = self.get_resume_point(nextblock)
c_resumepoint = inputconst(lltype.Signed, resumepoint)
- self.genop(block, 'collect_split', [c_resumepoint] + greens)
+ self.genop(postblock, 'collect_split', [c_resumepoint] + greens)
link.args = []
link.target = self.get_resume_point_link(nextblock).target
# to merge some of the possibly many return jitstates
self.mergepoint_set[nextblock] = 'local'
-
+
+ SSA_to_SSI({block: True,
+ postblock: False}, self.hannotator)
# __________ hints __________
More information about the Pypy-commit
mailing list