Author: Antonio Cuni <anto.c...@gmail.com>
Branch: gc-hooks
Changeset: r94193:ba293bc808ee
Date: 2018-03-31 01:59 +0200
http://bitbucket.org/pypy/pypy/changeset/ba293bc808ee/

Log:    start to add app-level gc hooks; the test pass, but we still need to
        polish stuff a bit

diff --git a/pypy/module/gc/__init__.py b/pypy/module/gc/__init__.py
--- a/pypy/module/gc/__init__.py
+++ b/pypy/module/gc/__init__.py
@@ -34,5 +34,10 @@
                 'get_typeids_z': 'referents.get_typeids_z',
                 'get_typeids_list': 'referents.get_typeids_list',
                 'GcRef': 'referents.W_GcRef',
+                'set_hooks': 'hook.set_hooks',
                 })
         MixedModule.__init__(self, space, w_name)
+
+    def setup_after_space_initialization(self):
+        from pypy.module.gc.hook import gchooks
+        gchooks.setspace(self.space)
diff --git a/pypy/module/gc/hook.py b/pypy/module/gc/hook.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/gc/hook.py
@@ -0,0 +1,54 @@
+from rpython.memory.gc.hook import GcHooks
+from pypy.interpreter.baseobjspace import ObjSpace
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.executioncontext import AsyncAction
+
+class LowLevelGcHooks(GcHooks):
+
+    def setspace(self, space):
+        self.space = space
+        self.hooks = space.fromcache(AppLevelHooks)
+
+    def on_gc_minor(self, total_memory_used, pinned_objects):
+        action = self.hooks.gc_minor
+        action.total_memory_used = total_memory_used
+        action.pinned_objects = pinned_objects
+        action.fire()
+
+    def on_gc_collect_step(self, oldstate, newstate):
+        pass
+
+    def on_gc_collect(self, count, arenas_count_before, arenas_count_after,
+                      arenas_bytes, rawmalloc_bytes_before,
+                      rawmalloc_bytes_after):
+        pass
+
+
+gchooks = LowLevelGcHooks()
+
+class AppLevelHooks(object):
+
+    def __init__(self, space):
+        self.space = space
+        self.gc_minor = GcMinorHookAction(space)
+
+    def set_hooks(self, space, w_on_gc_minor):
+        # XXX: check for None and enable/disable accordingly
+        self.gc_minor.w_callable = w_on_gc_minor
+
+
+class GcMinorHookAction(AsyncAction):
+    w_callable = None
+    total_memory_used = 0
+    pinned_objects = 0
+
+    def perform(self, ec, frame):
+        self.space.call_function(self.w_callable,
+                                 self.space.wrap(self.total_memory_used),
+                                 self.space.wrap(self.pinned_objects))
+
+
+
+
+def set_hooks(space, w_on_gc_minor):
+    space.fromcache(AppLevelHooks).set_hooks(space, w_on_gc_minor)
diff --git a/pypy/module/gc/test/test_hook.py b/pypy/module/gc/test/test_hook.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/gc/test/test_hook.py
@@ -0,0 +1,26 @@
+from pypy.module.gc.hook import gchooks
+from pypy.interpreter.baseobjspace import ObjSpace
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+
+class AppTestGcHooks(object):
+
+    def setup_class(cls):
+        space = cls.space
+
+        @unwrap_spec(ObjSpace, int, int)
+        def fire_gc_minor(space, total_memory_used, pinned_objects):
+            gchooks.fire_gc_minor(total_memory_used, pinned_objects)
+        cls.w_fire_gc_minor = space.wrap(interp2app(fire_gc_minor))
+
+    def test_on_gc_minor(self):
+        import gc
+        lst = []
+        def on_gc_minor(total_memory_used, pinned_objects):
+            lst.append((total_memory_used, pinned_objects))
+        gc.set_hooks(on_gc_minor=on_gc_minor)
+        self.fire_gc_minor(10, 20)
+        self.fire_gc_minor(30, 40)
+        assert lst == [
+            (10, 20),
+            (30, 40),
+            ]
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to