[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