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

arigo at codespeak.net arigo at codespeak.net
Mon Nov 15 17:10:29 CET 2010


Author: arigo
Date: Mon Nov 15 17:10:27 2010
New Revision: 79112

Modified:
   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/test/test_basic.py
   pypy/branch/jit-free/pypy/jit/metainterp/test/test_warmstate.py
   pypy/branch/jit-free/pypy/jit/metainterp/warmstate.py
Log:
(antocuni, arigo)

Turn the storage of looptokens into nice methods on JitCell,
and internally store weakrefs.

Some debug_start/debug_print/debug_stops.


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 17:10:27 2010
@@ -500,12 +500,14 @@
         jitdriver_sd.warmstate.attach_unoptimized_bridge_from_interp(
             original_greenkey,
             new_loop_token)
-        # store the new loop in compiled_merge_points too
+        # store the new loop in compiled_merge_points_wref too
         old_loop_tokens = metainterp.get_compiled_merge_points(
             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,
+                                             old_loop_tokens)
 
     def reset_counter_from_failure(self):
         pass

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 17:10:27 2010
@@ -5,6 +5,7 @@
 from pypy.rlib.objectmodel import we_are_translated, r_dict, Symbolic
 from pypy.rlib.objectmodel import compute_hash, compute_unique_id
 from pypy.rlib.rarithmetic import intmask, r_longlong
+from pypy.rlib.debug import debug_start, debug_print, debug_stop
 from pypy.tool.uid import uid
 from pypy.conftest import option
 
@@ -753,7 +754,10 @@
             # MemoryManager.keep_loop_alive() has been called on this
             # loop token, which means that it has been successfully
             # compiled by the backend.  Free it now.
+            debug_start("jit-free-looptoken")
+            debug_print("Freeing loop #", self.number)
             self.cpu.free_loop_and_bridges(self)
+            debug_stop("jit-free-looptoken")
 
     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 17:10:27 2010
@@ -1,14 +1,16 @@
 import math
 from pypy.rlib.rarithmetic import r_longlong
+from pypy.rlib.debug import debug_start, debug_print, debug_stop
 
 #
 # Logic to decide which loops are old and not used any more.
 #
-# All the long-lived references to LoopToken are weakrefs, apart from
-# the 'alive_loops' set in MemoryManager, which is the only (long-living)
-# place that keeps them alive.  If a loop was not called for long enough,
-# then it is removed from 'alive_loops'.  It will soon be freed by the
-# GC.  LoopToken.__del__ calls the method cpu.free_loop_and_bridges().
+# All the long-lived references to LoopToken are weakrefs (see JitCell
+# in warmstate.py), apart from the 'alive_loops' set in MemoryManager,
+# which is the only (long-living) place that keeps them alive.  If a
+# loop was not called for long enough, then it is removed from
+# 'alive_loops'.  It will soon be freed by the GC.  LoopToken.__del__
+# calls the method cpu.free_loop_and_bridges().
 #
 # The alive_loops set is maintained using the notion of a global
 # 'current generation' which is, in practice, the total number of loops
@@ -55,7 +57,14 @@
             self.alive_loops[looptoken] = None
 
     def _kill_old_loops_now(self):
+        debug_start("jit-free-memmgr")
+        oldtotal = len(self.alive_loops)
+        debug_print("Loop tokens before:", oldtotal)
         max_generation = self.current_generation - self.max_age
         for looptoken in self.alive_loops.keys():
             if 0 <= looptoken.generation < max_generation:
                 del self.alive_loops[looptoken]
+        newtotal = len(self.alive_loops)
+        debug_print("Loop tokens freed: ", oldtotal - newtotal)
+        debug_print("Loop tokens left:  ", newtotal)
+        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 17:10:27 2010
@@ -1796,10 +1796,15 @@
             raise NotImplementedError(opname[opnum])
 
     def get_compiled_merge_points(self, greenkey):
+        """Get the list of looptokens corresponding to the greenkey.
+        Turns the (internal) list of weakrefs into regular refs.
+        """
+        cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
+        return cell.get_compiled_merge_points()
+
+    def set_compiled_merge_points(self, greenkey, looptokens):
         cell = self.jitdriver_sd.warmstate.jit_cell_at_key(greenkey)
-        if cell.compiled_merge_points is None:
-            cell.compiled_merge_points = []
-        return cell.compiled_merge_points
+        cell.set_compiled_merge_points(looptokens)
 
     def compile(self, original_boxes, live_arg_boxes, start):
         num_green_args = self.jitdriver_sd.num_green_args
@@ -1810,6 +1815,7 @@
         loop_token = compile.compile_new_loop(self, old_loop_tokens,
                                               greenkey, start)
         if loop_token is not None: # raise if it *worked* correctly
+            self.set_compiled_merge_points(greenkey, old_loop_tokens)
             raise GenerateMergePoint(live_arg_boxes, loop_token)
         self.history.operations.pop()     # remove the JUMP
 

Modified: pypy/branch/jit-free/pypy/jit/metainterp/test/test_basic.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/test/test_basic.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/test/test_basic.py	Mon Nov 15 17:10:27 2010
@@ -19,7 +19,11 @@
     from pypy.jit.metainterp import simple_optimize
 
     class FakeJitCell:
-        compiled_merge_points = None
+        __compiled_merge_points = []
+        def get_compiled_merge_points(self):
+            return self.__compiled_merge_points[:]
+        def set_compiled_merge_points(self, lst):
+            self.__compiled_merge_points = lst
 
     class FakeWarmRunnerState:
         def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):

Modified: pypy/branch/jit-free/pypy/jit/metainterp/test/test_warmstate.py
==============================================================================
--- pypy/branch/jit-free/pypy/jit/metainterp/test/test_warmstate.py	(original)
+++ pypy/branch/jit-free/pypy/jit/metainterp/test/test_warmstate.py	Mon Nov 15 17:10:27 2010
@@ -157,12 +157,15 @@
         _get_jitcell_at_ptr = None
     state = WarmEnterState(None, FakeJitDriverSD())
     get_jitcell = state.make_jitcell_getter()
+    class FakeLoopToken(object):
+        pass
+    looptoken = FakeLoopToken()
     state.attach_unoptimized_bridge_from_interp([ConstInt(5),
                                                  ConstFloat(2.25)],
-                                                "entry loop token")
+                                                looptoken)
     cell1 = get_jitcell(True, 5, 2.25)
     assert cell1.counter < 0
-    assert cell1.entry_loop_token == "entry loop token"
+    assert cell1.get_entry_loop_token() is looptoken
 
 def test_make_jitdriver_callbacks_1():
     class FakeWarmRunnerDesc:

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 17:10:27 2010
@@ -1,4 +1,4 @@
-import sys
+import sys, weakref
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.annlowlevel import hlstr, llstr, cast_base_ptr_to_instance
@@ -150,9 +150,34 @@
     #     counter == -1: there is an entry bridge for this cell
     #     counter == -2: tracing is currently going on for this cell
     counter = 0
-    compiled_merge_points = None
+    compiled_merge_points_wref = None    # list of weakrefs to LoopToken
     dont_trace_here = False
-    entry_loop_token = None
+    wref_entry_loop_token = None         # (possibly) one weakref to LoopToken
+
+    def get_compiled_merge_points(self):
+        result = []
+        if self.compiled_merge_points_wref is not None:
+            for wref in self.compiled_merge_points_wref:
+                looptoken = wref()
+                if looptoken is not None:
+                    result.append(looptoken)
+        return result
+
+    def set_compiled_merge_points(self, looptokens):
+        self.compiled_merge_points_wref = [self._makeref(token)
+                                           for token in looptokens]
+
+    def get_entry_loop_token(self):
+        if self.wref_entry_loop_token is not None:
+            return self.wref_entry_loop_token()
+        return None
+
+    def set_entry_loop_token(self, looptoken):
+        self.wref_entry_loop_token = self._makeref(looptoken)
+
+    def _makeref(self, looptoken):
+        assert looptoken is not None
+        return weakref.ref(looptoken)
 
 # ____________________________________________________________
 
@@ -234,8 +259,8 @@
                                               entry_loop_token):
         cell = self.jit_cell_at_key(greenkey)
         cell.counter = -1
-        old_token = cell.entry_loop_token
-        cell.entry_loop_token = entry_loop_token
+        old_token = cell.get_entry_loop_token()
+        cell.set_entry_loop_token(entry_loop_token)
         if old_token is not None:
             self.cpu.redirect_call_assembler(old_token, entry_loop_token)
 
@@ -308,7 +333,7 @@
                 # machine code was already compiled for these greenargs
                 # get the assembler and fill in the boxes
                 set_future_values(*args[num_green_args:])
-                loop_token = cell.entry_loop_token
+                loop_token = cell.get_entry_loop_token()
 
             # ---------- execute assembler ----------
             while True:     # until interrupted by an exception
@@ -532,11 +557,13 @@
         def get_assembler_token(greenkey, redboxes):
             # 'redboxes' is only used to know the types of red arguments
             cell = self.jit_cell_at_key(greenkey)
-            if cell.entry_loop_token is None:
+            entry_loop_token = cell.get_entry_loop_token()
+            if entry_loop_token is None:
                 from pypy.jit.metainterp.compile import compile_tmp_callback
-                cell.entry_loop_token = compile_tmp_callback(cpu, jd, greenkey,
-                                                             redboxes)
-            return cell.entry_loop_token
+                entry_loop_token = compile_tmp_callback(cpu, jd, greenkey,
+                                                        redboxes)
+                cell.set_entry_loop_token(entry_loop_token)
+            return entry_loop_token
         self.get_assembler_token = get_assembler_token
         
         #



More information about the Pypy-commit mailing list