[pypy-commit] pypy stmgc-c7: Trying to remove the conflicts on 'alive_loops'.

arigo noreply at buildbot.pypy.org
Wed Jan 28 16:13:27 CET 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c7
Changeset: r75562:b42c25c45a1c
Date: 2015-01-28 16:13 +0100
http://bitbucket.org/pypy/pypy/changeset/b42c25c45a1c/

Log:	Trying to remove the conflicts on 'alive_loops'.

diff --git a/rpython/jit/metainterp/memmgr.py b/rpython/jit/metainterp/memmgr.py
--- a/rpython/jit/metainterp/memmgr.py
+++ b/rpython/jit/metainterp/memmgr.py
@@ -1,7 +1,10 @@
 import math
 from rpython.rlib.rarithmetic import r_int64
 from rpython.rlib.debug import debug_start, debug_print, debug_stop
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import we_are_translated, stm_ignored
+from rpython.rlib.rgc import stm_is_enabled
+from rpython.rtyper import annlowlevel
+from rpython.rlib import rstm
 
 #
 # Logic to decide which loops are old and not used any more.
@@ -37,7 +40,13 @@
         # per second
         self.current_generation = r_int64(1)
         self.next_check = r_int64(-1)
-        self.alive_loops = {}
+        if not stm_is_enabled():
+            self.alive_loops = {}
+        else:
+            # hash table mapping integers to looptokens
+            self.stm_alive_loops = rstm.ll_hashtable_create()
+            # lowest integer key used in stm_alive_loops
+            self.stm_lowest_key = 0
 
     def set_max_age(self, max_age, check_frequency=0):
         if max_age <= 0:
@@ -57,21 +66,61 @@
 
     def keep_loop_alive(self, looptoken):
         if looptoken.generation != self.current_generation:
-            looptoken.generation = self.current_generation
-            self.alive_loops[looptoken] = None
+            # STM: never produce conflicts from this function.
+            with stm_ignored:
+                looptoken.generation = self.current_generation
+            if not stm_is_enabled():
+                self.alive_loops[looptoken] = None
+            else:
+                next_key = rstm.stm_count()
+                gcref = annlowlevel.cast_instance_to_gcref(looptoken)
+                rstm.ll_hashtable_set(self.stm_alive_loops, next_key, gcref)
 
     def _kill_old_loops_now(self):
         debug_start("jit-mem-collect")
-        oldtotal = len(self.alive_loops)
         #print self.alive_loops.keys()
         debug_print("Current generation:", self.current_generation)
+        max_generation = self.current_generation - (self.max_age-1)
+        #
+        if not stm_is_enabled():
+            oldtotal = len(self.alive_loops)
+            for looptoken in self.alive_loops.keys():
+                if not self._must_keep_loop(looptoken, max_generation):
+                    del self.alive_loops[looptoken]
+            newtotal = len(self.alive_loops)
+        else:
+            # this logic assumes that we are more or less the only running
+            # thread.  Even if there are possible corner cases, they should
+            # not have worse results than a possibly early or late freeing
+            # of one loop, and only in corner cases.
+            from rpython.jit.metainterp.history import JitCellToken
+            stm_alive_loops = self.stm_alive_loops
+            keep_loops = set()
+            #
+            # all keys in 'stm_alive_loops' should be in the following range
+            old_count = self.stm_lowest_key
+            new_count = rstm.stm_count()
+            for key in range(old_count, new_count):
+                gcref = rstm.ll_hashtable_get(stm_alive_loops, key)
+                if not gcref:
+                    continue
+                # make 'stm_alive_loops' empty, and add the loops that we
+                # must keep in the set 'keep_loops'
+                rstm.ll_hashtable_set(stm_alive_loops, key, rstm.NULL_GCREF)
+                looptoken = annlowlevel.cast_gcref_to_instance(JitCellToken,
+                                                               gcref)
+                if self._must_keep_loop(looptoken):
+                    keep_loops.add(looptoken)
+            newtotal = len(keep_loops)
+            #
+            # now re-add loops with key numbers that *end* at 'new_count'
+            for looptoken in keep_loops:
+                gcref = annlowlevel.cast_instance_to_gcref(looptoken)
+                rstm.ll_hashtable_set(stm_alive_loops, new_count, gcref)
+                new_count -= 1
+            self.stm_lowest_key = new_count + 1    # lowest used key number
+        #
         debug_print("Loop tokens before:", oldtotal)
-        max_generation = self.current_generation - (self.max_age-1)
-        for looptoken in self.alive_loops.keys():
-            if (0 <= looptoken.generation < max_generation or
-                looptoken.invalidated):
-                del self.alive_loops[looptoken]
-        newtotal = len(self.alive_loops)
         debug_print("Loop tokens freed: ", oldtotal - newtotal)
         debug_print("Loop tokens left:  ", newtotal)
         #print self.alive_loops.keys()
@@ -81,3 +130,7 @@
             # a single one is not enough for all tests :-(
             rgc.collect(); rgc.collect(); rgc.collect()
         debug_stop("jit-mem-collect")
+
+    def _must_keep_loop(self, looptoken, max_generation):
+        return not (0 <= looptoken.generation < max_generation or
+                    looptoken.invalidated)


More information about the pypy-commit mailing list