[pypy-svn] r32032 - in pypy/dist/pypy/jit: codegen/i386 hintannotator hintannotator/test timeshifter timeshifter/test

arigo at codespeak.net arigo at codespeak.net
Wed Sep 6 19:31:35 CEST 2006


Author: arigo
Date: Wed Sep  6 19:31:32 2006
New Revision: 32032

Added:
   pypy/dist/pypy/jit/timeshifter/test/test_exception.py   (contents, props changed)
Modified:
   pypy/dist/pypy/jit/codegen/i386/ri386genop.py
   pypy/dist/pypy/jit/hintannotator/model.py
   pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
   pypy/dist/pypy/jit/timeshifter/rcontainer.py
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
   pypy/dist/pypy/jit/timeshifter/rtyper.py
   pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/dist/pypy/jit/timeshifter/test/test_vlist.py
   pypy/dist/pypy/jit/timeshifter/timeshift.py
Log:
(pedronis, arigo)

Timeshift functions with exceptions.  In more details:

- split JITState / VirtualFrame classes
- exc_value_box and exc_type_box on the jitstate
- more support for functions returning Void
- ptr_iszero/ptr_nonzero operation support (in the
    hintannotator, in the timeshifter, in the i386 
    backend)



Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/ri386genop.py	(original)
+++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py	Wed Sep  6 19:31:32 2006
@@ -363,7 +363,7 @@
         self.mc.MOVZX(eax, al)
         return self.returnvar(eax)
 
-    def op_setarrayitem(self, (gv_ptr, gv_index, gv_value), gv_RESTYPE):
+    def op_setarrayitem(self, hello_world):
         # XXX! only works for GcArray(Signed) for now!!
         XXX-fixme
         A = DUMMY_A
@@ -381,6 +381,9 @@
             op = memSIB(edx, ecx, 0, startoffset)
         self.mc.MOV(op, eax)
 
+    op_ptr_nonzero = op_int_is_true
+    op_ptr_iszero  = op_bool_not        # for now
+
 
 DUMMY_A = lltype.GcArray(lltype.Signed)
 SIZE2SHIFT = {1: 0,

Modified: pypy/dist/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/model.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/model.py	Wed Sep  6 19:31:32 2006
@@ -12,7 +12,9 @@
                       cast_int_to_uint
                       cast_uint_to_int
                       cast_char_to_int
-                      cast_bool_to_int""".split()
+                      cast_bool_to_int
+                      ptr_nonzero
+                      ptr_iszero""".split()
 
 BINARY_OPERATIONS = """int_add int_sub int_mul int_mod int_and int_rshift int_floordiv
                        uint_add uint_sub uint_mul uint_mod uint_and uint_rshift uint_floordiv
@@ -302,6 +304,13 @@
         res_vstruct =hs_s1.contentdef.cast(TO)
         return SomeLLAbstractContainer(res_vstruct)
 
+    def ptr_nonzero(hs_s1):
+        return getbookkeeper().immutablevalue(True)
+
+    def ptr_iszero(hs_s1):
+        return getbookkeeper().immutablevalue(False)
+
+
 # ____________________________________________________________
 # binary
 
@@ -348,6 +357,12 @@
         contentdef = hs_cont1.contentdef.union(hs_cont2.contentdef)
         return SomeLLAbstractContainer(contentdef)
 
+    def ptr_eq((hs_cont1, hs_cont2)):
+        return SomeLLAbstractConstant(lltype.Bool, {})
+
+    def ptr_ne((hs_cont1, hs_cont2)):
+        return SomeLLAbstractConstant(lltype.Bool, {})
+
 
 class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue)):
     def union((hs_cont1, hs_val2)):
@@ -361,6 +376,14 @@
         return pair(hs_cont2, hs_val1).union()
 
 
+class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractValue),
+                 pairtype(SomeLLAbstractValue, SomeLLAbstractContainer)):
+
+    def ptr_eq(_):
+        return getbookkeeper().immutablevalue(False)
+
+    def ptr_ne(_):
+        return getbookkeeper().immutablevalue(True)
 
 
 class __extend__(pairtype(SomeLLAbstractContainer, SomeLLAbstractConstant)):
@@ -369,20 +392,6 @@
         hs_res = hs_a1.contentdef.read_item()
         return reorigin(hs_res, hs_res, hs_index)
 
-    def ptr_eq((hs_cont1, hs_ptr2)):
-        return getbookkeeper().immutablevalue(False)
-
-    def ptr_ne((hs_cont1, hs_ptr2)):
-        return getbookkeeper().immutablevalue(True)    
-
-class __extend__(pairtype(SomeLLAbstractConstant, SomeLLAbstractContainer)):
-
-    def ptr_eq((hs_ptr1, hs_cont2)):
-        return getbookkeeper().immutablevalue(False)
-
-    def ptr_ne((hs_ptr1, hs_cont2)):
-        return getbookkeeper().immutablevalue(True)    
-
 # ____________________________________________________________
 
 def handle_highlevel_operation(bookkeeper, ll_func, *args_hs):

Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py	Wed Sep  6 19:31:32 2006
@@ -507,8 +507,6 @@
         return 0
             
     hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)
-    # xxx this has a green return but the function has side effects
-    # we need to proper notice that for correct timeshifting
     assert isinstance(hs, SomeLLAbstractConstant)
     assert hs.concretetype == lltype.Signed
 
@@ -519,7 +517,5 @@
             raise e
         
     hs = hannotate(g, [bool], policy=P_OOPSPEC_NOVIRTUAL)    
-    # xxx this has a green return but the function has side effects
-    # we need to proper notice that for correct timeshifting
     assert isinstance(hs, SomeLLAbstractConstant)
     assert hs.concretetype == lltype.Signed    

Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py	Wed Sep  6 19:31:32 2006
@@ -126,6 +126,7 @@
         NamedFieldDesc.__init__(self, RGenOp, PTRTYPE, name)
         self.fieldindex = index
         self.gv_default = RGenOp.constPrebuiltGlobal(self.RESTYPE._defl())
+        self.defaultbox = self.redboxcls(self.kind, self.gv_default)
 
 class ArrayFieldDesc(FieldDesc):
     def __init__(self, RGenOp, PTRTYPE):

Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Wed Sep  6 19:31:32 2006
@@ -136,6 +136,22 @@
         argbox.getgenvar(jitstate.curbuilder))
     return rvalue.IntRedBox(fielddesc.indexkind, genvar)
 
+def ll_genptrnonzero(jitstate, argbox, reverse):
+    if argbox.is_constant():
+        addr = rvalue.ll_getvalue(argbox, llmemory.Address)
+        return rvalue.ll_fromvalue(jitstate, bool(addr) ^ reverse)
+    assert isinstance(argbox, rvalue.PtrRedBox)
+    builder = jitstate.curbuilder
+    if argbox.content is None:
+        gv_addr = argbox.getgenvar(builder)
+        if reverse:
+            gv_res = builder.genop1("ptr_iszero", gv_addr)
+        else:
+            gv_res = builder.genop1("ptr_nonzero", gv_addr)
+    else:
+        gv_res = builder.rgenop.genconst(True ^ reverse)
+    return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Bool), gv_res)
+
 # ____________________________________________________________
 # other jitstate/graph level operations
 
@@ -162,7 +178,7 @@
 start_new_block._annspecialcase_ = "specialize:arglltype(2)"
 
 def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes):
-    jitstate.local_boxes = redboxes
+    save_locals(jitstate, redboxes)
     if key not in states_dic:
         start_new_block(states_dic, jitstate, key)
         return False   # continue
@@ -203,47 +219,47 @@
     else:
         exitgvar = switchredbox.getgenvar(jitstate.curbuilder)
         later_builder = jitstate.curbuilder.jump_if_false(exitgvar)
-        memo = rvalue.copy_memo()
-        jitstate.local_boxes = redboxes_false
-        later_jitstate = jitstate.copy(memo)
-        later_jitstate.curbuilder = later_builder
-        later_jitstate.exitindex = exitindex
-        jitstate.split_queue.append(later_jitstate)
-        jitstate.local_boxes = redboxes_true
+        save_locals(jitstate, redboxes_false)
+        jitstate.split(later_builder, exitindex)
+        save_locals(jitstate, redboxes_true)
         enter_block(jitstate)
         return True
 
 def dispatch_next(oldjitstate, return_cache):
-    split_queue = oldjitstate.split_queue
+    split_queue = oldjitstate.frame.split_queue
     if split_queue:
         jitstate = split_queue.pop()
         enter_block(jitstate)
         return jitstate
     else:
-        return_queue = oldjitstate.return_queue
-        for jitstate in return_queue[:-1]:
-            res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
-                                              jitstate.local_boxes)
-            assert res is True   # finished
-        frozen, block = return_cache[()]
-        jitstate = return_queue[-1]
-        retbox = jitstate.local_boxes[0]
-        backstate = jitstate.backstate
-        backstate.curbuilder = jitstate.curbuilder
-        backstate.local_boxes.append(retbox)
-        backstate.exitindex = -1
-        # XXX for now the return value box is put in the parent's local_boxes,
-        # where a 'restore_local' operation will fetch it
-        return backstate
+        return leave_graph(oldjitstate.frame.return_queue, return_cache)
 
 def getexitindex(jitstate):
     return jitstate.exitindex
 
+def save_locals(jitstate, redboxes):
+    jitstate.frame.local_boxes = redboxes
+
 def getlocalbox(jitstate, i):
-    return jitstate.local_boxes[i]
+    return jitstate.frame.local_boxes[i]
+
+def getreturnbox(jitstate):
+    return jitstate.returnbox
+
+def getexctypebox(jitstate):
+    return jitstate.exc_type_box
+
+def getexcvaluebox(jitstate):
+    return jitstate.exc_value_box
+
+def setexctypebox(jitstate, box):
+    jitstate.exc_type_box = box
+
+def setexcvaluebox(jitstate, box):
+    jitstate.exc_value_box = box
 
 def save_return(jitstate):
-    jitstate.return_queue.append(jitstate)
+    jitstate.frame.return_queue.append(jitstate)
 
 def ll_gvar_from_redbox(jitstate, redbox):
     return redbox.getgenvar(jitstate.curbuilder)
@@ -251,69 +267,85 @@
 def ll_gvar_from_constant(jitstate, ll_value):
     return jitstate.curbuilder.rgenop.genconst(ll_value)
 
-def save_locals(jitstate, redboxes):
-    jitstate.local_boxes = redboxes
-
 # ____________________________________________________________
 
 
-class FrozenJITState(object):
-    fz_backstate = None
+class FrozenVirtualFrame(object):
+    fz_backframe = None
     #fz_local_boxes = ... set by freeze()
 
-    def exactmatch(self, jitstate, outgoingvarboxes, memo):
+    def exactmatch(self, vframe, outgoingvarboxes, memo):
         self_boxes = self.fz_local_boxes
-        live_boxes = jitstate.local_boxes
+        live_boxes = vframe.local_boxes
         fullmatch = True
         for i in range(len(self_boxes)):
             if not self_boxes[i].exactmatch(live_boxes[i],
                                             outgoingvarboxes,
                                             memo):
                 fullmatch = False
-        if self.fz_backstate is not None:
-            assert jitstate.backstate is not None
-            if not self.fz_backstate.exactmatch(jitstate.backstate,
+        if self.fz_backframe is not None:
+            assert vframe.backframe is not None
+            if not self.fz_backframe.exactmatch(vframe.backframe,
                                                 outgoingvarboxes,
                                                 memo):
                 fullmatch = False
         else:
-            assert jitstate.backstate is None
+            assert vframe.backframe is None
         return fullmatch
 
 
-class JITState(object):
-    exitindex = -1
+class FrozenJITState(object):
+    #fz_frame = ...           set by freeze()
+    #fz_exc_type_box = ...    set by freeze()
+    #fz_exc_value_box = ...   set by freeze()
 
-    def __init__(self, split_queue, return_queue, builder, backstate):
+    def exactmatch(self, jitstate, outgoingvarboxes, memo):
+        fullmatch = True
+        if not self.fz_frame.exactmatch(jitstate.frame,
+                                        outgoingvarboxes,
+                                        memo):
+            fullmatch = False
+        if not self.fz_exc_type_box.exactmatch(jitstate.exc_type_box,
+                                               outgoingvarboxes,
+                                               memo):
+            fullmatch = False
+        if not self.fz_exc_value_box.exactmatch(jitstate.exc_value_box,
+                                                outgoingvarboxes,
+                                                memo):
+            fullmatch = False
+        return fullmatch
+
+
+class VirtualFrame(object):
+
+    def __init__(self, backframe, split_queue, return_queue):
+        self.backframe = backframe
         self.split_queue = split_queue
         self.return_queue = return_queue
-        self.curbuilder = builder
-        self.backstate = backstate
         #self.local_boxes = ... set by callers
 
     def enter_block(self, incoming, memo):
         for box in self.local_boxes:
             box.enter_block(incoming, memo)
-        if self.backstate is not None:
-            self.backstate.enter_block(incoming, memo)
+        if self.backframe is not None:
+            self.backframe.enter_block(incoming, memo)
 
     def freeze(self, memo):
-        result = FrozenJITState()
+        result = FrozenVirtualFrame()
         frozens = [box.freeze(memo) for box in self.local_boxes]
         result.fz_local_boxes = frozens
-        if self.backstate is not None:
-            result.fz_backstate = self.backstate.freeze(memo)
+        if self.backframe is not None:
+            result.fz_backframe = self.backframe.freeze(memo)
         return result
 
     def copy(self, memo):
-        if self.backstate is None:
-            newbackstate = None
+        if self.backframe is None:
+            newbackframe = None
         else:
-            newbackstate = self.backstate.copy(memo)
-        result = JITState(self.split_queue,
-                          self.return_queue,
-                          None,
-                          newbackstate)
+            newbackframe = self.backframe.copy(memo)
+        result = VirtualFrame(newbackframe,
+                              self.split_queue,
+                              self.return_queue)
         result.local_boxes = [box.copy(memo) for box in self.local_boxes]
         return result
 
@@ -321,14 +353,63 @@
         local_boxes = self.local_boxes
         for i in range(len(local_boxes)):
             local_boxes[i] = local_boxes[i].replace(memo)
-        if self.backstate is not None:
-            self.backstate.replace(memo)
+        if self.backframe is not None:
+            self.backframe.replace(memo)
 
 
-def enter_graph(backstate):
-    return JITState([], [], backstate.curbuilder, backstate)
+class JITState(object):
+    returnbox = None
+
+    def __init__(self, builder, frame, exc_type_box, exc_value_box,
+                 exitindex=-1):
+        self.curbuilder = builder
+        self.frame = frame
+        self.exc_type_box = exc_type_box
+        self.exc_value_box = exc_value_box
+        self.exitindex = exitindex
 
-def fresh_jitstate(builder):
-    jitstate = JITState([], [], builder, None)
-    jitstate.local_boxes = []
+    def split(self, newbuilder, newexitindex):
+        memo = rvalue.copy_memo()
+        later_jitstate = JITState(newbuilder,
+                                  self.frame.copy(memo),
+                                  self.exc_type_box .copy(memo),
+                                  self.exc_value_box.copy(memo),
+                                  newexitindex)
+        self.frame.split_queue.append(later_jitstate)
+
+    def enter_block(self, incoming, memo):
+        self.frame.enter_block(incoming, memo)
+        self.exc_type_box .enter_block(incoming, memo)
+        self.exc_value_box.enter_block(incoming, memo)
+
+    def freeze(self, memo):
+        result = FrozenJITState()
+        result.fz_frame = self.frame.freeze(memo)
+        result.fz_exc_type_box  = self.exc_type_box .freeze(memo)
+        result.fz_exc_value_box = self.exc_value_box.freeze(memo)
+        return result
+
+    def replace(self, memo):
+        self.frame.replace(memo)
+        self.exc_type_box  = self.exc_type_box .replace(memo)
+        self.exc_value_box = self.exc_value_box.replace(memo)
+
+
+def enter_graph(jitstate):
+    jitstate.frame = VirtualFrame(jitstate.frame, [], [])
+
+def leave_graph(return_queue, return_cache):
+    for jitstate in return_queue[:-1]:
+        res = retrieve_jitstate_for_merge(return_cache, jitstate, (),
+                                          # XXX strange next argument
+                                          jitstate.frame.local_boxes)
+        assert res is True   # finished
+    frozen, block = return_cache[()]
+    jitstate = return_queue[-1]
+    myframe = jitstate.frame
+    if myframe.local_boxes:             # else it's a green Void return
+        jitstate.returnbox = myframe.local_boxes[0]
+        # ^^^ fetched by an 'fetch_return' operation
+    jitstate.frame = myframe.backframe
+    jitstate.exitindex = -1
     return jitstate

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Wed Sep  6 19:31:32 2006
@@ -120,6 +120,21 @@
     def translate_op_getfield(self, hop):
         if isinstance(hop.args_r[0], BlueRepr):
             return hop.args_r[0].timeshift_getfield(hop)
+        ts = self.timeshifter
+        if hop.args_v[0] == ts.cexcdata:
+            # reading one of the exception boxes (exc_type or exc_value)
+            fieldname = hop.args_v[1].value
+            if fieldname.endswith('exc_type'):
+                reader = rtimeshift.getexctypebox
+            elif fieldname.endswith('exc_value'):
+                reader = rtimeshift.getexcvaluebox
+            else:
+                raise Exception("getfield(exc_data, %r)" % (fieldname,))
+            v_jitstate = hop.llops.getjitstate()
+            return hop.llops.genmixlevelhelpercall(reader,
+                                                   [ts.s_JITState],
+                                                   [v_jitstate   ],
+                                                   ts.s_RedBox)
         # non virtual case        
         PTRTYPE = originalconcretetype(hop.args_s[0])
         if PTRTYPE.TO._hints.get('immutable', False): # foldable if all green
@@ -127,7 +142,6 @@
             if res is not None:
                 return res
             
-        ts = self.timeshifter
         v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
                                               green_void_repr)
         structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
@@ -183,10 +197,26 @@
     def translate_op_setfield(self, hop):
         if isinstance(hop.args_r[0], BlueRepr):
             return hop.args_r[0].timeshift_setfield(hop)
-        # non virtual case ...
         ts = self.timeshifter        
         PTRTYPE = originalconcretetype(hop.args_s[0])
         VALUETYPE = originalconcretetype(hop.args_s[2])
+        if hop.args_v[0] == ts.cexcdata:
+            # reading one of the exception boxes (exc_type or exc_value)
+            fieldname = hop.args_v[1].value
+            if fieldname.endswith('exc_type'):
+                writer = rtimeshift.setexctypebox
+            elif fieldname.endswith('exc_value'):
+                writer = rtimeshift.setexcvaluebox
+            else:
+                raise Exception("setfield(exc_data, %r)" % (fieldname,))
+            v_valuebox = hop.inputarg(self.getredrepr(VALUETYPE), arg=2)
+            v_jitstate = hop.llops.getjitstate()
+            hop.llops.genmixlevelhelpercall(writer,
+                                            [ts.s_JITState, ts.s_RedBox],
+                                            [v_jitstate,    v_valuebox ],
+                                            annmodel.s_None)
+            return
+        # non virtual case ...
         v_destbox, c_fieldname, v_valuebox = hop.inputargs(self.getredrepr(PTRTYPE),
                                                            green_void_repr,
                                                            self.getredrepr(VALUETYPE)
@@ -227,6 +257,21 @@
         r_result = hop.r_result
         return r_result.create(hop)
 
+    def translate_op_ptr_nonzero(self, hop, reverse=False):
+        ts = self.timeshifter
+        PTRTYPE = originalconcretetype(hop.args_s[0])
+        v_argbox, = hop.inputargs(self.getredrepr(PTRTYPE))
+        v_jitstate = hop.llops.getjitstate()
+        c_reverse = hop.inputconst(lltype.Bool, reverse)
+        return hop.llops.genmixlevelhelpercall(rtimeshift.ll_genptrnonzero,
+            [ts.s_JITState, ts.s_RedBox, annmodel.SomeBool()],
+            [v_jitstate,    v_argbox,    c_reverse          ],
+            ts.s_RedBox)
+
+    def translate_op_ptr_iszero(self, hop):
+        return self.translate_op_ptr_nonzero(hop, reverse=True)
+
+
     def guess_call_kind(self, spaceop):
         assert spaceop.opname == 'direct_call'
         c_func = spaceop.args[0]
@@ -262,6 +307,13 @@
         v_jitstate = hop.llops.getjitstate()
         return ts.read_out_box(hop.llops, v_jitstate, index)
 
+    def translate_op_fetch_return(self, hop):
+        ts = self.timeshifter
+        v_jitstate = hop.llops.getjitstate()
+        return hop.llops.genmixlevelhelpercall(rtimeshift.getreturnbox,
+                                               [ts.s_JITState],
+                                               [v_jitstate   ],
+                                               ts.s_RedBox)
 
     def handle_oopspec_call(self, hop):
         # special-cased call, for things like list methods

Added: pypy/dist/pypy/jit/timeshifter/test/test_exception.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/timeshifter/test/test_exception.py	Wed Sep  6 19:31:32 2006
@@ -0,0 +1,69 @@
+import py
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.llinterp import LLException
+from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
+from pypy.jit.timeshifter.test.test_timeshift import P_NOVIRTUAL
+
+
+class TestException(TimeshiftingTests):
+
+    def test_exception_check_melts_away(self):
+        def ll_two(x):
+            if x == 0:
+                raise ValueError
+            return x-1
+        def ll_function(y):
+            return ll_two(y) + 40
+
+        res = self.timeshift(ll_function, [3], [0], policy=P_NOVIRTUAL)
+        assert res == 42
+        self.check_insns({})
+
+    def test_propagate_exception(self):
+        S = lltype.Struct('S', ('flag', lltype.Signed))
+        s = lltype.malloc(S, immortal=True)
+        def ll_two(x):
+            if x == 0:
+                raise ValueError
+            return x+7
+        def ll_function(y):
+            res = ll_two(y)
+            s.flag = 1
+            return res
+
+        s.flag = 0
+        res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL)
+        assert res == -1
+        assert s.flag == 0
+
+        s.flag = 0
+        res = self.timeshift(ll_function, [0], [0], policy=P_NOVIRTUAL)
+        assert res == -1
+        assert s.flag == 0
+
+        s.flag = 0
+        res = self.timeshift(ll_function, [17], [0], policy=P_NOVIRTUAL)
+        assert res == 24
+        assert s.flag == 1
+        self.check_insns({'setfield': 1})
+
+    def test_catch(self):
+        def ll_two(x):
+            if x == 0:
+                raise ValueError
+            return x+7
+        def ll_function(y):
+            try:
+                return ll_two(y)
+            except ValueError:
+                return 42
+
+        res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL)
+        assert res == 42
+
+        res = self.timeshift(ll_function, [0], [0], policy=P_NOVIRTUAL)
+        assert res == 42
+
+        res = self.timeshift(ll_function, [17], [0], policy=P_NOVIRTUAL)
+        assert res == 24
+        self.check_insns({})

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	Wed Sep  6 19:31:32 2006
@@ -21,8 +21,6 @@
 
 P_NOVIRTUAL = AnnotatorPolicy()
 P_NOVIRTUAL.novirtualcontainer = True
-P_NOVIRTUAL.exceptiontransform = False # XXX for now, needs to make ptr_ne/eq
-                                       # not force things
 
 def getargtypes(annotator, values):
     return [annotation(annotator, x) for x in values]
@@ -91,6 +89,7 @@
 
         # make the timeshifted graphs
         htshift = HintTimeshift(ha, rtyper, self.RGenOp)
+        fresh_jitstate = htshift.ll_fresh_jitstate
         RESTYPE = htshift.originalconcretetype(
             ha.translator.graphs[0].getreturnvar())
         htshift.timeshift()
@@ -172,10 +171,10 @@
                     i += 1
                     timeshifted_entrypoint_args += (box,)
 
-            top_jitstate = rtimeshift.fresh_jitstate(builder)
+            top_jitstate = fresh_jitstate(builder)
             top_jitstate = timeshifted_entrypoint(top_jitstate,
                                                   *timeshifted_entrypoint_args)
-            returnbox = top_jitstate.local_boxes[0]
+            returnbox = rtimeshift.getreturnbox(top_jitstate)
             gv_ret = returnbox.getgenvar(top_jitstate.curbuilder)
             top_jitstate.curbuilder.finish_and_return(sigtoken, gv_ret)
 
@@ -796,3 +795,13 @@
         assert res == 21
         self.check_insns({'int_gt': 1, 'int_add': 1,
                           'int_sub': 1, 'int_mul': 1})
+
+    def test_void_call(self):
+        def ll_do_nothing(x):
+            pass
+        def ll_function(y):
+            ll_do_nothing(y)
+            return y
+
+        res = self.timeshift(ll_function, [3], [], policy=P_NOVIRTUAL)
+        assert res == 3

Modified: pypy/dist/pypy/jit/timeshifter/test/test_vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_vlist.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_vlist.py	Wed Sep  6 19:31:32 2006
@@ -4,8 +4,6 @@
 P_OOPSPEC = AnnotatorPolicy()
 P_OOPSPEC.novirtualcontainer = True
 P_OOPSPEC.oopspec = True
-P_OOPSPEC.exceptiontransform = False # XXX for now, needs to make ptr_ne/eq
-                                     # not force things
 
 
 class TestVList(TimeshiftingTests):

Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/timeshift.py	Wed Sep  6 19:31:32 2006
@@ -49,6 +49,21 @@
 ##        self.r_box_accum = getrepr(self.s_box_accum)
 ##        self.r_box_accum.setup()
 
+        self.cexcdata = hannotator.exceptiontransformer.cexcdata
+        gv_excdata = RGenOp.constPrebuiltGlobal(self.cexcdata.value)
+        LL_EXC_TYPE  = rtyper.exceptiondata.lltype_of_exception_type
+        LL_EXC_VALUE = rtyper.exceptiondata.lltype_of_exception_value
+        null_exc_type_box = rvalue.redbox_from_prebuilt_value(RGenOp,
+                                         lltype.nullptr(LL_EXC_TYPE.TO))
+        null_exc_value_box = rvalue.redbox_from_prebuilt_value(RGenOp,
+                                         lltype.nullptr(LL_EXC_VALUE.TO))
+
+        def ll_fresh_jitstate(builder):
+            return JITState(builder, None,
+                            null_exc_type_box,
+                            null_exc_value_box)
+        self.ll_fresh_jitstate = ll_fresh_jitstate
+
     def s_r_instanceof(self, cls, can_be_None=True):
         # Return a SomeInstance / InstanceRepr pair correspnding to the specified class.
         return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None)
@@ -199,14 +214,13 @@
         newstartblock = self.insert_before_block(self.graph.startblock, None,
                                                  closeblock=True)
         llops = HintLowLevelOpList(self)
-        v_backstate = llops.getjitstate()
+        v_jitstate = llops.getjitstate()
 
         llops.genop('direct_call', [self.c_ll_clearcaches_ptr])
-        v_jitstate1 = llops.genmixlevelhelpercall(rtimeshift.enter_graph,
-                               [self.s_JITState],
-                               [v_backstate],
-                               self.s_JITState)
-        llops.setjitstate(v_jitstate1)
+        llops.genmixlevelhelpercall(rtimeshift.enter_graph,
+                                    [self.s_JITState],
+                                    [v_jitstate     ],
+                                    annmodel.s_None)
         newstartblock.operations = list(llops)
                     
     def insert_before_block(self, block, block_entering_links,
@@ -313,7 +327,7 @@
         orig_key_v = []
         for newvar in newinputargs:
             r = self.hrtyper.bindingrepr(newvar)
-            if isinstance(r, GreenRepr):
+            if isinstance(r, GreenRepr) and r.lowleveltype is not lltype.Void:
                 r_from = getrepr(r.annotation())
                 s_erased = r.erased_annotation()
                 r_to = getrepr(s_erased)
@@ -585,10 +599,7 @@
                 block.operations.insert(i, extraop)
 
                 replacement = {}
-                # XXX for now, the call appends the return value box to
-                # the local_boxes of our jitstate, from where we can fish
-                # it using a 'restore_local' ----------vvvvvvvvvvv
-                for i, var in enumerate(vars_to_save + [op.result]):
+                for i, var in enumerate(vars_to_save):
                     newvar = copyvar(self.hannotator, var)
                     c_index = flowmodel.Constant(i, concretetype=lltype.Signed)
                     extraop = flowmodel.SpaceOperation('restore_local',
@@ -597,6 +608,15 @@
                     block.operations.append(extraop)
                     replacement[var] = newvar
 
+                if isinstance(hrtyper.bindingrepr(op.result), RedRepr):
+                    var = op.result
+                    newvar = copyvar(self.hannotator, var)
+                    extraop = flowmodel.SpaceOperation('fetch_return',
+                                                       [],
+                                                       newvar)
+                    block.operations.append(extraop)
+                    replacement[var] = newvar
+
                 link.args = [replacement.get(var, var) for var in link.args]
                 block = link.target
                 entering_links[block] = [link]



More information about the Pypy-commit mailing list