[pypy-svn] r64691 - in pypy/branch/pyjitpl5/pypy/jit: backend backend/llgraph backend/test metainterp metainterp/test

arigo at codespeak.net arigo at codespeak.net
Sun Apr 26 16:35:55 CEST 2009


Author: arigo
Date: Sun Apr 26 16:35:53 2009
New Revision: 64691

Modified:
   pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
   pypy/branch/pyjitpl5/pypy/jit/backend/model.py
   pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
Log:
Replace _save_recursive_call() with an interface change.  The idea is
that the backend should not patch the real boxes in-place, but only
expose the result via an interface, get_latest_value_xxx().  The
front-end will then copy the values into the boxes in a try:finally:,
and restore their value afterwards.  It's expected to be much safer than
the previous hack.


Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/runner.py	Sun Apr 26 16:35:53 2009
@@ -176,28 +176,20 @@
                 raise Exception("bad box in valueboxes: %r" % (box,))
         # run the loop
         fail_index = llimpl.frame_execute(frame)
-        # we hit a FAIL operation.  Fish for the values
-        # (in a real backend, this should be done by the FAIL operation
-        # itself, not here)
-        op = self.fail_ops[fail_index]
-        for i in range(len(op.args)):
-            box = op.args[i]
-            if isinstance(box, history.BoxInt):
-                value = llimpl.frame_int_getvalue(frame, i)
-                box.changevalue_int(value)
-            elif isinstance(box, history.BoxPtr):
-                value = llimpl.frame_ptr_getvalue(frame, i)
-                box.changevalue_ptr(value)
-            elif self.is_oo and isinstance(box, history.BoxObj):
-                value = llimpl.frame_ptr_getvalue(frame, i)
-                box.changevalue_obj(value)
-            elif isinstance(box, history.ConstInt):
-                pass
-            elif isinstance(box, history.ConstPtr):
-                pass
-            else:
-                raise Exception("bad box in 'fail': %r" % (box,))
-        return op
+        # we hit a FAIL operation.
+        self.latest_frame = frame
+        return self.fail_ops[fail_index]
+
+    def get_latest_value_int(self, index):
+        return llimpl.frame_int_getvalue(self.latest_frame, index)
+
+    def get_latest_value_ptr(self, index):
+        return llimpl.frame_ptr_getvalue(self.latest_frame, index)
+
+    def get_latest_value_obj(self, index):
+        return llimpl.frame_ptr_getvalue(self.latest_frame, index)
+
+    # ----------
 
     def get_exception(self):
         return self.cast_adr_to_int(llimpl.get_exception())

Modified: pypy/branch/pyjitpl5/pypy/jit/backend/model.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/model.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/model.py	Sun Apr 26 16:35:53 2009
@@ -9,7 +9,22 @@
         Returns the ResOperation that failed, of type rop.FAIL.
         """
         raise NotImplementedError
-    
+
+    def get_latest_value_int(self, index):
+        """Returns the value for the index'th argument to the
+        lastest rop.FAIL.  Returns an int."""
+        raise NotImplementedError
+
+    def get_latest_value_ptr(self, index):
+        """Returns the value for the index'th argument to the
+        lastest rop.FAIL.  Returns a ptr."""
+        raise NotImplementedError
+
+    def get_latest_value_obj(self, index):
+        """Returns the value for the index'th argument to the
+        lastest rop.FAIL.  Returns an obj."""
+        raise NotImplementedError
+
     def get_exception(self):
         raise NotImplementedError
 

Modified: pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/test/runner.py	Sun Apr 26 16:35:53 2009
@@ -29,8 +29,10 @@
             self.guard_failed = False
         else:
             self.guard_failed = True
-        if result_type != 'void':
-            return res.args[0]
+        if result_type == 'int':
+            return BoxInt(self.cpu.get_latest_value_int(0))
+        elif result_type == 'ptr':
+            return BoxPtr(self.cpu.get_latest_value_ptr(0))
 
     def get_compiled_single_operation(self, opnum, result_type, valueboxes,
                                       descr):

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py	Sun Apr 26 16:35:53 2009
@@ -44,31 +44,32 @@
 
 class IndirectCallset(history.AbstractValue):
     def __init__(self, codewriter, graphs):
-        keys = []
-        values = []
+        self.keys = []
+        self.values = []
         for graph in graphs:
             fnptr = codewriter.rtyper.getcallable(graph)
             fnaddress = codewriter.ts.cast_fnptr_to_root(fnptr)
-            keys.append(fnaddress)
-            values.append(codewriter.get_jitcode(graph))
+            self.keys.append(fnaddress)
+            self.values.append(codewriter.get_jitcode(graph))
+        self.dict = None
 
-        def bytecode_for_address(fnaddress):
-            if we_are_translated():
-                if self.dict is None:
-                    # Build the dictionary at run-time.  This is needed
-                    # because the keys are function addresses, so they
-                    # can change from run to run.
-                    self.dict = {}
-                    for i in range(len(keys)):
-                        self.dict[keys[i]] = values[i]
-                return self.dict[fnaddress]
-            else:
+    def bytecode_for_address(self, fnaddress):
+        if we_are_translated():
+            if self.dict is None:
+                # Build the dictionary at run-time.  This is needed
+                # because the keys are function addresses, so they
+                # can change from run to run.
+                self.dict = {}
+                keys = self.keys
+                values = self.values
                 for i in range(len(keys)):
-                    if fnaddress == keys[i]:
-                        return values[i]
-                raise KeyError(fnaddress)
-        self.bytecode_for_address = bytecode_for_address
-        self.dict = None
+                    self.dict[keys[i]] = values[i]
+            return self.dict[fnaddress]
+        else:
+            for i in range(len(self.keys)):
+                if fnaddress == self.keys[i]:
+                    return self.values[i]
+            raise KeyError(fnaddress)
 
 class SwitchDict(history.AbstractValue):
     "Get a 'dict' attribute mapping integer values to bytecode positions."

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py	Sun Apr 26 16:35:53 2009
@@ -6,7 +6,8 @@
 
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.history import TreeLoop, log, Box, History
-from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr
+from pypy.jit.metainterp.history import AbstractDescr, BoxInt, BoxPtr, BoxObj
+from pypy.jit.metainterp import history
 from pypy.jit.metainterp.specnode import NotSpecNode
 from pypy.rlib.debug import debug_print
 
@@ -58,7 +59,7 @@
     else:
         if target_loop is not None:
             show_loop(metainterp, target_loop)
-    if target_loop is not None and target_loop not in map_loop2descr:
+    if target_loop is not None and type(target_loop) is not TerminatingLoop:
         target_loop.check_consistency()
     return target_loop
 
@@ -71,7 +72,7 @@
                 errmsg += ': ' + str(error)
         else:
             errmsg = None
-        if loop is None or loop in map_loop2descr:
+        if loop is None or type(loop) is TerminatingLoop:
             extraloops = []
         else:
             extraloops = [loop]
@@ -122,50 +123,94 @@
 
 # ____________________________________________________________
 
-class DoneWithThisFrameDescr0(AbstractDescr):
+class DoneWithThisFrameDescrVoid(AbstractDescr):
     def handle_fail_op(self, metainterp_sd, fail_op):
-        raise metainterp_sd.DoneWithThisFrame(None)
+        assert metainterp_sd.result_type == history.VOID
+        raise metainterp_sd.DoneWithThisFrameVoid()
 
-class DoneWithThisFrameDescr1(AbstractDescr):
+class DoneWithThisFrameDescrInt(AbstractDescr):
     def handle_fail_op(self, metainterp_sd, fail_op):
+        assert metainterp_sd.result_type == history.INT
         resultbox = fail_op.args[0]
-        raise metainterp_sd.DoneWithThisFrame(resultbox)
+        if isinstance(resultbox, BoxInt):
+            result = metainterp_sd.cpu.get_latest_value_int(0)
+        else:
+            assert isinstance(resultbox, history.Const)
+            result = resultbox.getint()
+        raise metainterp_sd.DoneWithThisFrameInt(result)
+
+class DoneWithThisFrameDescrPtr(AbstractDescr):
+    def handle_fail_op(self, metainterp_sd, fail_op):
+        assert metainterp_sd.result_type == history.PTR
+        resultbox = fail_op.args[0]
+        if isinstance(resultbox, BoxPtr):
+            result = metainterp_sd.cpu.get_latest_value_ptr(0)
+        else:
+            assert isinstance(resultbox, history.Const)
+            result = resultbox.getptr_base()
+        raise metainterp_sd.DoneWithThisFramePtr(result)
+
+class DoneWithThisFrameDescrObj(AbstractDescr):
+    def handle_fail_op(self, metainterp_sd, fail_op):
+        assert metainterp_sd.result_type == history.OBJ
+        resultbox = fail_op.args[0]
+        if isinstance(resultbox, BoxObj):
+            result = metainterp_sd.cpu.get_latest_value_obj(0)
+        else:
+            assert isinstance(resultbox, history.Const)
+            result = resultbox.getobj()
+        raise metainterp_sd.DoneWithThisFrameObj(result)
 
 class ExitFrameWithExceptionDescr(AbstractDescr):
     def handle_fail_op(self, metainterp_sd, fail_op):
         assert len(fail_op.args) == 1
         valuebox = fail_op.args[0]
-        raise metainterp_sd.ExitFrameWithException(valuebox)
-
-done_with_this_frame_descr_0 = DoneWithThisFrameDescr0()
-done_with_this_frame_descr_1 = DoneWithThisFrameDescr1()
+        if isinstance(valuebox, BoxPtr):
+            value = metainterp_sd.cpu.get_latest_value_ptr(0)
+        else:
+            assert isinstance(valuebox, history.Const)
+            value = valuebox.getptr_base()
+        raise metainterp_sd.ExitFrameWithException(value)
+
+done_with_this_frame_descr_void = DoneWithThisFrameDescrVoid()
+done_with_this_frame_descr_int = DoneWithThisFrameDescrInt()
+done_with_this_frame_descr_ptr = DoneWithThisFrameDescrPtr()
+done_with_this_frame_descr_obj = DoneWithThisFrameDescrObj()
 exit_frame_with_exception_descr = ExitFrameWithExceptionDescr()
-map_loop2descr = {}
+
+class TerminatingLoop(TreeLoop):
+    pass
 
 # pseudo-loops to make the life of optimize.py easier
-_loop = TreeLoop('done_with_this_frame_int')
+_loop = TerminatingLoop('done_with_this_frame_int')
 _loop.specnodes = [NotSpecNode()]
 _loop.inputargs = [BoxInt()]
+_loop.finishdescr = done_with_this_frame_descr_int
 loops_done_with_this_frame_int = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_1
 
-_loop = TreeLoop('done_with_this_frame_ptr')
+_loop = TerminatingLoop('done_with_this_frame_ptr')
 _loop.specnodes = [NotSpecNode()]
 _loop.inputargs = [BoxPtr()]
+_loop.finishdescr = done_with_this_frame_descr_ptr
 loops_done_with_this_frame_ptr = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_1
 
-_loop = TreeLoop('done_with_this_frame_void')
+_loop = TerminatingLoop('done_with_this_frame_obj')
+_loop.specnodes = [NotSpecNode()]
+_loop.inputargs = [BoxObj()]
+_loop.finishdescr = done_with_this_frame_descr_obj
+loops_done_with_this_frame_obj = [_loop]
+
+_loop = TerminatingLoop('done_with_this_frame_void')
 _loop.specnodes = []
 _loop.inputargs = []
+_loop.finishdescr = done_with_this_frame_descr_void
 loops_done_with_this_frame_void = [_loop]
-map_loop2descr[_loop] = done_with_this_frame_descr_0
 
-_loop = TreeLoop('exit_frame_with_exception')
+_loop = TerminatingLoop('exit_frame_with_exception')
 _loop.specnodes = [NotSpecNode()]
 _loop.inputargs = [BoxPtr()]
+_loop.finishdescr = exit_frame_with_exception_descr
 loops_exit_frame_with_exception = [_loop]
-map_loop2descr[_loop] = exit_frame_with_exception_descr
 del _loop
 
 
@@ -181,7 +226,49 @@
     def handle_fail_op(self, metainterp_sd, fail_op):
         from pypy.jit.metainterp.pyjitpl import MetaInterp
         metainterp = MetaInterp(metainterp_sd)
-        return metainterp.handle_guard_failure(fail_op, self)
+        patch = self.patch_boxes_temporarily(metainterp_sd, fail_op)
+        try:
+            return metainterp.handle_guard_failure(fail_op, self)
+        finally:
+            self.restore_patched_boxes(metainterp_sd, fail_op, patch)
+
+    def patch_boxes_temporarily(self, metainterp_sd, fail_op):
+        # A bit indirect: when we hit a rop.FAIL, the current values are
+        # stored somewhere in the CPU backend.  Below we fetch them and
+        # copy them into the real boxes, i.e. the 'fail_op.args'.  We
+        # are in a try:finally path at the end of which, in
+        # restore_patched_boxes(), we can safely undo exactly the
+        # changes done here.
+        cpu = metainterp_sd.cpu
+        patch = []
+        for i in range(len(fail_op.args)):
+            box = fail_op.args[i]
+            patch.append(box.clonebox())
+            if isinstance(box, BoxInt):
+                srcvalue = cpu.get_latest_value_int(i)
+                box.changevalue_int(srcvalue)
+            elif isinstance(box, BoxPtr):
+                srcvalue = cpu.get_latest_value_ptr(i)
+                box.changevalue_ptr(srcvalue)
+            elif cpu.is_oo and isinstance(box, BoxObj):
+                srcvalue = cpu.get_latest_value_obj(i)
+                box.changevalue_obj(srcvalue)
+            else:
+                assert False
+        return patch
+
+    def restore_patched_boxes(self, metainterp_sd, fail_op, patch):
+        for i in range(len(patch)-1, -1, -1):
+            srcbox = patch[i]
+            dstbox = fail_op.args[i]
+            if isinstance(srcbox, BoxInt):
+                srcbox.changevalue_int(dstbox.getint())
+            elif isinstance(srcbox, BoxPtr):
+                srcbox.changevalue_ptr(dstbox.getptr_base())
+            elif metainterp_sd.cpu.is_oo and isinstance(srcbox, BoxObj):
+                srcbox.changevalue_obj(dstbox.getobj())
+            else:
+                assert False
 
     def get_guard_op(self):
         guard_op = self.history.operations[self.history_guard_index]
@@ -270,13 +357,13 @@
 
 def prepare_last_operation(new_loop, target_loop):
     op = new_loop.operations[-1]
-    if target_loop not in map_loop2descr:
+    if not isinstance(target_loop, TerminatingLoop):
         # normal case
         op.jump_target = target_loop
     else:
-        # The target_loop is a pseudo-loop done_with_this_frame.  Replace
-        # the operation with the real operation we want, i.e. a FAIL.
-        descr = map_loop2descr[target_loop]
+        # The target_loop is a pseudo-loop, e.g. done_with_this_frame.
+        # Replace the operation with the real operation we want, i.e. a FAIL.
+        descr = target_loop.finishdescr
         new_op = ResOperation(rop.FAIL, op.args, None, descr=descr)
         new_loop.operations[-1] = new_op
 

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/history.py	Sun Apr 26 16:35:53 2009
@@ -16,6 +16,7 @@
 
 # ____________________________________________________________
 
+VOID = 'v'
 INT = 'i'
 PTR = 'p'
 OBJ = 'o'
@@ -295,11 +296,11 @@
     def get_(self):
         return ootype.ooidentityhash(self.value) # XXX: check me
 
-    def getaddr(self, cpu):
-        # so far this is used only when calling
-        # CodeWriter.IndirectCallset.bytecode_for_address.  We don't need a
-        # real addr, but just a key for the dictionary
-        return self.value
+##    def getaddr(self, cpu):
+##        # so far this is used only when calling
+##        # CodeWriter.IndirectCallset.bytecode_for_address.  We don't need a
+##        # real addr, but just a key for the dictionary
+##        return self.value
 
     def equals(self, other):
         return self.value == other.getobj()

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py	Sun Apr 26 16:35:53 2009
@@ -529,7 +529,11 @@
     def opimpl_indirect_call(self, pc, indirectcallset, box, varargs):
         box = self.implement_guard_value(pc, box)
         cpu = self.metainterp.cpu
-        jitcode = indirectcallset.bytecode_for_address(box.getaddr(cpu))
+        if cpu.is_oo:
+            key = box.getobj()
+        else:
+            key = box.getaddr(cpu)
+        jitcode = indirectcallset.bytecode_for_address(key)
         f = self.metainterp.newframe(jitcode)
         f.setup_call(varargs)
         return True
@@ -806,6 +810,19 @@
         self.options = options
         self.globaldata = MetaInterpGlobalData()
 
+        RESULT = portal_graph.getreturnvar().concretetype
+        kind = history.getkind(RESULT)
+        if kind == 'void':
+            self.result_type = history.VOID
+        elif kind == 'int':
+            self.result_type = history.INT
+        elif kind == 'ptr':
+            self.result_type = history.PTR
+        elif kind == 'obj':
+            self.result_type = history.OBJ
+        else:
+            assert False
+
         self.opcode_implementations = []
         self.opcode_names = []
         self.opname_to_index = {}
@@ -868,28 +885,10 @@
 
 class MetaInterpGlobalData(object):
     def __init__(self):
-        self.metainterp_doing_call = None
         self._debug_history = []
         self.compiled_merge_points = r_dict(history.mp_eq, history.mp_hash)
                  # { greenkey: list-of-MergePoints }
 
-    def set_metainterp_doing_call(self, metainterp):
-        self.save_recursive_call()
-        self.metainterp_doing_call = metainterp
-
-    def unset_metainterp_doing_call(self, metainterp):
-        if self.metainterp_doing_call != metainterp:
-            metainterp._restore_recursive_call()
-        self.metainterp_doing_call = None
-
-    def save_recursive_call(self):
-        if self.metainterp_doing_call is not None:
-            self.metainterp_doing_call._save_recursive_call()
-            self.metainterp_doing_call = None
-
-    def assert_empty(self):
-        assert self.metainterp_doing_call is None
-
 # ____________________________________________________________
 
 class MetaInterp(object):
@@ -917,7 +916,18 @@
         else:
             if not isinstance(self.history, history.BlackHole):
                 self.compile_done_with_this_frame(resultbox)
-            raise self.staticdata.DoneWithThisFrame(resultbox)
+            sd = self.staticdata
+            if sd.result_type == history.VOID:
+                assert resultbox is None
+                raise sd.DoneWithThisFrameVoid
+            elif sd.result_type == history.INT:
+                raise sd.DoneWithThisFrameInt(resultbox.getint())
+            elif sd.result_type == history.PTR:
+                raise sd.DoneWithThisFramePtr(resultbox.getptr_base())
+            elif self.cpu.is_oo and sd.result_type == history.OBJ:
+                raise sd.DoneWithThisFrameObj(resultbox.getobj())
+            else:
+                assert False
 
     def finishframe_exception(self, exceptionbox, excvaluebox):
         if we_are_translated():   # detect and propagate AssertionErrors early
@@ -939,7 +949,7 @@
             self.framestack.pop()
         if not isinstance(self.history, history.BlackHole):
             self.compile_exit_frame_with_exception(excvaluebox)
-        raise self.staticdata.ExitFrameWithException(excvaluebox)
+        raise self.staticdata.ExitFrameWithException(excvaluebox.getptr_base())
 
     def create_empty_history(self):
         self.history = history.History(self.cpu)
@@ -954,9 +964,6 @@
 
     @specialize.arg(1)
     def execute_and_record(self, opnum, argboxes, descr=None):
-        # detect recursions when using rop.CALL
-        if opnum == rop.CALL:
-            self.staticdata.globaldata.set_metainterp_doing_call(self)
         # execute the operation first
         history.check_descr(descr)
         resbox = executor.execute(self.cpu, opnum, argboxes, descr)
@@ -972,82 +979,11 @@
                 resbox = resbox.nonconstbox()    # ensure it is a Box
         else:
             assert resbox is None or isinstance(resbox, Box)
-            if opnum == rop.CALL:
-                self.staticdata.globaldata.unset_metainterp_doing_call(self)
         # record the operation if not constant-folded away
         if not canfold:
             self.history.record(opnum, argboxes, resbox, descr)
         return resbox
 
-    def _save_recursive_call(self):
-        # A bit of a hack: we need to be safe against box.changevalue_xxx()
-        # called by cpu.execute_operations(), in case we are recursively
-        # in another MetaInterp.  Temporarily save away the content of the
-        # boxes.
-        log('recursive call to execute_operations()!')
-        saved_env = []
-        framestack = []
-        for f in self.framestack:
-            newenv = []
-            #
-            box = f.exception_box
-            if isinstance(box, Box):
-                saved_env.append(box.clonebox())
-            box = f.exc_value_box
-            if isinstance(box, Box):
-                saved_env.append(box.clonebox())
-            #
-            for box in f.env:
-                if isinstance(box, Box):
-                    saved_env.append(box.clonebox())
-                newenv.append(box)
-            framestack.append(newenv)
-        pseudoframe = instantiate(MIFrame)
-        pseudoframe.env = saved_env
-        pseudoframe._saved_framestack = framestack
-        self.framestack.append(pseudoframe)
-
-    def _restore_recursive_call(self):
-        log('recursion detected, restoring state')
-        if not we_are_translated():
-            assert not hasattr(self.framestack[-1], 'jitcode')
-            assert hasattr(self.framestack[-2], 'jitcode')
-        pseudoframe = self.framestack.pop()
-        saved_env = pseudoframe.env
-        i = 0
-        assert len(pseudoframe._saved_framestack) == len(self.framestack)
-        for j in range(len(self.framestack)):
-            f = self.framestack[j]
-            #
-            box = f.exception_box
-            if isinstance(box, BoxInt):
-                box.changevalue_int(saved_env[i].getint())
-                i += 1
-            box = f.exc_value_box
-            if isinstance(box, BoxPtr):
-                box.changevalue_ptr(saved_env[i].getptr_base())
-                i += 1
-            #
-            pseudoenv = pseudoframe._saved_framestack[j]
-            assert len(f.env) == len(pseudoenv)
-            for k in range(len(f.env)):
-                box = f.env[k]
-                if isinstance(box, BoxInt):
-                    assert isinstance(pseudoenv[k], BoxInt)
-                    box.changevalue_int(saved_env[i].getint())
-                    i += 1
-                elif isinstance(box, BoxPtr):
-                    assert isinstance(pseudoenv[k], BoxPtr)
-                    box.changevalue_ptr(saved_env[i].getptr_base())
-                    i += 1
-                else:
-                    if isinstance(box, ConstInt):
-                        assert box.getint() == pseudoenv[k].getint()
-                    elif isinstance(box, ConstPtr):
-                        assert box.getptr_base() == pseudoenv[k].getptr_base()
-                    assert isinstance(box, Const)
-        assert i == len(saved_env)
-
     def _interpret(self):
         # Execute the frames forward until we raise a DoneWithThisFrame,
         # a ContinueRunningNormally, or a GenerateMergePoint exception.
@@ -1204,15 +1140,22 @@
 
     def compile_done_with_this_frame(self, exitbox):
         # temporarily put a JUMP to a pseudo-loop
-        if exitbox is not None:
-            exits = [exitbox]
-            if isinstance(exitbox, BoxInt) or isinstance(exitbox, ConstInt):
-                loops = compile.loops_done_with_this_frame_int
-            else:
-                loops = compile.loops_done_with_this_frame_ptr
-        else:
+        sd = self.staticdata
+        if sd.result_type == history.VOID:
+            assert exitbox is None
             exits = []
             loops = compile.loops_done_with_this_frame_void
+        elif sd.result_type == history.INT:
+            exits = [exitbox]
+            loops = compile.loops_done_with_this_frame_int
+        elif sd.result_type == history.PTR:
+            exits = [exitbox]
+            loops = compile.loops_done_with_this_frame_ptr
+        elif sd.cpu.is_oo and sd.result_type == history.OBJ:
+            exits = [exitbox]
+            loops = compile.loops_done_with_this_frame_obj
+        else:
+            assert False
         self.history.record(rop.JUMP, exits, None)
         target_loop = compile.compile_new_bridge(self, loops, self.resumekey)
         assert target_loop is loops[0]

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_basic.py	Sun Apr 26 16:35:53 2009
@@ -77,14 +77,16 @@
             cw.make_one_bytecode(graph_key, False, called_from)
         metainterp.staticdata.portal_code = maingraph
         metainterp.staticdata.state = FakeWarmRunnerDesc()
-        metainterp.staticdata.DoneWithThisFrame = DoneWithThisFrame
+        metainterp.staticdata.DoneWithThisFrameInt = DoneWithThisFrame
+        metainterp.staticdata.DoneWithThisFramePtr = DoneWithThisFrame
+        metainterp.staticdata.DoneWithThisFrameObj = DoneWithThisFrame
         self.metainterp = metainterp
         try:
             metainterp.compile_and_run_once(*args)
         except DoneWithThisFrame, e:
             #if conftest.option.view:
             #    metainterp.stats.view()
-            return e.args[0].value
+            return e.args[0]
         else:
             raise Exception("FAILED")
 

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py	Sun Apr 26 16:35:53 2009
@@ -270,9 +270,9 @@
         #               except ContinueRunningNormally, e:
         #                   *args = *e.new_args
         #               except DoneWithThisFrame, e:
-        #                   return e.result
+        #                   return e.return
         #               except ExitFrameWithException, e:
-        #                   raise e.type, e.value
+        #                   raise Exception, e.value
         #
         #       def portal(*args):
         #           while 1:
@@ -288,17 +288,37 @@
         portal_ptr = self.ts.functionptr(PORTALFUNC, 'portal',
                                          graph = portalgraph)
 
-        class DoneWithThisFrame(JitException):
-            def __init__(self, resultbox):
-                self.resultbox = resultbox
+        class DoneWithThisFrameVoid(JitException):
             def __str__(self):
-                return 'DoneWithThisFrame(%s)' % (self.resultbox,)
+                return 'DoneWithThisFrameVoid()'
+
+        class DoneWithThisFrameInt(JitException):
+            def __init__(self, result):
+                assert lltype.typeOf(result) is lltype.Signed
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFrameInt(%s)' % (self.result,)
+
+        class DoneWithThisFramePtr(JitException):
+            def __init__(self, result):
+                assert lltype.typeOf(result) == llmemory.GCREF
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFramePtr(%s)' % (self.result,)
+
+        class DoneWithThisFrameObj(JitException):
+            def __init__(self, result):
+                assert ootype.typeOf(result) == ootype.Object
+                self.result = result
+            def __str__(self):
+                return 'DoneWithThisFrameObj(%s)' % (self.result,)
 
         class ExitFrameWithException(JitException):
-            def __init__(self, valuebox):
-                self.valuebox = valuebox
+            def __init__(self, value):
+                assert lltype.typeOf(value) == llmemory.GCREF
+                self.value = value
             def __str__(self):
-                return 'ExitFrameWithException(%s)' % (self.valuebox,)
+                return 'ExitFrameWithException(%s)' % (self.value,)
 
         class ContinueRunningNormally(JitException):
             def __init__(self, args):
@@ -308,15 +328,22 @@
                 return 'ContinueRunningNormally(%s)' % (
                     ', '.join(map(str, self.args)),)
 
-        self.DoneWithThisFrame = DoneWithThisFrame
+        self.DoneWithThisFrameVoid = DoneWithThisFrameVoid
+        self.DoneWithThisFrameInt = DoneWithThisFrameInt
+        self.DoneWithThisFramePtr = DoneWithThisFramePtr
+        self.DoneWithThisFrameObj = DoneWithThisFrameObj
         self.ExitFrameWithException = ExitFrameWithException
         self.ContinueRunningNormally = ContinueRunningNormally
-        self.metainterp_sd.DoneWithThisFrame = DoneWithThisFrame
+        self.metainterp_sd.DoneWithThisFrameVoid = DoneWithThisFrameVoid
+        self.metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrameInt
+        self.metainterp_sd.DoneWithThisFramePtr = DoneWithThisFramePtr
+        self.metainterp_sd.DoneWithThisFrameObj = DoneWithThisFrameObj
         self.metainterp_sd.ExitFrameWithException = ExitFrameWithException
         self.metainterp_sd.ContinueRunningNormally = ContinueRunningNormally
         rtyper = self.translator.rtyper
         portalfunc_ARGS = unrolling_iterable(list(enumerate(PORTALFUNC.ARGS)))
         RESULT = PORTALFUNC.RESULT
+        result_kind = history.getkind(RESULT)
 
         def ll_portal_runner(*args):
             while 1:
@@ -328,10 +355,21 @@
                     for i, ARG in portalfunc_ARGS:
                         v = unwrap(ARG, e.args[i])
                         args = args + (v,)
-                except DoneWithThisFrame, e:
-                    return unwrap(RESULT, e.resultbox)
+                except DoneWithThisFrameVoid:
+                    assert result_kind == 'void'
+                    return
+                except DoneWithThisFrameInt, e:
+                    assert result_kind == 'int'
+                    return lltype.cast_primitive(RESULT, e.result)
+                except DoneWithThisFramePtr, e:
+                    assert result_kind == 'ptr'
+                    return lltype.cast_opaque_ptr(RESULT, e.result)
+                except DoneWithThisFrameObj, e:
+                    assert result_kind == 'obj'
+                    return ootype.cast_from_object(RESULT, e.result)
                 except ExitFrameWithException, e:
-                    value = e.valuebox.getptr(lltype.Ptr(rclass.OBJECT))
+                    value = lltype.cast_opaque_ptr(lltype.Ptr(rclass.OBJECT),
+                                                   e.value)
                     if not we_are_translated():
                         raise LLException(value.typeptr, value)
                     else:
@@ -512,10 +550,8 @@
                     loop = cell.bridge
                     boxes = cell.fill_boxes(*args[num_green_args:])
             # ---------- execute assembler ----------
-            warmrunnerdesc.metainterp_sd.globaldata.save_recursive_call()
             while True:     # until interrupted by an exception
                 metainterp_sd = warmrunnerdesc.metainterp_sd
-                metainterp_sd.globaldata.assert_empty()
                 fail_op = metainterp_sd.cpu.execute_operations(loop, boxes)
                 loop, boxes = fail_op.descr.handle_fail_op(metainterp_sd,
                                                            fail_op)



More information about the Pypy-commit mailing list