[pypy-commit] pypy improve-gc-tracing-hooks: (arigo, fijal) whack whack whack, until we get the first test to call the callback

fijal noreply at buildbot.pypy.org
Mon Oct 20 14:43:30 CEST 2014


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: improve-gc-tracing-hooks
Changeset: r74019:403fe85b70bd
Date: 2014-10-20 14:43 +0200
http://bitbucket.org/pypy/pypy/changeset/403fe85b70bd/

Log:	(arigo, fijal) whack whack whack, until we get the first test to
	call the callback

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
@@ -70,7 +70,6 @@
                             member_index,
                             is_rpython_class,
                             has_custom_trace,
-                            get_custom_trace,
                             fast_path_tracing,
                             has_gcptr):
         self.getfinalizer = getfinalizer
@@ -88,7 +87,6 @@
         self.member_index = member_index
         self.is_rpython_class = is_rpython_class
         self.has_custom_trace = has_custom_trace
-        self.get_custom_trace = get_custom_trace
         self.fast_path_tracing = fast_path_tracing
         self.has_gcptr = has_gcptr
 
@@ -223,14 +221,7 @@
                 item += itemlength
                 length -= 1
         if self.has_custom_trace(typeid):
-            generator = self.get_custom_trace(typeid)
-            item = llmemory.NULL
-            while True:
-                item = generator(obj, item)
-                if not item:
-                    break
-                if self.points_to_valid_gc_object(item):
-                    callback(item, arg)
+            self.custom_trace_dispatcher(obj, typeid, callback, arg)
     _trace_slow_path._annspecialcase_ = 'specialize:arg(2)'
 
     def trace_partial(self, obj, start, stop, callback, arg):
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -21,13 +21,9 @@
     # It is called with the object as first argument, and the previous
     # returned address (or NULL the first time) as the second argument.
     FINALIZER_FUNC = lltype.FuncType([llmemory.Address], lltype.Void)
-    CUSTOMTRACER_FUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
-                                        llmemory.Address)
     FINALIZER = lltype.Ptr(FINALIZER_FUNC)
-    CUSTOMTRACER = lltype.Ptr(CUSTOMTRACER_FUNC)
     EXTRA = lltype.Struct("type_info_extra",
-                          ('finalizer', FINALIZER),
-                          ('customtracer', CUSTOMTRACER))
+                          ('finalizer', FINALIZER))
 
     # structure describing the layout of a typeid
     TYPE_INFO = lltype.Struct("type_info",
@@ -133,12 +129,6 @@
         infobits = self.get(typeid).infobits
         return infobits & T_HAS_CUSTOM_TRACE != 0
 
-    def q_get_custom_trace(self, typeid):
-        ll_assert(self.q_has_custom_trace(typeid),
-                  "T_HAS_CUSTOM_TRACE missing")
-        typeinfo = self.get(typeid)
-        return typeinfo.extra.customtracer
-
     def q_fast_path_tracing(self, typeid):
         # return True if none of the flags T_HAS_GCPTR_IN_VARSIZE,
         # T_IS_GCARRAY_OF_GCPTR or T_HAS_CUSTOM_TRACE is set
@@ -165,7 +155,6 @@
             self.q_member_index,
             self.q_is_rpython_class,
             self.q_has_custom_trace,
-            self.q_get_custom_trace,
             self.q_fast_path_tracing,
             self.q_has_gcptr)
 
@@ -411,7 +400,9 @@
         return None
 
     def initialize_gc_query_function(self, gc):
-        return GCData(self.type_info_group).set_query_functions(gc)
+        gcdata = GCData(self.type_info_group)
+        gcdata.set_query_functions(gc)
+        return gcdata
 
     def consider_constant(self, TYPE, value, gc):
         if value is not lltype.top_container(value):
diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py
--- a/rpython/memory/gcwrapper.py
+++ b/rpython/memory/gcwrapper.py
@@ -29,7 +29,7 @@
                                                lltype2vtable,
                                                self.llinterp)
         self.get_type_id = layoutbuilder.get_type_id
-        layoutbuilder.initialize_gc_query_function(self.gc)
+        gcdata = layoutbuilder.initialize_gc_query_function(self.gc)
 
         constants = collect_constants(flowgraphs)
         for obj in constants:
@@ -38,8 +38,27 @@
 
         self.constantroots = layoutbuilder.addresses_of_static_ptrs
         self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc
+        self.prepare_custom_trace_funcs(gcdata)
         self._all_prebuilt_gc = layoutbuilder.all_prebuilt_gc
 
+    def prepare_custom_trace_funcs(self, gcdata):
+        custom_trace_funcs = self.llinterp.typer.custom_trace_funcs
+
+        def custom_trace(obj, typeid, callback, arg):
+            for TP, func in custom_trace_funcs:
+                if typeid == self.get_type_id(TP):
+                    func(obj, callback, arg)
+                    return
+            else:
+                assert False
+        
+        for TP, func in custom_trace_funcs:
+            type_info = gcdata.get(self.get_type_id(TP))
+            type_info.infobits |= (gctypelayout.T_HAS_CUSTOM_TRACE |
+                                   gctypelayout.T_HAS_GCPTR)
+
+        self.gc.custom_trace_dispatcher = custom_trace
+
     # ____________________________________________________________
     #
     # Interface for the llinterp
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
@@ -6,7 +6,7 @@
 from rpython.rtyper.test.test_llinterp import get_interpreter
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.lltypesystem.lloperation import llop
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import we_are_translated, keepalive_until_here
 from rpython.rlib.objectmodel import compute_unique_id
 from rpython.rlib import rgc
 from rpython.rlib.rstring import StringBuilder
@@ -762,6 +762,22 @@
             assert rgc.get_gcflag_extra(a1) == False
             assert rgc.get_gcflag_extra(a2) == False
         self.interpret(fn, [])
+    
+    def test_register_custom_trace_hook(self):
+        S = lltype.GcStruct('S', ('x', lltype.Signed))
+        called = []
+
+        def trace_hook(obj, callback, arg):
+            called.append("called")
+
+        def f():
+            rgc.register_custom_trace_hook(S, trace_hook)
+            s = lltype.malloc(S)
+            rgc.collect()
+            keepalive_until_here(s)
+
+        self.interpret(f, [])
+        assert called # not empty, can contain more than one item
 
 from rpython.rlib.objectmodel import UnboxedValue
 
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
@@ -14,7 +14,7 @@
 from rpython.conftest import option
 from rpython.rlib.rstring import StringBuilder
 from rpython.rlib.rarithmetic import LONG_BIT
-import pdb
+
 
 WORD = LONG_BIT // 8
 
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -550,14 +550,14 @@
 def lltype_is_gc(TP):
     return getattr(getattr(TP, "TO", None), "_gckind", "?") == 'gc'
 
-def register_custom_gc_trace(TP, func):
+def register_custom_trace_hook(TP, func):
     """ This function does not do anything, but called from any annotated
     place, will tell that "func" is used to trace GC roots inside any instance
     of the type TP
     """
 
 class RegisterGcTraceEntry(ExtRegistryEntry):
-    _about_ = register_custom_gc_trace
+    _about_ = register_custom_trace_hook
 
     def compute_result_annotation(self, *args_s):
         pass
diff --git a/rpython/rlib/test/test_rgc.py b/rpython/rlib/test/test_rgc.py
--- a/rpython/rlib/test/test_rgc.py
+++ b/rpython/rlib/test/test_rgc.py
@@ -229,14 +229,14 @@
     n = rgc.get_rpy_memory_usage(rgc.cast_instance_to_gcref(x1))
     assert n >= 8 and n <= 64
 
-def test_register_custom_gc_trace():
+def test_register_custom_trace_hook():
     TP = lltype.GcStruct('X')
 
     def trace_func():
         xxx # should not be annotated here
     
     def f():
-        rgc.register_custom_gc_trace(TP, trace_func)
+        rgc.register_custom_trace_hook(TP, trace_func)
     
     t, typer, graph = gengraph(f, [])
 


More information about the pypy-commit mailing list