[pypy-commit] pypy improve-gc-tracing-hooks: Simplify custom tracers with gc._trace_callback(). Port jitframe.

arigo noreply at buildbot.pypy.org
Tue Oct 21 15:20:26 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: improve-gc-tracing-hooks
Changeset: r74037:9ec0a7216835
Date: 2014-10-21 15:20 +0200
http://bitbucket.org/pypy/pypy/changeset/9ec0a7216835/

Log:	Simplify custom tracers with gc._trace_callback(). Port jitframe.

diff --git a/rpython/jit/backend/llsupport/jitframe.py b/rpython/jit/backend/llsupport/jitframe.py
--- a/rpython/jit/backend/llsupport/jitframe.py
+++ b/rpython/jit/backend/llsupport/jitframe.py
@@ -3,6 +3,7 @@
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib.debug import ll_assert
 from rpython.rlib.objectmodel import enforceargs
+from rpython.rlib import rgc
 
 SIZEOFSIGNED = rffi.sizeof(lltype.Signed)
 IS_32BIT = (SIZEOFSIGNED == 4)
@@ -45,6 +46,7 @@
 # detailed explanation how it is on your architecture
 
 def jitframe_allocate(frame_info):
+    rgc.register_custom_trace_hook(JITFRAME, lambda_jitframe_trace)
     frame = lltype.malloc(JITFRAME, frame_info.jfi_frame_depth)
     frame.jf_frame_info = frame_info
     frame.jf_extra_stack_depth = 0
@@ -80,8 +82,6 @@
     ('jf_guard_exc', llmemory.GCREF),
     # in case the frame got reallocated, we have to forward it somewhere
     ('jf_forward', lltype.Ptr(JITFRAME)),
-    # absolutely useless field used to make up for tracing hooks inflexibilities
-    ('jf_gc_trace_state', lltype.Signed),
     # the actual frame
     ('jf_frame', lltype.Array(lltype.Signed)),
     # note that we keep length field, because it's crucial to have the data
@@ -105,75 +105,38 @@
 UNSIGN_SIZE = llmemory.sizeof(lltype.Unsigned)
 STACK_DEPTH_OFS = getofs('jf_extra_stack_depth')
 
-def jitframe_trace(obj_addr, prev):
-    if prev == llmemory.NULL:
-        (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -1
-        return obj_addr + getofs('jf_descr')
-    fld = (obj_addr + getofs('jf_gc_trace_state')).signed[0]
-    if fld < 0:
-        if fld == -1:
-            (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -2
-            return obj_addr + getofs('jf_force_descr')
-        elif fld == -2:
-            (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -3
-            return obj_addr + getofs('jf_savedata')
-        elif fld == -3:
-            (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -4
-            return obj_addr + getofs('jf_guard_exc')
-        elif fld == -4:
-            (obj_addr + getofs('jf_gc_trace_state')).signed[0] = -5
-            return obj_addr + getofs('jf_forward')
-        else:
-            if not (obj_addr + getofs('jf_gcmap')).address[0]:
-                return llmemory.NULL    # done
-            else:
-                fld = 0    # fall-through
-    # bit pattern
-    # decode the pattern
+def jitframe_trace(gc, obj_addr, callback, arg):
+    gc._trace_callback(callback, arg, obj_addr + getofs('jf_descr'))
+    gc._trace_callback(callback, arg, obj_addr + getofs('jf_force_descr'))
+    gc._trace_callback(callback, arg, obj_addr + getofs('jf_savedata'))
+    gc._trace_callback(callback, arg, obj_addr + getofs('jf_guard_exc'))
+    gc._trace_callback(callback, arg, obj_addr + getofs('jf_forward'))
+
     if IS_32BIT:
-        # 32 possible bits
-        state = fld & 0x1f
-        no = fld >> 5
         MAX = 32
     else:
-        # 64 possible bits
-        state = fld & 0x3f
-        no = fld >> 6
         MAX = 64
     gcmap = (obj_addr + getofs('jf_gcmap')).address[0]
+    if not gcmap:
+        return      # done
     gcmap_lgt = (gcmap + GCMAPLENGTHOFS).signed[0]
+    no = 0
     while no < gcmap_lgt:
         cur = (gcmap + GCMAPBASEOFS + UNSIGN_SIZE * no).unsigned[0]
-        while not (cur & (1 << state)):
-            state += 1
-            if state == MAX:
-                no += 1
-                state = 0
-                break      # next iteration of the outermost loop
-        else:
-            # found it
-            index = no * SIZEOFSIGNED * 8 + state
-            # save new state
-            state += 1
-            if state == MAX:
-                no += 1
-                state = 0
-            if IS_32BIT:
-                new_state = state | (no << 5)
-            else:
-                new_state = state | (no << 6)
-            (obj_addr + getofs('jf_gc_trace_state')).signed[0] = new_state
-            # sanity check
-            frame_lgt = (obj_addr + getofs('jf_frame') + LENGTHOFS).signed[0]
-            ll_assert(index < frame_lgt, "bogus frame field get")
-            return (obj_addr + getofs('jf_frame') + BASEITEMOFS + SIGN_SIZE *
-                    (index))
-    return llmemory.NULL
-
-CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
-                                  llmemory.Address)
-jitframe_trace_ptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), jitframe_trace)
-
-lltype.attachRuntimeTypeInfo(JITFRAME, customtraceptr=jitframe_trace_ptr)
+        bitindex = 0
+        while bitindex < MAX:
+            if cur & (1 << bitindex):
+                # the 'bitindex' is set in 'cur'
+                index = no * SIZEOFSIGNED * 8 + bitindex
+                # sanity check
+                frame_lgt = (obj_addr + getofs('jf_frame') + LENGTHOFS) \
+                    .signed[0]
+                ll_assert(index < frame_lgt, "bogus frame field get")
+                gc._trace_callback(callback, arg,
+                                   obj_addr + getofs('jf_frame') +
+                                   BASEITEMOFS + SIGN_SIZE * index)
+            bitindex += 1
+        no += 1
+lambda_jitframe_trace = lambda: jitframe_trace
 
 JITFRAMEPTR = lltype.Ptr(JITFRAME)
diff --git a/rpython/jit/backend/llsupport/test/test_gc.py b/rpython/jit/backend/llsupport/test/test_gc.py
--- a/rpython/jit/backend/llsupport/test/test_gc.py
+++ b/rpython/jit/backend/llsupport/test/test_gc.py
@@ -254,11 +254,15 @@
     frame.jf_gcmap[2] = r_uint(2 | 16 | 32 | 128)
     frame.jf_gcmap[3] = r_uint(0)
     frame_adr = llmemory.cast_ptr_to_adr(frame)
+    #
     all_addrs = []
-    next = jitframe.jitframe_trace(frame_adr, llmemory.NULL)
-    while next:
-        all_addrs.append(next)
-        next = jitframe.jitframe_trace(frame_adr, next)
+    class FakeGC:
+        def _trace_callback(self, callback, arg, addr):
+            assert callback == "hello"
+            assert arg == "world"
+            all_addrs.append(addr)
+    jitframe.jitframe_trace(FakeGC(), frame_adr, "hello", "world")
+    #
     counter = 0
     for name in jitframe.JITFRAME._names:
         TP = getattr(jitframe.JITFRAME, name)
@@ -297,12 +301,12 @@
     frame.jf_gcmap[0] = r_uint(18446744073441116160)
     frame.jf_gcmap[1] = r_uint(18446740775107559407)
     frame.jf_gcmap[2] = r_uint(3)
-    all_addrs = []
     frame_adr = llmemory.cast_ptr_to_adr(frame)
-    next = jitframe.jitframe_trace(frame_adr, llmemory.NULL)
-    while next:
-        all_addrs.append(next)
-        next = jitframe.jitframe_trace(frame_adr, next)
+    class FakeGC:
+        def _trace_callback(self, callback, arg, addr):
+            assert callback == "hello"
+            assert arg == "world"
+    jitframe.jitframe_trace(FakeGC(), frame_adr, "hello", "world")
     # assert did not hang
 
     lltype.free(frame_info, flavor='raw')
diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -224,6 +224,11 @@
             self.custom_trace_dispatcher(obj, typeid, callback, arg)
     _trace_slow_path._annspecialcase_ = 'specialize:arg(2)'
 
+    def _trace_callback(self, callback, arg, addr):
+        if self.is_valid_gc_object(addr.address[0]):
+            callback(addr, arg)
+    _trace_callback._annspecialcase_ = 'specialize:arg(1)'
+
     def trace_partial(self, obj, start, stop, callback, arg):
         """Like trace(), but only walk the array part, for indices in
         range(start, stop).  Must only be called if has_gcptr_in_varsize().
diff --git a/rpython/memory/test/gc_test_base.py b/rpython/memory/test/gc_test_base.py
--- a/rpython/memory/test/gc_test_base.py
+++ b/rpython/memory/test/gc_test_base.py
@@ -245,8 +245,7 @@
         T = lltype.GcStruct('T', ('z', lltype.Signed))
         offset_of_x = llmemory.offsetof(S, 'x')
         def customtrace(gc, obj, callback, arg):
-            if gc.is_valid_gc_object((obj + offset_of_x).address[0]):
-                callback(obj + offset_of_x, arg)
+            gc._trace_callback(callback, arg, obj + offset_of_x)
         lambda_customtrace = lambda: customtrace
         #
         for attrname in ['x', 'y']:
diff --git a/rpython/memory/test/test_transformed_gc.py b/rpython/memory/test/test_transformed_gc.py
--- a/rpython/memory/test/test_transformed_gc.py
+++ b/rpython/memory/test/test_transformed_gc.py
@@ -390,8 +390,7 @@
         T = lltype.GcStruct('T', ('z', lltype.Signed))
         offset_of_x = llmemory.offsetof(S, 'x')
         def customtrace(gc, obj, callback, arg):
-            if gc.is_valid_gc_object((obj + offset_of_x).address[0]):
-                callback(obj + offset_of_x, arg)
+            gc._trace_callback(callback, arg, obj + offset_of_x)
         lambda_customtrace = lambda: customtrace
 
         #
diff --git a/rpython/rlib/_stacklet_asmgcc.py b/rpython/rlib/_stacklet_asmgcc.py
--- a/rpython/rlib/_stacklet_asmgcc.py
+++ b/rpython/rlib/_stacklet_asmgcc.py
@@ -102,8 +102,7 @@
                                                   location)
                     # yield the translated addr of the next GCREF in the stack
                     addr = self.translateptr(addr)
-                    if gc.is_valid_gc_object(addr.address[0]):
-                        callback(addr, arg)
+                    gc._trace_callback(callback, arg, addr)
 
                 caller = self.otherframe
                 reg = CALLEE_SAVED_REGS - 1
diff --git a/rpython/translator/c/test/test_newgc.py b/rpython/translator/c/test/test_newgc.py
--- a/rpython/translator/c/test/test_newgc.py
+++ b/rpython/translator/c/test/test_newgc.py
@@ -446,8 +446,7 @@
         S = lltype.GcStruct('S', ('x', llmemory.Address))
         offset_of_x = llmemory.offsetof(S, 'x')
         def customtrace(gc, obj, callback, arg):
-            if gc.is_valid_gc_object((obj + offset_of_x).address[0]):
-                callback(obj + offset_of_x, arg)
+            gc._trace_callback(callback, arg, obj + offset_of_x)
         lambda_customtrace = lambda: customtrace
         #
         def setup():


More information about the pypy-commit mailing list