[pypy-commit] pypy continulet-jit-3: (fijal, arigo)

arigo noreply at buildbot.pypy.org
Sat Oct 13 18:44:31 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: continulet-jit-3
Changeset: r58105:716a9d2d6183
Date: 2012-10-13 18:44 +0200
http://bitbucket.org/pypy/pypy/changeset/716a9d2d6183/

Log:	(fijal, arigo)

	Start serious fixing and refactoring in the frontend.

diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -18,7 +18,6 @@
 
 from pypy.jit.metainterp import resoperation
 from pypy.jit.metainterp.resoperation import rop
-from pypy.jit.metainterp.jitframe import JITFRAMEPTR
 from pypy.jit.backend.llgraph import symbolic
 from pypy.jit.codewriter import longlong
 from pypy.jit.codewriter.effectinfo import EffectInfo
@@ -481,7 +480,6 @@
 
 class Frame(object):
     OPHANDLERS = [None] * (rop._LAST+1)
-    _TYPE = JITFRAMEPTR.TO
 
     def __init__(self, cpu):
         self.verbose = False
@@ -517,6 +515,7 @@
         """Execute all operations in a loop,
         possibly following to other loops as well.
         """
+        assert self._may_force == -1
         assert self._last_exception is None, "exception left behind"
         verbose = True
         self.opindex = 0
@@ -578,7 +577,11 @@
                 if self.verbose:
                     log.trace('finished: %s' % (
                         ', '.join(map(str, args)),))
-                self.fail_args = args
+                assert len(op.args) <= 1, "FINISH with more than 1 arg"
+                self.finish_args = op.args
+                self.fail_args = op.fail_args
+                self.fail_index = op.fail_index
+                self._may_force = self.opindex
                 return
 
             else:
@@ -1066,16 +1069,15 @@
             #
             # Emulate the fast path
             failindex = frame_descr_index(subframe)
-            realsubframe = lltype.cast_opaque_ptr(JITFRAMEPTR, subframe)
             if failindex == self.cpu.done_with_this_frame_int_v:
                 reset_vable(jd, vable)
-                return self.cpu.get_latest_value_int(realsubframe, 0)
+                return self.cpu.get_latest_value_int(subframe, 0)
             if failindex == self.cpu.done_with_this_frame_ref_v:
                 reset_vable(jd, vable)
-                return self.cpu.get_latest_value_ref(realsubframe, 0)
+                return self.cpu.get_latest_value_ref(subframe, 0)
             if failindex == self.cpu.done_with_this_frame_float_v:
                 reset_vable(jd, vable)
-                return self.cpu.get_latest_value_float(realsubframe, 0)
+                return self.cpu.get_latest_value_float(subframe, 0)
             if failindex == self.cpu.done_with_this_frame_void_v:
                 reset_vable(jd, vable)
                 return None
@@ -1083,7 +1085,7 @@
             assembler_helper_ptr = jd.assembler_helper_adr.ptr  # fish
             assembler_helper = assembler_helper_ptr._obj._callable
             try:
-                return assembler_helper(realsubframe, vable)
+                return assembler_helper(subframe, vable)
             except LLException, lle:
                 assert self._last_exception is None, "exception left behind"
                 self._last_exception = lle
@@ -1320,7 +1322,6 @@
             import sys, pdb
             pdb.post_mortem(sys.exc_info()[2])
         raise
-    del frame.env
     return result
 
 def frame_descr_index(frame):
@@ -1392,10 +1393,13 @@
     frame._forced = True
     assert frame._may_force >= 0
     call_op = frame.loop.operations[frame._may_force]
-    guard_op = frame.loop.operations[frame._may_force+1]
     opnum = call_op.opnum
-    assert opnum == rop.CALL_MAY_FORCE or opnum == rop.CALL_ASSEMBLER
-    frame._populate_fail_args(guard_op, skip=call_op.result)
+    if opnum != rop.FINISH:
+        assert opnum == rop.CALL_MAY_FORCE or opnum == rop.CALL_ASSEMBLER
+        guard_op = frame.loop.operations[frame._may_force+1]
+        frame._populate_fail_args(guard_op, skip=call_op.result)
+    else:
+        frame._populate_fail_args(call_op)
     return frame.fail_index
 
 ##def cast_adr_to_int(memocast, adr):
@@ -1863,12 +1867,12 @@
 
 
 COMPILEDLOOP = lltype.Ptr(lltype.OpaqueType("CompiledLoop"))
-FRAME = JITFRAMEPTR
-#OOFRAME = lltype.Ptr(lltype.OpaqueType("OOFrame"))
+FRAME = lltype.Ptr(lltype.OpaqueType("Frame"))
+OOFRAME = lltype.Ptr(lltype.OpaqueType("OOFrame"))
 
 _TO_OPAQUE[CompiledLoop] = COMPILEDLOOP.TO
-#_TO_OPAQUE[Frame] = FRAME.TO
-#_TO_OPAQUE[OOFrame] = OOFRAME.TO
+_TO_OPAQUE[Frame] = FRAME.TO
+_TO_OPAQUE[OOFrame] = OOFRAME.TO
 
 s_CompiledLoop = annmodel.SomePtr(COMPILEDLOOP)
 s_Frame = annmodel.SomePtr(FRAME)
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -12,7 +12,6 @@
 from pypy.jit.metainterp.history import REF, INT, FLOAT, STRUCT
 from pypy.jit.metainterp.warmstate import unwrap
 from pypy.jit.metainterp.resoperation import rop
-from pypy.jit.metainterp.jitframe import JITFRAMEPTR
 from pypy.jit.backend import model
 from pypy.jit.backend.llgraph import llimpl, symbolic
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
@@ -216,7 +215,7 @@
                 else:
                     raise Exception("'%s' args contain: %r" % (op.getopname(),
                                                                x))
-            if op.is_guard():
+            if op.is_guard() or op.getopnum() == rop.FINISH:
                 faildescr = op.getdescr()
                 assert isinstance(faildescr, history.AbstractFailDescr)
                 faildescr._fail_args_types = []
@@ -252,9 +251,7 @@
             targettoken = op.getdescr()
             llimpl.compile_add_jump_target(c, targettoken, clt)
         elif op.getopnum() == rop.FINISH:
-            faildescr = op.getdescr()
-            index = self.get_fail_descr_number(faildescr)
-            llimpl.compile_add_fail(c, index)
+            pass
         else:
             assert False, "unknown operation"
 
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -153,11 +153,19 @@
         necessarily correct after a FINISH."""
         return len(jitframe.jf_gcvalues)
 
-    def grab_exc_value(self, jitframe):
-        """Return and clear the exception set by the latest execute_token(),
-        when it exits due to a failure of a GUARD_EXCEPTION or
-        GUARD_NO_EXCEPTION.  (Returns a GCREF)"""        # XXX remove me
-        return jitframe.jf_excvalue
+    def get_finish_value_int(self, jitframe):
+        """Return the result passed to FINISH, which was an int."""
+        return jitframe.jf_finish_int
+
+    def get_finish_value_float(self, jitframe):
+        """Return the result passed to FINISH, which was a FLOATSTORAGE."""
+        return jitframe.jf_finish_float
+
+    def get_finish_value_ref(self, jitframe):
+        """Return and clear the result passed to FINISH, which was a GCREF.
+        Also used when it exits due to a failure of a GUARD_EXCEPTION or
+        GUARD_NO_EXCEPTION, to return the exception."""
+        return jitframe.jf_finish_ref
 
     def redirect_call_assembler(self, oldlooptoken, newlooptoken):
         """Redirect oldlooptoken to newlooptoken.  More precisely, it is
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -1549,7 +1549,6 @@
 def resume_in_blackhole(metainterp_sd, jitdriver_sd, jitframe, resumedescr,
                         all_virtuals=None):
     from pypy.jit.metainterp.resume import blackhole_from_resumedata
-    #debug_start('jit-blackhole')
     blackholeinterp = blackhole_from_resumedata(
         metainterp_sd.blackholeinterpbuilder,
         jitdriver_sd,
@@ -1564,15 +1563,11 @@
     current_exc = blackholeinterp._prepare_resume_from_failure(
         resumedescr.guard_opnum, jitframe, dont_change_position)
 
-    #try:
     _run_forever(blackholeinterp, current_exc)
-    #finally:
-        #debug_stop('jit-blackhole')
 
 def convert_and_run_from_pyjitpl(metainterp, raising_exception=False):
     # Get a chain of blackhole interpreters and fill them by copying
     # 'metainterp.framestack'.
-    #debug_start('jit-blackhole')
     metainterp_sd = metainterp.staticdata
     nextbh = None
     for frame in metainterp.framestack:
@@ -1590,7 +1585,4 @@
         firstbh.exception_last_value = current_exc
         current_exc = lltype.nullptr(rclass.OBJECTPTR.TO)
     #
-    #try:
     _run_forever(firstbh, current_exc)
-    #finally:
-        #debug_stop('jit-blackhole')
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -411,71 +411,6 @@
 
 # ____________________________________________________________
 
-class _DoneWithThisFrameDescr(AbstractFailDescr):
-    pass
-
-class DoneWithThisFrameDescrVoid(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
-        assert jitdriver_sd.result_type == history.VOID
-        raise metainterp_sd.DoneWithThisFrameVoid()
-
-class DoneWithThisFrameDescrInt(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
-        assert jitdriver_sd.result_type == history.INT
-        result = metainterp_sd.cpu.get_latest_value_int(jitframe, 0)
-        raise metainterp_sd.DoneWithThisFrameInt(result)
-
-class DoneWithThisFrameDescrRef(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
-        assert jitdriver_sd.result_type == history.REF
-        cpu = metainterp_sd.cpu
-        result = cpu.get_latest_value_ref(jitframe, 0)
-        raise metainterp_sd.DoneWithThisFrameRef(cpu, result)
-
-class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
-        assert jitdriver_sd.result_type == history.FLOAT
-        result = metainterp_sd.cpu.get_latest_value_float(jitframe, 0)
-        raise metainterp_sd.DoneWithThisFrameFloat(result)
-
-class ExitFrameWithExceptionDescrRef(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
-        cpu = metainterp_sd.cpu
-        value = cpu.get_latest_value_ref(jitframe, 0)
-        raise metainterp_sd.ExitFrameWithExceptionRef(cpu, value)
-
-
-class TerminatingLoopToken(JitCellToken): # FIXME: kill?
-    terminating = True
-
-    def __init__(self, nargs, finishdescr):
-        self.finishdescr = finishdescr
-
-def make_done_loop_tokens():
-    done_with_this_frame_descr_void = DoneWithThisFrameDescrVoid()
-    done_with_this_frame_descr_int = DoneWithThisFrameDescrInt()
-    done_with_this_frame_descr_ref = DoneWithThisFrameDescrRef()
-    done_with_this_frame_descr_float = DoneWithThisFrameDescrFloat()
-    exit_frame_with_exception_descr_ref = ExitFrameWithExceptionDescrRef()
-
-    # pseudo loop tokens to make the life of optimize.py easier
-    return {'loop_tokens_done_with_this_frame_int': [
-                TerminatingLoopToken(1, done_with_this_frame_descr_int)
-                ],
-            'loop_tokens_done_with_this_frame_ref': [
-                TerminatingLoopToken(1, done_with_this_frame_descr_ref)
-                ],
-            'loop_tokens_done_with_this_frame_float': [
-                TerminatingLoopToken(1, done_with_this_frame_descr_float)
-                ],
-            'loop_tokens_done_with_this_frame_void': [
-                TerminatingLoopToken(0, done_with_this_frame_descr_void)
-                ],
-            'loop_tokens_exit_frame_with_exception_ref': [
-                TerminatingLoopToken(1, exit_frame_with_exception_descr_ref)
-                ],
-            }
-
 class ResumeDescr(AbstractFailDescr):
     pass
 
@@ -698,7 +633,8 @@
         # future failure of the GUARD_NOT_FORCED
         self.save_data(jitframe, all_virtuals)
 
-    def save_data(self, key, value):
+    def save_data(self, jitframe, value):
+        return   # XXXXX
         globaldata = self.metainterp_sd.globaldata
         if we_are_translated():
             assert key not in globaldata.resume_virtuals
@@ -710,6 +646,7 @@
             rv.append((key, value))
 
     def fetch_data(self, key):
+        XXXXX
         globaldata = self.metainterp_sd.globaldata
         if we_are_translated():
             assert key in globaldata.resume_virtuals
@@ -727,8 +664,7 @@
         return data
 
     def _clone_if_mutable(self):
-        res = ResumeGuardForcedDescr(self.metainterp_sd,
-                                     self.jitdriver_sd)
+        res = self.__class__(self.metainterp_sd, self.jitdriver_sd)
         self.copy_all_attributes_into(res)
         return res
 
@@ -815,6 +751,46 @@
         metainterp_sd.stats.add_jitcell_token(jitcell_token)
 
 
+_DoneWithThisFrameDescr = ResumeGuardForcedDescr    # XXX replace me
+
+class DoneWithThisFrameDescrVoid(_DoneWithThisFrameDescr):
+    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
+        assert jitdriver_sd is self.jitdriver_sd
+        assert jitdriver_sd.result_type == history.VOID
+        raise metainterp_sd.DoneWithThisFrameVoid()
+
+class DoneWithThisFrameDescrInt(_DoneWithThisFrameDescr):
+    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
+        assert jitdriver_sd is self.jitdriver_sd
+        assert jitdriver_sd.result_type == history.INT
+        result = metainterp_sd.cpu.get_finish_value_int(jitframe)
+        raise metainterp_sd.DoneWithThisFrameInt(result)
+
+class DoneWithThisFrameDescrRef(_DoneWithThisFrameDescr):
+    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
+        assert jitdriver_sd is self.jitdriver_sd
+        assert jitdriver_sd.result_type == history.REF
+        cpu = metainterp_sd.cpu
+        result = cpu.get_finish_value_ref(jitframe)
+        raise metainterp_sd.DoneWithThisFrameRef(cpu, result)
+
+class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr):
+    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
+        assert jitdriver_sd is self.jitdriver_sd
+        assert jitdriver_sd.result_type == history.FLOAT
+        result = metainterp_sd.cpu.get_finish_value_float(jitframe)
+        raise metainterp_sd.DoneWithThisFrameFloat(result)
+
+class ExitFrameWithExceptionDescrRef(_DoneWithThisFrameDescr):
+    def handle_fail(self, metainterp_sd, jitdriver_sd, jitframe):
+        assert jitdriver_sd is self.jitdriver_sd
+        cpu = metainterp_sd.cpu
+        value = cpu.get_finish_value_ref(jitframe)
+        raise metainterp_sd.ExitFrameWithExceptionRef(cpu, value)
+
+# ____________________________________________________________
+
+
 def compile_trace(metainterp, resumekey, resume_at_jump_descr=None):
     """Try to compile a new bridge leading from the beginning of the history
     to some existing place.
@@ -874,6 +850,7 @@
     calls back the interpreter.  Used temporarily: a fully compiled
     version of the code may end up replacing it.
     """
+    XXXX # fix me
     jitcell_token = make_jitcell_token(jitdriver_sd)
     nb_red_args = jitdriver_sd.num_red_args
     assert len(redargtypes) == nb_red_args
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -654,7 +654,6 @@
     target_tokens = None
     failed_states = None
     retraced_count = 0
-    terminating = False # see TerminatingLoopToken in compile.py
     invalidated = False
     outermost_jitdriver_sd = None
     # and more data specified by the backend when the loop is compiled
@@ -784,7 +783,7 @@
                 box = op.getarg(i)
                 if isinstance(box, Box):
                     assert box in seen
-            if op.is_guard():
+            if op.is_guard() or op.getopnum() == rop.FINISH:
                 assert op.getdescr() is not None
                 if hasattr(op.getdescr(), '_debug_suboperations'):
                     ops = op.getdescr()._debug_suboperations
diff --git a/pypy/jit/metainterp/jitdriver.py b/pypy/jit/metainterp/jitdriver.py
--- a/pypy/jit/metainterp/jitdriver.py
+++ b/pypy/jit/metainterp/jitdriver.py
@@ -18,7 +18,6 @@
     #    self.warmstate         ... pypy.jit.metainterp.warmspot
     #    self.handle_jitexc_from_bh pypy.jit.metainterp.warmspot
     #    self.no_loop_header    ... pypy.jit.metainterp.warmspot
-    #    self.portal_finishtoken... pypy.jit.metainterp.pyjitpl
     #    self.index             ... pypy.jit.codewriter.call
     #    self.mainjitcode       ... pypy.jit.codewriter.call
 
diff --git a/pypy/jit/metainterp/jitframe.py b/pypy/jit/metainterp/jitframe.py
--- a/pypy/jit/metainterp/jitframe.py
+++ b/pypy/jit/metainterp/jitframe.py
@@ -1,16 +1,6 @@
-from pypy.rpython.lltypesystem import lltype, llmemory, rffi
-from pypy.rpython.annlowlevel import llhelper
+from pypy.rpython.lltypesystem import lltype, llmemory
 
 
-_LONGLONGARRAY = lltype.GcArray(lltype.SignedLongLong)
-
-JITFRAME = lltype.GcStruct('JITFRAME',
-               ('jf_descr', llmemory.GCREF),
-               ('jf_excvalue', llmemory.GCREF),
-               ('jf_nongcvalues', lltype.Ptr(_LONGLONGARRAY)),
-               ('jf_gcvalues', lltype.Array(llmemory.GCREF)))
-JITFRAMEPTR = lltype.Ptr(JITFRAME)
-
 # Constants used for the 'jit_frame' field of virtualizables/virtualrefs:
 #
 #   1. TOKEN_NONE means not in the JIT at all, except as described below.
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -546,6 +546,8 @@
                 op = self.store_final_boxes_in_guard(op)
         elif op.can_raise():
             self.exception_might_have_happened = True
+        elif op.getopnum() == rop.FINISH:
+            op = self.store_final_boxes_in_guard(op)
         if op.result:
             if op.result in self.seen_results:
                 raise ValueError, "invalid optimization"
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1459,8 +1459,6 @@
         self._addr2name_keys = []
         self._addr2name_values = []
 
-        self.__dict__.update(compile.make_done_loop_tokens())
-
     def _freeze_(self):
         return True
 
@@ -1500,18 +1498,6 @@
         self.callinfocollection = codewriter.callcontrol.callinfocollection
         self.has_libffi_call = codewriter.callcontrol.has_libffi_call
         #
-        # store this information for fastpath of call_assembler
-        # (only the paths that can actually be taken)
-        for jd in self.jitdrivers_sd:
-            name = {history.INT: 'int',
-                    history.REF: 'ref',
-                    history.FLOAT: 'float',
-                    history.VOID: 'void'}[jd.result_type]
-            tokens = getattr(self, 'loop_tokens_done_with_this_frame_%s' % name)
-            jd.portal_finishtoken = tokens[0].finishdescr
-            num = self.cpu.get_fail_descr_number(tokens[0].finishdescr)
-            setattr(self.cpu, 'done_with_this_frame_%s_v' % name, num)
-        #
         exc_descr = compile.PropagateExceptionDescr()
         num = self.cpu.get_fail_descr_number(exc_descr)
         self.cpu.propagate_exception_v = num
@@ -1598,8 +1584,6 @@
         self.indirectcall_dict = None
         self.addr2name = None
         self.loopnumbering = 0
-        self.resume_virtuals = {}
-        self.resume_virtuals_not_translated = []
 
 # ____________________________________________________________
 
@@ -2204,40 +2188,34 @@
             self.raise_continue_running_normally(live_arg_boxes, jitcell_token)
 
     def compile_done_with_this_frame(self, exitbox):
-        self.gen_store_back_in_virtualizable()
-        # temporarily put a JUMP to a pseudo-loop
-        sd = self.staticdata
         result_type = self.jitdriver_sd.result_type
         if result_type == history.VOID:
             assert exitbox is None
-            exits = []
-            loop_tokens = sd.loop_tokens_done_with_this_frame_void
+            self.compile_done([], compile.DoneWithThisFrameDescrVoid)
         elif result_type == history.INT:
-            exits = [exitbox]
-            loop_tokens = sd.loop_tokens_done_with_this_frame_int
+            self.compile_done([exitbox], compile.DoneWithThisFrameDescrInt)
         elif result_type == history.REF:
-            exits = [exitbox]
-            loop_tokens = sd.loop_tokens_done_with_this_frame_ref
+            self.compile_done([exitbox], compile.DoneWithThisFrameDescrRef)
         elif result_type == history.FLOAT:
-            exits = [exitbox]
-            loop_tokens = sd.loop_tokens_done_with_this_frame_float
+            self.compile_done([exitbox], compile.DoneWithThisFrameDescrFloat)
         else:
             assert False
-        # FIXME: kill TerminatingLoopToken?
-        # FIXME: can we call compile_trace?
-        token = loop_tokens[0].finishdescr
+
+    def compile_exit_frame_with_exception(self, valuebox):
+        self.compile_done([valuebox], compile.ExitFrameWithExceptionDescrRef)
+
+    def compile_done(self, exits, DoneCls):
+        self.record_set_jit_frame()
+        virtualizable_boxes = None
+        if (self.jitdriver_sd.virtualizable_info is not None or
+            self.jitdriver_sd.greenfield_info is not None):
+            virtualizable_boxes = self.virtualizable_boxes
+        assert len(self.virtualref_boxes) == 0
+        token = DoneCls(self.staticdata, self.jitdriver_sd)
+        resume.capture_resumedata([], virtualizable_boxes, [], token)
         self.history.record(rop.FINISH, exits, None, descr=token)
         target_token = compile.compile_trace(self, self.resumekey)
-        if target_token is not token:
-            compile.giveup()
-
-    def compile_exit_frame_with_exception(self, valuebox):
-        self.gen_store_back_in_virtualizable()
-        sd = self.staticdata
-        token = sd.loop_tokens_exit_frame_with_exception_ref[0].finishdescr
-        self.history.record(rop.FINISH, [valuebox], None, descr=token)
-        target_token = compile.compile_trace(self, self.resumekey)
-        if target_token is not token:
+        if target_token is None:
             compile.giveup()
 
     @specialize.arg(1)
@@ -2325,7 +2303,12 @@
             virtualizable_box = self.virtualizable_boxes[-1]
             virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
             vinfo.tracing_before_residual_call(virtualizable)
-            #
+            self.record_set_jit_frame()
+
+    def record_set_jit_frame(self):
+        vinfo = self.jitdriver_sd.virtualizable_info
+        if vinfo is not None:
+            virtualizable_box = self.virtualizable_boxes[-1]
             jit_frame_box = history.BoxPtr()
             self.history.record(rop.JIT_FRAME, [], jit_frame_box)
             self.history.record(rop.SETFIELD_GC, [virtualizable_box,
@@ -2423,7 +2406,9 @@
             # warmstate.py.
             virtualizable_box = self.virtualizable_boxes[-1]
             virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
-            assert not vinfo.is_token_nonnull_gcref(virtualizable)
+            # clear the jit_frame, forgetting whatever stale value it has
+            # so far, and store the content of the boxes into the virtualizable
+            vinfo.reset_jit_frame(virtualizable)
             # fill the virtualizable with the local boxes
             self.synchronize_virtualizable()
         #
@@ -2459,28 +2444,6 @@
                                                         virtualizable)
             self.virtualizable_boxes.append(virtualizable_box)
 
-    def gen_store_back_in_virtualizable(self):
-        vinfo = self.jitdriver_sd.virtualizable_info
-        if vinfo is not None:
-            # xxx only write back the fields really modified
-            vbox = self.virtualizable_boxes[-1]
-            for i in range(vinfo.num_static_extra_boxes):
-                fieldbox = self.virtualizable_boxes[i]
-                descr = vinfo.static_field_descrs[i]
-                self.execute_and_record(rop.SETFIELD_GC, descr, vbox, fieldbox)
-            i = vinfo.num_static_extra_boxes
-            virtualizable = vinfo.unwrap_virtualizable_box(vbox)
-            for k in range(vinfo.num_arrays):
-                descr = vinfo.array_field_descrs[k]
-                abox = self.execute_and_record(rop.GETFIELD_GC, descr, vbox)
-                descr = vinfo.array_descrs[k]
-                for j in range(vinfo.get_array_length(virtualizable, k)):
-                    itembox = self.virtualizable_boxes[i]
-                    i += 1
-                    self.execute_and_record(rop.SETARRAYITEM_GC, descr,
-                                            abox, ConstInt(j), itembox)
-            assert i + 1 == len(self.virtualizable_boxes)
-
     def replace_box(self, oldbox, newbox):
         assert isinstance(oldbox, Box)
         for frame in self.framestack:
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -593,7 +593,7 @@
         }
 
     is_guard = name.startswith('GUARD')
-    if is_guard:
+    if is_guard or name == 'FINISH':
         assert withdescr
         baseclass = GuardResOp
     elif withdescr:
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -55,13 +55,17 @@
 def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes,
                        storage):
     n = len(framestack)-1
-    top = framestack[n]
-    _ensure_parent_resumedata(framestack, n)
-    frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list,
-                                top.jitcode, top.pc)
+    if n >= 0:
+        top = framestack[n]
+        _ensure_parent_resumedata(framestack, n)
+        frame_info_list = FrameInfo(top.parent_resumedata_frame_info_list,
+                                    top.jitcode, top.pc)
+        snapshot = Snapshot(top.parent_resumedata_snapshot,
+                            top.get_list_of_active_boxes(False))
+    else:
+        frame_info_list = None
+        snapshot = None
     storage.rd_frame_info_list = frame_info_list
-    snapshot = Snapshot(top.parent_resumedata_snapshot,
-                        top.get_list_of_active_boxes(False))
     if virtualizable_boxes is not None:
         boxes = virtualref_boxes + virtualizable_boxes
     else:
@@ -1103,11 +1107,9 @@
             assert vinfo.is_token_nonnull_gcref(virtualizable)
             vinfo.reset_token_gcref(virtualizable)
         else:
-            # just jumped away from assembler (case 4 in the comment in
-            # virtualizable.py) into tracing (case 2); check that vable_token
-            # is and stays 0.  Note the call to reset_vable_token() in
-            # warmstate.py.
-            assert not vinfo.is_token_nonnull_gcref(virtualizable)
+            # here, virtualizable.jit_frame may contain a leftover from
+            # earlier.  We have to clean it here.
+            vinfo.reset_jit_frame(virtualizable)
         return vinfo.write_from_resume_data_partial(virtualizable, self, numb)
 
     def load_value_of_type(self, TYPE, tagged):
diff --git a/pypy/jit/metainterp/test/test_virtualizable.py b/pypy/jit/metainterp/test/test_virtualizable.py
--- a/pypy/jit/metainterp/test/test_virtualizable.py
+++ b/pypy/jit/metainterp/test/test_virtualizable.py
@@ -12,7 +12,6 @@
 from pypy.jit.metainterp.warmspot import get_stats, get_translator
 from pypy.jit.metainterp import history
 from pypy.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
-from pypy.jit.metainterp.jitframe import JITFRAMEPTR
 
 def promote_virtualizable(*args):
     pass
@@ -145,11 +144,41 @@
             while m > 0:
                 g(xy, n)
                 m -= 1
+            promote_virtualizable(xy, 'inst_x')
             return xy.inst_x
         res = self.meta_interp(f, [18])
         assert res == 10180
         self.check_resops(setfield_gc=0, getfield_gc=2)
 
+    def test_synchronize_in_return_with_rescall(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
+                                virtualizables = ['xy'])
+        @dont_look_inside
+        def rescall(xy, n):
+            if n > 9999999:
+                promote_virtualizable(xy, 'inst_x')
+        def g(xy, n):
+            while n > 0:
+                myjitdriver.can_enter_jit(xy=xy, n=n)
+                myjitdriver.jit_merge_point(xy=xy, n=n)
+                promote_virtualizable(xy, 'inst_x')
+                xy.inst_x += 1
+                rescall(xy, n)
+                n -= 1
+        def f(n):
+            xy = self.setup()
+            xy.inst_x = 10000
+            m = 10
+            while m > 0:
+                g(xy, n)
+                m -= 1
+            promote_virtualizable(xy, 'inst_x')
+            return xy.inst_x
+        res = self.meta_interp(f, [18])
+        assert res == 10180
+        # two setfield_gc(virtualizable, jit_frame)
+        self.check_resops(setfield_gc=2, getfield_gc=2)
+
     def test_virtualizable_and_greens(self):
         myjitdriver = JitDriver(greens = ['m'], reds = ['n', 'xy'],
                                 virtualizables = ['xy'])
diff --git a/pypy/jit/metainterp/virtualizable.py b/pypy/jit/metainterp/virtualizable.py
--- a/pypy/jit/metainterp/virtualizable.py
+++ b/pypy/jit/metainterp/virtualizable.py
@@ -216,6 +216,7 @@
         self.cast_gcref_to_vtype = cast_gcref_to_vtype
 
         def reset_jit_frame(virtualizable):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
             virtualizable.jit_frame = jitframe.TOKEN_NONE
         self.reset_jit_frame = reset_jit_frame
 
diff --git a/pypy/jit/metainterp/virtualref.py b/pypy/jit/metainterp/virtualref.py
--- a/pypy/jit/metainterp/virtualref.py
+++ b/pypy/jit/metainterp/virtualref.py
@@ -12,7 +12,7 @@
         # we make the low-level type of an RPython class directly
         self.JIT_VIRTUAL_REF = lltype.GcStruct('JitVirtualRef',
             ('super', rclass.OBJECT),
-            ('jit_frame', jitframe.JITFRAMEPTR),
+            ('jit_frame', llmemory.GCREF),
             ('forced', rclass.OBJECTPTR))
         self.jit_virtual_ref_vtable = lltype.malloc(rclass.OBJECT_VTABLE,
                                                     zero=True, flavor='raw',
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -549,9 +549,8 @@
             ASMRESTYPE = lltype.Float
         else:
             assert False
-        from pypy.jit.metainterp.jitframe import JITFRAMEPTR
         (_, jd._PTR_ASSEMBLER_HELPER_FUNCTYPE) = self.cpu.ts.get_FuncType(
-            [JITFRAMEPTR, llmemory.GCREF], ASMRESTYPE)
+            [llmemory.GCREF], ASMRESTYPE)
 
     def rewrite_can_enter_jits(self):
         sublists = {}
@@ -804,12 +803,8 @@
 
         vinfo = jd.virtualizable_info
 
-        def assembler_call_helper(jitframe, virtualizableref):
+        def assembler_call_helper(jitframe):
             fail_descr = self.cpu.get_latest_descr(jitframe)
-            if vinfo is not None:
-                virtualizable = lltype.cast_opaque_ptr(
-                    vinfo.VTYPEPTR, virtualizableref)
-                vinfo.reset_jit_frame(virtualizable)
             try:
                 fail_descr.handle_fail(self.metainterp_sd, jd, jitframe)
             except JitException, e:
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -301,23 +301,22 @@
         func_execute_token = self.cpu.make_execute_token(*ARGS)
 
         def execute_assembler(loop_token, *args):
+            # XXX temporary: we need to force the virtualizable, in case
+            # it contains a jit_frame.  Do better later.
+            if vinfo is not None:
+                virtualizable = args[index_of_virtualizable]
+                vinfo.clear_jit_frame(virtualizable)
+            #
             # Call the backend to run the 'looptoken' with the given
             # input args.
             frame = func_execute_token(loop_token, *args)
-            fail_descr = self.cpu.get_latest_descr(frame)
-            #
-            # If we have a virtualizable, we have to reset its
-            # 'jit_frame' field afterwards
-            if vinfo is not None:
-                virtualizable = args[index_of_virtualizable]
-                virtualizable = vinfo.cast_gcref_to_vtype(virtualizable)
-                vinfo.reset_jit_frame(virtualizable)
             #
             # Record in the memmgr that we just ran this loop,
             # so that it will keep it alive for a longer time
             warmrunnerdesc.memory_manager.keep_loop_alive(loop_token)
             #
             # Handle the failure
+            fail_descr = self.cpu.get_latest_descr(frame)
             fail_descr.handle_fail(metainterp_sd, jitdriver_sd, frame)
             #
             assert 0, "should have raised"


More information about the pypy-commit mailing list