[pypy-svn] r79118 - in pypy/branch/jit-free/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Mon Nov 15 19:06:46 CET 2010


Author: arigo
Date: Mon Nov 15 19:06:44 2010
New Revision: 79118

Modified:
   pypy/branch/jit-free/pypy/jit/metainterp/blackhole.py
   pypy/branch/jit-free/pypy/jit/metainterp/compile.py
   pypy/branch/jit-free/pypy/jit/metainterp/history.py
   pypy/branch/jit-free/pypy/jit/metainterp/memmgr.py
   pypy/branch/jit-free/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/jit-free/pypy/jit/metainterp/resume.py
   pypy/branch/jit-free/pypy/jit/metainterp/test/test_memmgr.py
   pypy/branch/jit-free/pypy/jit/metainterp/warmspot.py
   pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py
Log:
In-progress: revert the "cleanup" part of r79094.
It was a really bad idea after all to put a strong reference
from the ResumeDescrs to the LoopToken.  Indeed, the LoopTokens
are supposed to be only stored in weak lists on JitCell and be
only be kept alive carefully by memmgr.py.


Modified: pypy/branch/jit-free/pypy/jit/metainterp/blackhole.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/blackhole.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/blackhole.py	Mon Nov 15 19:06:44 2010
@@ -1362,12 +1362,14 @@
     # We will continue to loop in _run_forever() from the parent level.
     return blackholeinterp, lle
 
-def resume_in_blackhole(metainterp_sd, resumedescr, all_virtuals=None):
+def resume_in_blackhole(metainterp_sd, jitdriver_sd, resumedescr,
+                        all_virtuals=None):
     from pypy.jit.metainterp.resume import blackhole_from_resumedata
     debug_start('jit-blackhole')
     metainterp_sd.profiler.start_blackhole()
     blackholeinterp = blackhole_from_resumedata(
         metainterp_sd.blackholeinterpbuilder,
+        jitdriver_sd,
         resumedescr,
         all_virtuals)
     current_exc = blackholeinterp._prepare_resume_from_failure(

Modified: pypy/branch/jit-free/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/compile.py	Mon Nov 15 19:06:44 2010
@@ -42,11 +42,10 @@
     name = metainterp.staticdata.stats.name_for_new_loop()
     return TreeLoop(name)
 
-def make_loop_token(cpu, nb_args, jitdriver_sd, greenkey):
+def make_loop_token(cpu, nb_args, jitdriver_sd):
     loop_token = LoopToken(cpu)
     loop_token.specnodes = [prebuiltNotSpecNode] * nb_args
     loop_token.outermost_jitdriver_sd = jitdriver_sd
-    loop_token.outermost_greenkey = greenkey
     return loop_token
 
 # ____________________________________________________________
@@ -66,7 +65,7 @@
     metainterp_sd = metainterp.staticdata
     jitdriver_sd = metainterp.jitdriver_sd
     loop_token = make_loop_token(metainterp.cpu, len(loop.inputargs),
-                                 jitdriver_sd, greenkey)
+                                 jitdriver_sd)
     loop.token = loop_token
     loop.operations[-1].setdescr(loop_token)     # patch the target of the JUMP
     try:
@@ -143,32 +142,32 @@
     pass
 
 class DoneWithThisFrameDescrVoid(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd):
-        #assert jitdriver_sd.result_type == history.VOID
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
+        assert jitdriver_sd.result_type == history.VOID
         raise metainterp_sd.DoneWithThisFrameVoid()
 
 class DoneWithThisFrameDescrInt(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd):
-        #assert jitdriver_sd.result_type == history.INT
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
+        assert jitdriver_sd.result_type == history.INT
         result = metainterp_sd.cpu.get_latest_value_int(0)
         raise metainterp_sd.DoneWithThisFrameInt(result)
 
 class DoneWithThisFrameDescrRef(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd):
-        #assert jitdriver_sd.result_type == history.REF
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
+        assert jitdriver_sd.result_type == history.REF
         cpu = metainterp_sd.cpu
         result = cpu.get_latest_value_ref(0)
         cpu.clear_latest_values(1)
         raise metainterp_sd.DoneWithThisFrameRef(cpu, result)
 
 class DoneWithThisFrameDescrFloat(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd):
-        #assert jitdriver_sd.result_type == history.FLOAT
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
+        assert jitdriver_sd.result_type == history.FLOAT
         result = metainterp_sd.cpu.get_latest_value_float(0)
         raise metainterp_sd.DoneWithThisFrameFloat(result)
 
 class ExitFrameWithExceptionDescrRef(_DoneWithThisFrameDescr):
-    def handle_fail(self, metainterp_sd):
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
         cpu = metainterp_sd.cpu
         value = cpu.get_latest_value_ref(0)
         cpu.clear_latest_values(1)
@@ -210,9 +209,8 @@
             }
 
 class ResumeDescr(AbstractFailDescr):
-    def __init__(self, original_loop_token):
-        assert isinstance(original_loop_token, history.LoopToken)
-        self.original_loop_token = original_loop_token
+    def __init__(self, original_greenkey):
+        self.original_greenkey = original_greenkey
 
 class ResumeGuardDescr(ResumeDescr):
     _counter = 0        # if < 0, there is one counter per value;
@@ -255,29 +253,26 @@
             # a negative value
             self._counter = cnt | i
 
-    def handle_fail(self, metainterp_sd):
-        if self.must_compile(metainterp_sd):
-            return self._trace_and_compile_from_bridge(metainterp_sd)
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
+        if self.must_compile(metainterp_sd, jitdriver_sd):
+            return self._trace_and_compile_from_bridge(metainterp_sd,
+                                                       jitdriver_sd)
         else:
             from pypy.jit.metainterp.blackhole import resume_in_blackhole
-            resume_in_blackhole(metainterp_sd, self)
+            resume_in_blackhole(metainterp_sd, jitdriver_sd, self)
             assert 0, "unreachable"
 
-    def _trace_and_compile_from_bridge(self, metainterp_sd):
+    def _trace_and_compile_from_bridge(self, metainterp_sd, jitdriver_sd):
+        # 'jitdriver_sd' corresponds to the outermost one, i.e. the one
+        # of the jit_merge_point where we started the loop, even if the
+        # loop itself may contain temporarily recursion into other
+        # jitdrivers.
         from pypy.jit.metainterp.pyjitpl import MetaInterp
-        metainterp = MetaInterp(metainterp_sd, self.get_jitdriver_sd())
+        metainterp = MetaInterp(metainterp_sd, jitdriver_sd)
         return metainterp.handle_guard_failure(self)
     _trace_and_compile_from_bridge._dont_inline_ = True
 
-    def get_jitdriver_sd(self):
-        # Returns the jitdriver_sd that corresponds to the outermost
-        # level, i.e. the level of the jit_merge_point where we started
-        # the loop, even if the loop itself may contain some recursion
-        # into other jitdrivers.
-        return self.original_loop_token.outermost_jitdriver_sd
-
-    def must_compile(self, metainterp_sd):
-        jitdriver_sd = self.get_jitdriver_sd()
+    def must_compile(self, metainterp_sd, jitdriver_sd):
         trace_eagerness = jitdriver_sd.warmstate.trace_eagerness
         if self._counter >= 0:
             self._counter += 1
@@ -335,18 +330,18 @@
         res.rd_pendingfields = self.rd_pendingfields
 
     def _clone_if_mutable(self):
-        res = ResumeGuardDescr(self.original_loop_token)
+        res = ResumeGuardDescr(self.original_greenkey)
         self.copy_all_attrbutes_into(res)
         return res
 
 class ResumeGuardForcedDescr(ResumeGuardDescr):
 
-    def __init__(self, metainterp_sd, original_loop_token, jitdriver_sd):
-        ResumeGuardDescr.__init__(self, original_loop_token)
+    def __init__(self, metainterp_sd, original_greenkey, jitdriver_sd):
+        ResumeGuardDescr.__init__(self, original_greenkey)
         self.metainterp_sd = metainterp_sd
         self.jitdriver_sd = jitdriver_sd
 
-    def handle_fail(self, metainterp_sd):
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
         # Failures of a GUARD_NOT_FORCED are never compiled, but
         # always just blackholed.  First fish for the data saved when
         # the virtualrefs and virtualizable have been forced by
@@ -356,7 +351,8 @@
         all_virtuals = self.fetch_data(token)
         if all_virtuals is None:
             all_virtuals = []
-        resume_in_blackhole(metainterp_sd, self, all_virtuals)
+        assert jitdriver_sd is self.jitdriver_sd
+        resume_in_blackhole(metainterp_sd, jitdriver_sd, self, all_virtuals)
         assert 0, "unreachable"
 
     @staticmethod
@@ -409,7 +405,7 @@
 
     def _clone_if_mutable(self):
         res = ResumeGuardForcedDescr(self.metainterp_sd,
-                                     self.original_loop_token,
+                                     self.original_greenkey,
                                      self.jitdriver_sd)
         self.copy_all_attrbutes_into(res)
         return res
@@ -476,11 +472,8 @@
 
 
 class ResumeFromInterpDescr(ResumeDescr):
-    def __init__(self, metainterp, greenkey, redkey):
-        original_loop_token = make_loop_token(metainterp.cpu, len(redkey),
-                                              metainterp.jitdriver_sd,
-                                              greenkey)
-        ResumeDescr.__init__(self, original_loop_token)
+    def __init__(self, original_greenkey, redkey):
+        ResumeDescr.__init__(self, original_greenkey)
         self.redkey = redkey
 
     def compile_and_attach(self, metainterp, new_loop):
@@ -491,22 +484,22 @@
         metainterp_sd = metainterp.staticdata
         jitdriver_sd = metainterp.jitdriver_sd
         metainterp.history.inputargs = self.redkey
-        new_loop_token = self.original_loop_token
-        original_greenkey = new_loop_token.outermost_greenkey
+        new_loop_token = make_loop_token(metainterp.cpu, len(self.redkey),
+                                         metainterp.jitdriver_sd)
         new_loop.inputargs = self.redkey
         new_loop.token = new_loop_token
         send_loop_to_backend(metainterp_sd, new_loop, "entry bridge")
         # send the new_loop to warmspot.py, to be called directly the next time
         jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp(
-            original_greenkey,
+            self.original_greenkey,
             new_loop_token)
         # store the new loop in compiled_merge_points_wref too
         old_loop_tokens = metainterp.get_compiled_merge_points(
-            original_greenkey)
+            self.original_greenkey)
         # it always goes at the end of the list, as it is the most
         # general loop token
         old_loop_tokens.append(new_loop_token)
-        metainterp.set_compiled_merge_points(original_greenkey,
+        metainterp.set_compiled_merge_points(self.original_greenkey,
                                              old_loop_tokens)
 
     def reset_counter_from_failure(self):
@@ -561,7 +554,7 @@
 # ____________________________________________________________
 
 class PropagateExceptionDescr(AbstractFailDescr):
-    def handle_fail(self, metainterp_sd):
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
         cpu = metainterp_sd.cpu
         exception = cpu.grab_exc_value()
         raise metainterp_sd.ExitFrameWithExceptionRef(cpu, exception)
@@ -575,7 +568,7 @@
     """
     # 'redboxes' is only used to know the types of red arguments.
     inputargs = [box.clonebox() for box in redboxes]
-    loop_token = make_loop_token(cpu, len(inputargs), jitdriver_sd, greenboxes)
+    loop_token = make_loop_token(cpu, len(inputargs), jitdriver_sd)
     # 'nb_red_args' might be smaller than len(redboxes),
     # because it doesn't include the virtualizable boxes.
     nb_red_args = jitdriver_sd.num_red_args

Modified: pypy/branch/jit-free/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/history.py	Mon Nov 15 19:06:44 2010
@@ -181,7 +181,7 @@
     index = -1
     original_loop_token = None
 
-    def handle_fail(self, metainterp_sd):
+    def handle_fail(self, metainterp_sd, jitdriver_sd):
         raise NotImplementedError
     def compile_and_attach(self, metainterp, new_loop):
         raise NotImplementedError
@@ -730,7 +730,6 @@
     """
     terminating = False # see TerminatingLoopToken in compile.py
     outermost_jitdriver_sd = None
-    outermost_greenkey = None
     # specnodes = ...
     # and more data specified by the backend when the loop is compiled
     cpu = None
@@ -759,6 +758,9 @@
             self.cpu.free_loop_and_bridges(self)
             debug_stop("jit-free-looptoken")
 
+    def __repr__(self):
+        return '<Loop %d, gen=%d>' % (self.number, self.generation)
+
     def repr_of_descr(self):
         return '<Loop%d>' % self.number
 

Modified: pypy/branch/jit-free/pypy/jit/metainterp/memmgr.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/memmgr.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/memmgr.py	Mon Nov 15 19:06:44 2010
@@ -59,6 +59,8 @@
     def _kill_old_loops_now(self):
         debug_start("jit-free-memmgr")
         oldtotal = len(self.alive_loops)
+        print self.alive_loops.keys()
+        debug_print("Current generation:", self.current_generation)
         debug_print("Loop tokens before:", oldtotal)
         max_generation = self.current_generation - self.max_age
         for looptoken in self.alive_loops.keys():
@@ -67,4 +69,5 @@
         newtotal = len(self.alive_loops)
         debug_print("Loop tokens freed: ", oldtotal - newtotal)
         debug_print("Loop tokens left:  ", newtotal)
+        print self.alive_loops.keys()
         debug_stop("jit-free-memmgr")

Modified: pypy/branch/jit-free/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/pyjitpl.py	Mon Nov 15 19:06:44 2010
@@ -1048,13 +1048,13 @@
         else:
             moreargs = list(extraargs)
         metainterp_sd = metainterp.staticdata
-        original_loop_token = metainterp.resumekey.original_loop_token
+        original_greenkey = metainterp.resumekey.original_greenkey
         if opnum == rop.GUARD_NOT_FORCED:
-            resumedescr = compile.ResumeGuardForcedDescr(metainterp.staticdata,
-                                                      original_loop_token,
-                                                      metainterp.jitdriver_sd)
+            resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd,
+                                                   original_greenkey,
+                                                   metainterp.jitdriver_sd)
         else:
-            resumedescr = compile.ResumeGuardDescr(original_loop_token)
+            resumedescr = compile.ResumeGuardDescr(original_greenkey)
         guard_op = metainterp.history.record(opnum, moreargs, None,
                                              descr=resumedescr)
         virtualizable_boxes = None
@@ -1326,6 +1326,11 @@
                     return jitcode
             return None
 
+    def try_to_free_some_loops(self):
+        # Increase here the generation recorded by the memory manager.
+        if self.warmrunnerdesc is not None:       # for tests
+            self.warmrunnerdesc.memory_manager.next_generation()
+
     # ---------------- logging ------------------------
 
     def log(self, msg):
@@ -1369,9 +1374,6 @@
         self.portal_trace_positions = []
         self.free_frames_list = []
         self.last_exc_value_box = None
-        # Increase here the generation recorded by the memory manager.
-        if self.staticdata.warmrunnerdesc is not None:       # for tests
-            self.staticdata.warmrunnerdesc.memory_manager.next_generation()
 
     def perform_call(self, jitcode, boxes, greenkey=None):
         # causes the metainterp to enter the given subfunction
@@ -1622,6 +1624,7 @@
         # is also available as 'self.jitdriver_sd', because we need to
         # specialize this function and a few other ones for the '*args'.
         debug_start('jit-tracing')
+        self.staticdata.try_to_free_some_loops()
         self.staticdata._setup_once()
         self.staticdata.profiler.start_tracing()
         assert jitdriver_sd is self.jitdriver_sd
@@ -1639,7 +1642,7 @@
         num_green_args = self.jitdriver_sd.num_green_args
         original_greenkey = original_boxes[:num_green_args]
         redkey = original_boxes[num_green_args:]
-        self.resumekey = compile.ResumeFromInterpDescr(self, original_greenkey,
+        self.resumekey = compile.ResumeFromInterpDescr(original_greenkey,
                                                        redkey)
         self.seen_loop_header_for_jdindex = -1
         try:
@@ -1652,6 +1655,7 @@
 
     def handle_guard_failure(self, key):
         debug_start('jit-tracing')
+        self.staticdata.try_to_free_some_loops()
         self.staticdata.profiler.start_tracing()
         assert isinstance(key, compile.ResumeGuardDescr)
         self.initialize_state_from_guard_failure(key)
@@ -1662,7 +1666,7 @@
             debug_stop('jit-tracing')
 
     def _handle_guard_failure(self, key):
-        original_greenkey = key.original_loop_token.outermost_greenkey
+        original_greenkey = key.original_greenkey
         # notice that here we just put the greenkey
         # use -1 to mark that we will have to give up
         # because we cannot reconstruct the beginning of the proper loop

Modified: pypy/branch/jit-free/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/resume.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/resume.py	Mon Nov 15 19:06:44 2010
@@ -915,11 +915,10 @@
 
 # ---------- when resuming for blackholing, get direct values ----------
 
-def blackhole_from_resumedata(blackholeinterpbuilder, storage,
+def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage,
                               all_virtuals=None):
     resumereader = ResumeDataDirectReader(blackholeinterpbuilder.metainterp_sd,
                                           storage, all_virtuals)
-    jitdriver_sd = storage.get_jitdriver_sd()
     vinfo = jitdriver_sd.virtualizable_info
     ginfo = jitdriver_sd.greenfield_info
     vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info

Modified: pypy/branch/jit-free/pypy/jit/metainterp/test/test_memmgr.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/test/test_memmgr.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/test/test_memmgr.py	Mon Nov 15 19:06:44 2010
@@ -1,7 +1,6 @@
 from pypy.jit.metainterp.memmgr import MemoryManager
-
-##missing:
-##    contains_jumps_to needs to be filled
+from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.rlib.jit import JitDriver
 
 
 class FakeLoopToken:
@@ -57,3 +56,23 @@
                 assert tokens[i] not in memmgr.alive_loops
             else:
                 assert tokens[i] in memmgr.alive_loops
+
+
+class TestIntegration(LLJitMixin):
+
+    def test_loop_kept_alive(self):
+        myjitdriver = JitDriver(greens=[], reds=['n'])
+        def g():
+            n = 10
+            while n > 0:
+                myjitdriver.can_enter_jit(n=n)
+                myjitdriver.jit_merge_point(n=n)
+                n = n - 1
+            return 21
+        def f():
+            for i in range(6):
+                g()
+            return 42
+
+        res = self.meta_interp(f, [], loop_longevity=1)
+        assert res == 42

Modified: pypy/branch/jit-free/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/warmspot.py	Mon Nov 15 19:06:44 2010
@@ -67,7 +67,8 @@
 
 def jittify_and_run(interp, graph, args, repeat=1,
                     backendopt=False, trace_limit=sys.maxint,
-                    debug_level=DEBUG_STEPS, inline=False, **kwds):
+                    debug_level=DEBUG_STEPS, inline=False,
+                    loop_longevity=0, **kwds):
     from pypy.config.config import ConfigError
     translator = interp.typer.annotator.translator
     try:
@@ -85,6 +86,7 @@
         jd.warmstate.set_param_trace_limit(trace_limit)
         jd.warmstate.set_param_inlining(inline)
         jd.warmstate.set_param_debug(debug_level)
+        jd.warmstate.set_param_loop_longevity(loop_longevity)
     warmrunnerdesc.finish()
     res = interp.eval_graph(graph, args)
     if not kwds.get('translate_support_code', False):
@@ -713,7 +715,7 @@
                         vinfo.VTYPEPTR, virtualizableref)
                     vinfo.reset_vable_token(virtualizable)
                 try:
-                    loop_token = fail_descr.handle_fail(self.metainterp_sd)
+                    loop_token = fail_descr.handle_fail(self.metainterp_sd, jd)
                 except JitException, e:
                     return handle_jitexception(e)
                 fail_descr = self.execute_token(loop_token)
@@ -820,4 +822,5 @@
         debug_stop("jit-running")
         self.metainterp_sd.profiler.end_running()
         self.memory_manager.keep_loop_alive(loop_token)
+        print loop_token
         return fail_descr

Modified: pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py	Mon Nov 15 19:06:44 2010
@@ -340,7 +340,8 @@
                 fail_descr = warmrunnerdesc.execute_token(loop_token)
                 if vinfo is not None:
                     vinfo.reset_vable_token(virtualizable)
-                loop_token = fail_descr.handle_fail(metainterp_sd)
+                loop_token = fail_descr.handle_fail(metainterp_sd,
+                                                    jitdriver_sd)
 
         maybe_compile_and_run._dont_inline_ = True
         self.maybe_compile_and_run = maybe_compile_and_run



More information about the Pypy-commit mailing list