[pypy-svn] r38059 - in pypy/branch/jit-virtual-world/pypy/jit: goal timeshifter timeshifter/test
arigo at codespeak.net
arigo at codespeak.net
Wed Feb 7 13:39:33 CET 2007
Author: arigo
Date: Wed Feb 7 13:39:28 2007
New Revision: 38059
Modified:
pypy/branch/jit-virtual-world/pypy/jit/goal/targetjit.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rcontainer.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rvalue.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_promotion.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
Log:
(pedronis, arre, arigo) (work from yesterday)
* support debug_assert as giving a hint about a pointer being
zero or nonzero.
* fix a promotion bug by cleaning up where the 'resuming'
attribute lives. Finally got rid of pickjitstate().
* review and clean up of the 'blockset' usage in call handling
in transform.py.
* support for adding a 'split' between a residual call and the
following promotion, for the common case of a promoted value
of zero. Disabled, because it makes compilation time much
worse in practice instead of helping :-( The current idea
about why is that the promotes everywhere have the good
effect of stopping compilation early on paths that will
never be seen at all anyway.
* need to save and restore exceptions around a call to
ll_continue_compilation, otherwise the current run-time
exception unexpectedly shows up in the compiler!
* some general 'assert'ed care when setting known_nonzero.
* create uninitialized backend places when possible.
Modified: pypy/branch/jit-virtual-world/pypy/jit/goal/targetjit.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/goal/targetjit.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/goal/targetjit.py Wed Feb 7 13:39:28 2007
@@ -12,7 +12,9 @@
from pypy.translator.backendopt.all import backend_optimizations
backend_optimizations(self.translator,
inline_threshold=0,
- merge_if_blocks=False)
+ merge_if_blocks=False,
+ constfold=True,
+ remove_asserts=True)
#
task_prehannotatebackendopt = taskdef(task_prehannotatebackendopt,
[TranslationDriver.RTYPE],
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 Wed Feb 7 13:39:28 2007
@@ -85,7 +85,6 @@
self.ll_fresh_jitstate = ll_fresh_jitstate
def ll_finish_jitstate(jitstate, exceptiondesc, graphsigtoken):
- assert jitstate.resuming is None
returnbox = rtimeshift.getreturnbox(jitstate)
gv_ret = returnbox.getgenvar(jitstate)
builder = jitstate.curbuilder
@@ -648,6 +647,22 @@
def translate_op_debug_assert(self, hop):
pass
+ def translate_op_debug_assert_ptr_nonzero(self, hop, nonzeroness=True):
+ hs = hop.args_s[0]
+ if hs.is_green():
+ return
+ v_box = hop.inputarg(self.getredrepr(originalconcretetype(hs)), arg=0)
+ v_box = hop.llops.as_ptrredbox(v_box)
+ c_nonzeroness = hop.inputconst(lltype.Bool, nonzeroness)
+ v_jitstate = hop.llops.getjitstate()
+ hop.llops.genmixlevelhelpercall(rtimeshift.ll_learn_nonzeroness,
+ [self.s_JITState, self.s_PtrRedBox, annmodel.s_Bool],
+ [v_jitstate, v_box , c_nonzeroness ],
+ annmodel.s_None)
+
+ def translate_op_debug_assert_ptr_iszero(self, hop):
+ self.translate_op_debug_assert_ptr_nonzero(hop, nonzeroness=False)
+
def translate_op_resume_point(self, hop):
pass
@@ -917,11 +932,10 @@
annmodel.s_None)
def translate_op_leave_graph_red(self, hop, is_portal=False):
- v_jitstate = hop.llops.getjitstate()
c_is_portal = inputconst(lltype.Bool, is_portal)
v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_red,
- [self.s_JITState, self.s_Queue, annmodel.s_Bool],
- [v_jitstate , self.v_queue, c_is_portal],
+ [self.s_Queue, annmodel.s_Bool],
+ [self.v_queue, c_is_portal],
self.s_JITState)
hop.llops.setjitstate(v_newjs)
@@ -929,18 +943,17 @@
self.translate_op_leave_graph_red(hop, is_portal=True)
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, self.s_Queue],
- [v_jitstate , self.v_queue],
+ [self.s_Queue],
+ [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_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.leave_graph_yellow,
- [self.s_JITState, self.s_Queue],
- [v_jitstate , self.v_queue],
+ v_newjs = hop.llops.genmixlevelhelpercall(
+ rtimeshift.leave_graph_yellow,
+ [self.s_Queue],
+ [self.v_queue],
self.s_JITState)
hop.llops.setjitstate(v_newjs)
@@ -1165,8 +1178,10 @@
DispatchQueueSubclass = self.get_dispatch_subclass(mpfamily)
- def call_for_global_resuming(jitstate):
- jitstate.frame.dispatchqueue = DispatchQueueSubclass()
+ def call_for_global_resuming(jitstate, resuming):
+ dispatchqueue = DispatchQueueSubclass()
+ dispatchqueue.resuming = resuming
+ jitstate.frame.dispatchqueue = dispatchqueue
jitstate.resumepoint = N
finaljitstate = tsfn(jitstate, *dummy_args)
if finaljitstate is not None:
@@ -1184,11 +1199,10 @@
annmodel.s_None)
def translate_op_dispatch_next(self, hop):
- v_jitstate = hop.llops.getjitstate()
v_newjs = hop.llops.genmixlevelhelpercall(rtimeshift.dispatch_next,
- [self.s_JITState, self.s_Queue],
- [v_jitstate , self.v_queue],
- self.s_JITState)
+ [self.s_Queue],
+ [self.v_queue],
+ self.s_JITState)
hop.llops.setjitstate(v_newjs)
def translate_op_getresumepoint(self, hop):
@@ -1318,11 +1332,7 @@
args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate]
RESULT = lltype.typeOf(fnptr).TO.RESULT
v_newjitstate = hop.genop('direct_call', args_v, RESULT)
- 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)
+ hop.llops.setjitstate(v_newjitstate)
return hop.genop('ptr_iszero', [v_newjitstate],
resulttype = lltype.Bool)
@@ -1342,11 +1352,7 @@
RESULT = v_tsfunc.concretetype.TO.RESULT
args_v.append(hop.inputconst(lltype.Void, graph2ts.values()))
v_newjitstate = hop.genop('indirect_call', args_v, RESULT)
- 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)
+ hop.llops.setjitstate(v_newjitstate)
return hop.genop('ptr_iszero', [v_newjitstate],
resulttype = lltype.Bool)
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rcontainer.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rcontainer.py Wed Feb 7 13:39:28 2007
@@ -604,8 +604,7 @@
memo.containers[self] = vrti
builder = jitstate.curbuilder
- place = builder.alloc_frame_place(typedesc.ptrkind,
- typedesc.gv_null)
+ place = builder.alloc_frame_place(typedesc.ptrkind)
gv_forced = builder.genop_absorb_place(typedesc.ptrkind, place)
vrti.forced_place = place
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 Wed Feb 7 13:39:28 2007
@@ -210,7 +210,7 @@
incoming[i].genvar = linkargs[i]
return newblock
-def return_marker(jitstate):
+def return_marker(jitstate, resuming):
raise AssertionError("shouldn't get here")
def start_new_block(states_dic, jitstate, key, global_resumer, index=-1):
@@ -228,7 +228,7 @@
states_dic[key][index] = (frozen, newblock)
if global_resumer is not None and global_resumer is not return_marker:
- assert jitstate.resuming is None
+ assert jitstate.get_resuming() is None
jitstate.curbuilder.log('start_new_block %s' % (key,))
greens_gv = jitstate.greens
rgenop = jitstate.curbuilder.rgenop
@@ -298,7 +298,7 @@
box.content = content.cleanup_partial_data(keep)
def merge_generalized(jitstate):
- resuming = jitstate.resuming
+ resuming = jitstate.get_resuming()
if resuming is None:
node = jitstate.promotion_path
while not node.cut_limit:
@@ -327,7 +327,7 @@
return exitgvar.revealconst(lltype.Bool)
else:
# XXX call another function with list(greens_gv) instead
- resuming = jitstate.resuming
+ resuming = jitstate.get_resuming()
if resuming is not None and resuming.mergesleft == 0:
node = resuming.path.pop()
assert isinstance(node, PromotionPathSplit)
@@ -350,7 +350,7 @@
return exitgvar.revealconst(lltype.Bool)
else:
# XXX call another function with list(greens_gv) instead
- resuming = jitstate.resuming
+ resuming = jitstate.get_resuming()
if resuming is not None and resuming.mergesleft == 0:
node = resuming.path.pop()
assert isinstance(node, PromotionPathSplit)
@@ -380,7 +380,7 @@
# and all the other jitstates in the chain are paused
greens_gv = list(greens_gv)
pending = jitstate_chain
- resuming = jitstate_chain.resuming
+ resuming = jitstate_chain.get_resuming()
if resuming is not None and resuming.mergesleft == 0:
node = resuming.path.pop()
assert isinstance(node, PromotionPathCollectSplit)
@@ -423,7 +423,7 @@
newchain = jitstate
dispatchqueue.split_chain = newchain
-def dispatch_next(oldjitstate, dispatchqueue):
+def dispatch_next(dispatchqueue):
if dispatchqueue.split_chain is not None:
jitstate = dispatchqueue.split_chain
dispatchqueue.split_chain = jitstate.next
@@ -435,17 +435,13 @@
jitstate.curbuilder.start_writing()
return jitstate
else:
- oldjitstate.resumepoint = -1
- return oldjitstate
+ return None
def getresumepoint(jitstate):
- return jitstate.resumepoint
-
-def pickjitstate(oldjitstate, newjitstate):
- if newjitstate is not None:
- return newjitstate
+ if jitstate is None:
+ return -1 # done
else:
- return oldjitstate
+ return jitstate.resumepoint
def save_locals(jitstate, *redboxes):
redboxes = list(redboxes)
@@ -479,8 +475,8 @@
jitstate.exc_value_box = box
def setexception(jitstate, typebox, valuebox):
- typebox.known_nonzero = True
- valuebox.known_nonzero = True
+ typebox .learn_nonzeroness(jitstate, True)
+ valuebox.learn_nonzeroness(jitstate, True)
jitstate.exc_type_box = typebox
jitstate.exc_value_box = valuebox
@@ -491,6 +487,9 @@
jitstate.next = dispatchqueue.return_chain
dispatchqueue.return_chain = jitstate
+def ll_learn_nonzeroness(jitstate, ptrbox, nonzeroness):
+ ptrbox.learn_nonzeroness(jitstate, nonzeroness)
+
##def ll_gvar_from_redbox(jitstate, redbox):
## return redbox.getgenvar(jitstate)
@@ -615,10 +614,9 @@
incoming[i].genvar = vars_gv[i]
jitstate.curbuilder = builder
jitstate.greens = self.greens_gv
- jitstate.resuming = resuminginfo
assert jitstate.frame.backframe is None
resuminginfo.merges_to_see()
- self.global_resumer(jitstate)
+ self.global_resumer(jitstate, resuminginfo)
builder.show_incremental_progress()
class PromotionPathNode(AbstractPromotionPath):
@@ -695,6 +693,7 @@
annmodel.lltype_to_annotation(ERASED)],
annmodel.s_None, needtype=True)
RGenOp = hrtyper.RGenOp
+ self.exceptiondesc = hrtyper.exceptiondesc
self.gv_continue_compilation = RGenOp.constPrebuiltGlobal(fnptr)
self.sigtoken = RGenOp.sigToken(lltype.typeOf(fnptr).TO)
## self.PROMOTION_POINT = r_PromotionPoint.lowleveltype
@@ -714,7 +713,8 @@
incoming_gv = [box.genvar for box in incoming]
flexswitch, default_builder = builder.flexswitch(gv_switchvar,
incoming_gv)
- if jitstate.resuming is None:
+ resuming = jitstate.get_resuming()
+ if resuming is None:
jitstate.curbuilder = default_builder
# default case of the switch:
pm = PromotionPoint(flexswitch, incoming_gv,
@@ -723,9 +723,18 @@
ll_pm = cast_instance_to_base_ptr(pm)
gv_pm = default_builder.rgenop.genconst(ll_pm)
gv_switchvar = promotebox.genvar
+ exceptiondesc = promotiondesc.exceptiondesc
+ gv_exc_type = exceptiondesc.genop_get_exc_type (default_builder)
+ gv_exc_value = exceptiondesc.genop_get_exc_value(default_builder)
+ exceptiondesc.genop_set_exc_type (default_builder,
+ exceptiondesc.gv_null_exc_type )
+ exceptiondesc.genop_set_exc_value(default_builder,
+ exceptiondesc.gv_null_exc_value)
default_builder.genop_call(promotiondesc.sigtoken,
promotiondesc.gv_continue_compilation,
[gv_pm, gv_switchvar])
+ exceptiondesc.genop_set_exc_type (default_builder, gv_exc_type )
+ exceptiondesc.genop_set_exc_value(default_builder, gv_exc_value)
linkargs = []
for box in incoming:
linkargs.append(box.getgenvar(jitstate))
@@ -733,7 +742,6 @@
return True
else:
assert jitstate.promotion_path is None
- resuming = jitstate.resuming
if resuming.mergesleft != 0:
default_builder.pause_writing([])
return True
@@ -757,7 +765,7 @@
incoming[i].genvar = incoming_gv[i]
flexswitch = pm.flexswitch
promotebox.setgenvar(promotenode.gv_value)
- jitstate.resuming = None
+ jitstate.clear_resuming()
node = PromotionPathMergesToSee(promotenode, 0)
jitstate.promotion_path = node
else:
@@ -771,6 +779,7 @@
# ____________________________________________________________
class BaseDispatchQueue(object):
+ resuming = None
def __init__(self):
self.split_chain = None
@@ -933,15 +942,13 @@
generated_oop_residual_can_raise = False
def __init__(self, builder, frame, exc_type_box, exc_value_box,
- resumepoint=-1, newgreens=[], resuming=None,
- virtualizables=None):
+ resumepoint=-1, newgreens=[], virtualizables=None):
self.curbuilder = builder
self.frame = frame
self.exc_type_box = exc_type_box
self.exc_value_box = exc_value_box
self.resumepoint = resumepoint
self.greens = newgreens
- self.resuming = resuming # None or a ResumingInfo
# XXX can not be adictionary
# it needs to be iterated in a deterministic order.
@@ -966,7 +973,6 @@
self.exc_value_box.copy(memo),
newresumepoint,
newgreens,
- self.resuming,
virtualizables)
# add the later_jitstate to the chain of pending-for-dispatch_next()
dispatchqueue = self.frame.dispatchqueue
@@ -1109,7 +1115,17 @@
def residual_exception(self, e):
self.residual_ll_exception(cast_instance_to_base_ptr(e))
-
+
+
+ def get_resuming(self):
+ return self.frame.dispatchqueue.resuming
+
+ def clear_resuming(self):
+ f = self.frame
+ while f is not None:
+ f.dispatchqueue.resuming = None
+ f = f.backframe
+
def start_writing(jitstate=None, prevopen=None):
if jitstate is not prevopen:
@@ -1124,18 +1140,22 @@
ensure_queue._annspecialcase_ = 'specialize:arg(1)'
def replayable_ensure_queue(jitstate, DispatchQueueClass):
- resuming = jitstate.resuming
- if resuming is None:
+ if jitstate.frame is None: # common case
return DispatchQueueClass()
else:
+ # replaying
dispatchqueue = jitstate.frame.dispatchqueue
assert isinstance(dispatchqueue, DispatchQueueClass)
return dispatchqueue
replayable_ensure_queue._annspecialcase_ = 'specialize:arg(1)'
def enter_frame(jitstate, dispatchqueue):
+ if jitstate.frame:
+ resuming = jitstate.get_resuming()
+ dispatchqueue.resuming = resuming
+ else:
+ resuming = None
jitstate.frame = VirtualFrame(jitstate.frame, dispatchqueue)
- resuming = jitstate.resuming
if resuming is None:
node = PromotionPathCall(jitstate.promotion_path)
node = PromotionPathMergesToSee(node, 0)
@@ -1152,7 +1172,7 @@
parent_mergesleft = MC_CALL_NOT_TAKEN
dispatchqueue.mergecounter = parent_mergesleft
-def merge_returning_jitstates(jitstate, dispatchqueue, force_merge=False):
+def merge_returning_jitstates(dispatchqueue, force_merge=False):
return_chain = dispatchqueue.return_chain
return_cache = {}
still_pending = None
@@ -1191,9 +1211,9 @@
start_writing(still_pending, opened)
return still_pending
-def leave_graph_red(jitstate, dispatchqueue, is_portal):
- resuming = jitstate.resuming
- return_chain = merge_returning_jitstates(jitstate, dispatchqueue,
+def leave_graph_red(dispatchqueue, is_portal):
+ resuming = dispatchqueue.resuming
+ return_chain = merge_returning_jitstates(dispatchqueue,
force_merge=is_portal)
if is_portal:
assert return_chain is None or return_chain.next is None
@@ -1208,9 +1228,9 @@
jitstate = jitstate.next
return return_chain
-def leave_graph_gray(jitstate, dispatchqueue):
- resuming = jitstate.resuming
- return_chain = merge_returning_jitstates(jitstate, dispatchqueue)
+def leave_graph_gray(dispatchqueue):
+ resuming = dispatchqueue.resuming
+ return_chain = merge_returning_jitstates(dispatchqueue)
if resuming is not None:
resuming.leave_call(dispatchqueue)
jitstate = return_chain
@@ -1222,10 +1242,11 @@
return return_chain
def leave_frame(jitstate):
+ resuming = jitstate.get_resuming()
myframe = jitstate.frame
backframe = myframe.backframe
jitstate.frame = backframe
- if jitstate.resuming is None:
+ if resuming is None:
#debug_view(jitstate)
node = jitstate.promotion_path
while not node.cut_limit:
@@ -1238,8 +1259,8 @@
jitstate.promotion_path = node
-def leave_graph_yellow(jitstate, mydispatchqueue):
- resuming = jitstate.resuming
+def leave_graph_yellow(mydispatchqueue):
+ resuming = mydispatchqueue.resuming
if resuming is not None:
resuming.leave_call(mydispatchqueue)
return_chain = mydispatchqueue.return_chain
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rvalue.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rvalue.py Wed Feb 7 13:39:28 2007
@@ -195,10 +195,16 @@
def learn_nonzeroness(self, jitstate, nonzeroness):
if nonzeroness:
- self.known_nonzero = True
+ if self.is_constant():
+ assert self.known_nonzero # already
+ else:
+ self.known_nonzero = True
else:
- gv_null = jitstate.curbuilder.rgenop.genzeroconst(self.kind)
- self.setgenvar_hint(gv_null, known_nonzero=False)
+ if self.is_constant():
+ assert not self.genvar.revealconst(llmemory.Address)
+ else:
+ gv_null = jitstate.curbuilder.rgenop.genzeroconst(self.kind)
+ self.setgenvar_hint(gv_null, known_nonzero=False)
def __repr__(self):
if not self.genvar and self.content is not None:
@@ -207,7 +213,7 @@
return RedBox.__repr__(self)
def op_getfield(self, jitstate, fielddesc):
- self.known_nonzero = True
+ self.learn_nonzeroness(jitstate, True)
if self.content is not None:
box = self.content.op_getfield(jitstate, fielddesc)
if box is not None:
@@ -219,7 +225,7 @@
return box
def op_setfield(self, jitstate, fielddesc, valuebox):
- self.known_nonzero = True
+ self.learn_nonzeroness(jitstate, True)
gv_ptr = self.genvar
if gv_ptr:
fielddesc.generate_set(jitstate, gv_ptr,
@@ -229,7 +235,7 @@
self.content.op_setfield(jitstate, fielddesc, valuebox)
def op_getsubstruct(self, jitstate, fielddesc):
- self.known_nonzero = True
+ self.learn_nonzeroness(jitstate, True)
gv_ptr = self.genvar
if gv_ptr:
return fielddesc.generate_getsubstruct(jitstate, gv_ptr)
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_promotion.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_promotion.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_promotion.py Wed Feb 7 13:39:28 2007
@@ -384,3 +384,25 @@
res = self.timeshift(ll_function, [4], [], policy=P_NOVIRTUAL)
assert res == 6
self.check_insns(int_add=0)
+
+ def test_two_promotions_in_call(self):
+ def ll_two(n, m):
+ if n < 1:
+ return m
+ else:
+ return n
+
+ def ll_one(n, m):
+ n = ll_two(n, m)
+ n = hint(n, promote=True)
+ m = hint(m, promote=True)
+ return hint(n + m, variable=True)
+
+ def ll_function(n, m):
+ hint(None, global_merge_point=True)
+ c = ll_one(n, m)
+ return c
+
+ res = self.timeshift(ll_function, [4, 7], [], policy=P_NOVIRTUAL)
+ assert res == 11
+ self.check_insns(int_add=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 Wed Feb 7 13:39:28 2007
@@ -7,7 +7,7 @@
from pypy.jit.timeshifter import rtimeshift, rvalue
from pypy.objspace.flow.model import summary, Variable
from pypy.rpython.lltypesystem import lltype, llmemory, rstr
-from pypy.rlib.objectmodel import hint, keepalive_until_here
+from pypy.rlib.objectmodel import hint, keepalive_until_here, debug_assert
from pypy.rlib.unroll import unrolling_iterable
from pypy.rpython.annlowlevel import PseudoHighLevelCallable
from pypy.rpython.module.support import LLSupport
@@ -1349,6 +1349,29 @@
assert res == 250
self.check_insns(int_mul=1, int_add=0)
+ def test_debug_assert_ptr_nonzero(self):
+ S = lltype.GcStruct('s', ('x', lltype.Signed))
+ def h():
+ s = lltype.malloc(S)
+ s.x = 42
+ return s
+ def g(s):
+ # assumes that s is not null here
+ debug_assert(bool(s), "please don't give me a null")
+ return 5
+ def f(m):
+ s = h()
+ n = g(s)
+ if not s:
+ n *= m
+ return n
+
+ P = StopAtXPolicy(h)
+
+ res = self.timeshift(f, [17], [], policy=P)
+ assert res == 5
+ self.check_insns(int_mul=0)
+
def test_indirect_red_call(self):
def h1(n):
return n*2
@@ -1382,7 +1405,7 @@
try:
return g(n, x)
except ValueError:
- return -1
+ return -1111
P = StopAtXPolicy()
res = self.timeshift(f, [7, 3], policy=P)
@@ -1390,7 +1413,7 @@
self.check_insns(indirect_call=1)
res = self.timeshift(f, [-7, 3], policy=P)
- assert res == -1
+ assert res == -1111
self.check_insns(indirect_call=1)
def test_indirect_gray_call(self):
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 Wed Feb 7 13:39:28 2007
@@ -127,6 +127,16 @@
op.opname = replace[op.opname]
op.args = [v1]
break
+ # debug_assert(ptr_iszero(p)) => debug_assert_ptr_iszero(p)
+ # debug_assert(ptr_nonzero(p)) => debug_assert_ptr_nonzero(p)
+ for block in self.graph.iterblocks():
+ for op in block.operations:
+ if op.opname == 'debug_assert':
+ v = op.args[0]
+ srcopname, srcargs = self.trace_back_bool_var(block, v)
+ if srcopname in ('ptr_iszero', 'ptr_nonzero'):
+ op.opname += '_' + srcopname
+ op.args[0] = srcargs[0]
def graph_calling_color(self, tsgraph):
args_hs, hs_res = self.hannotator.bookkeeper.tsgraphsigs[tsgraph]
@@ -263,11 +273,10 @@
if not hs_switch.is_green():
self.insert_split_handling(block)
- def trace_back_exitswitch(self, block):
+ def trace_back_bool_var(self, block, v):
"""Return the (opname, arguments) that created the exitswitch of
the block. The opname is None if not found.
"""
- v = block.exitswitch
inverted = False
for i in range(len(block.operations)-1, -1, -1):
op = block.operations[i]
@@ -293,7 +302,7 @@
# try to look where the v_redswitch comes from
split_variant = ''
split_extras = []
- srcopname, srcargs = self.trace_back_exitswitch(block)
+ srcopname, srcargs = self.trace_back_bool_var(block, block.exitswitch)
if srcopname == 'ptr_nonzero':
split_variant = '_ptr_nonzero'
split_extras = srcargs
@@ -603,17 +612,20 @@
nextblock.inputargs.insert(0, v_result)
reds, greens = self.sort_by_color(varsalive)
+ blockset = {}
+ blockset[block] = True # reachable from outside
+ blockset[nextblock] = False
+
v_func = op.args[0]
hs_func = self.hannotator.binding(v_func)
if hs_func.is_green():
constantblock = block
nonconstantblock = None
- blockset = {}
else:
constantblock = Block([])
nonconstantblock = Block([])
- blockset = {constantblock: False,
- nonconstantblock: False}
+ blockset[constantblock] = False
+ blockset[nonconstantblock] = False
v_is_constant = self.genop(block, 'is_constant', [v_func],
resulttype = lltype.Bool)
self.genswitch(block, v_is_constant, true = constantblock,
@@ -639,6 +651,7 @@
self.hannotator.bindings[v0] = hs
conversionblock.closeblock(Link(conversionblock.inputargs,
nextblock))
+ blockset[conversionblock] = False
# to merge some of the possibly many return jitstates
self.mergepoint_set[nextblock] = 'local'
@@ -647,23 +660,16 @@
self.genop(postconstantblock, 'collect_split', [c_resumepoint] + greens)
resumeblock = self.get_resume_point_link(conversionblock).target
postconstantblock.recloseblock(Link([], resumeblock))
+ blockset[resumeblock] = True # reachable from outside
if nonconstantblock is not None:
nonconstantblock.recloseblock(Link(linkargs, nextblock))
- v_res, nonconstantblock2 = self.handle_residual_call_details(
+ v_res = self.handle_residual_call_details(
nonconstantblock, 0, op,
- color, preserve_res =
+ color, blockset, preserve_res =
(color != 'gray'),
withexc=withexc)
- #if color == 'red':
- # linkargs[0] = v_res
-
- blockset[nonconstantblock2] = False
-
-
- blockset[block] = True # reachable from outside
- blockset[nextblock] = True # reachable from outside
SSA_to_SSI(blockset, self.hannotator)
def handle_gray_call(self, block, pos, withexc):
@@ -689,13 +695,13 @@
link_f.args = linkargs
link_f.target = nextblock
residualblock.closeblock(Link(linkargs, nextblock))
- residualblock2 = self.handle_after_residual_call_details(
- residualblock, 0, [], oop=True,
+ blockset = { block: True,
+ nextblock: False,
+ residualblock: False }
+ self.handle_after_residual_call_details(
+ residualblock, 0, [], blockset, oop=True,
withexc=True)
- blockset = { block: True, nextblock: False,
- residualblock: False,
- residualblock2: False }
SSA_to_SSI(blockset, self.hannotator)
def handle_vable_call(self, block, pos):
@@ -736,11 +742,14 @@
color = 'gray'
else:
color = 'red'
- v_res, _ = self.handle_residual_call_details(block, pos, op, color,
- withexc)
+ blockset = {block: True}
+ v_res = self.handle_residual_call_details(block, pos, op, color,
+ blockset, withexc)
+ SSA_to_SSI(blockset, self.hannotator)
return v_res
-
- def handle_residual_call_details(self, block, pos, op, color, withexc,
+
+ def handle_residual_call_details(self, block, pos, op, color,
+ blockset, withexc,
preserve_res=True):
if op.opname == 'direct_call':
args_v = op.args[1:]
@@ -758,14 +767,14 @@
if preserve_res:
v_res = newops[call_index].result = op.result
- nextblock = self.handle_after_residual_call_details(block, pos,
- newops, withexc)
-
- return v_res, nextblock
+ self.handle_after_residual_call_details(block, pos,
+ newops, blockset,
+ withexc)
+ return v_res
- def handle_after_residual_call_details(self, block, pos, newops, withexc,
- oop = False):
+ def handle_after_residual_call_details(self, block, pos, newops, blockset,
+ withexc, oop = False):
dopts = {'withexc': withexc, 'oop': oop }
copts = Constant(dopts, lltype.Void)
v_flags = self.genop(newops, 'after_residual_call', [copts],
@@ -775,16 +784,46 @@
residual_fetch_pos = pos+residual_fetch_index
block.operations[pos:pos+1] = newops
- link = split_block(self.hannotator, block, residual_fetch_pos)
- nextblock = link.target
+ link_t = split_block(self.hannotator, block, residual_fetch_pos)
+ nextblock = link_t.target
+ blockset[nextblock] = False
+ i_flags = link_t.args.index(v_flags)
- reds, greens = self.sort_by_color(link.args)
+ reds, greens = self.sort_by_color(link_t.args)
self.genop(block, 'save_locals', reds)
- v_finished_flag = self.genop(block, 'promote', [v_flags],
+
+ SPLIT_FOR_ZERO = False
+
+ if SPLIT_FOR_ZERO:
+ promoteblock = Block([copyvar(self.hannotator, v)
+ for v in link_t.args])
+ link_f = Link(link_t.args, promoteblock)
+ promoteblock.recloseblock(Link(promoteblock.inputargs, nextblock))
+ blockset[promoteblock] = False
+ v_flags2 = promoteblock.inputargs[i_flags]
+ else:
+ promoteblock = block
+ v_flags2 = v_flags
+ v_finished_flag = self.genop(promoteblock, 'promote', [v_flags2],
resulttype = lltype.Bool)
- self.go_to_dispatcher_if(block, v_finished_flag)
+ self.go_to_dispatcher_if(promoteblock, v_finished_flag)
- return nextblock
+ if SPLIT_FOR_ZERO:
+ c_zero = inputconst(lltype.Signed, 0)
+ link_t.args = link_t.args[:]
+ link_t.args[i_flags] = c_zero
+
+ resumepoint = self.get_resume_point(promoteblock)
+ c_resumepoint = inputconst(lltype.Signed, resumepoint)
+ v_is_zero = self.genop(block, 'int_eq', [v_flags, c_zero],
+ resulttype=lltype.Bool, red=True)
+ v_is_zero = self.genop(block, 'split',
+ [v_is_zero, c_resumepoint] + greens,
+ resulttype = lltype.Bool)
+ block.exitswitch = v_is_zero
+ link_t.exitcase = True
+ link_f.exitcase = False
+ block.recloseblock(link_f, link_t)
# __________ hints __________
More information about the Pypy-commit
mailing list