Author: Armin Rigo <[email protected]>
Branch: gc-del-3
Changeset: r84132:585ea21d4f7f
Date: 2016-05-02 19:31 +0200
http://bitbucket.org/pypy/pypy/changeset/585ea21d4f7f/

Log:    in-progress

diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -1565,6 +1565,13 @@
             self.header(shadow).tid |= GCFLAG_VISITED
             new_shadow_object_dict.setitem(obj, shadow)
 
+    def register_finalizer(self, fq_index, gcobj):
+        from rpython.rtyper.lltypesystem import rffi
+        obj = llmemory.cast_ptr_to_adr(gcobj)
+        self.probably_young_objects_with_finalizers.append(obj)
+        fq_index = rffi.cast(llmemory.Address, fq_index)
+        self.probably_young_objects_with_finalizers.append(fq_index)
+
     # ----------
     # Nursery collection
 
@@ -2617,12 +2624,12 @@
     def deal_with_young_objects_with_finalizers(self):
         while self.probably_young_objects_with_finalizers.non_empty():
             obj = self.probably_young_objects_with_finalizers.popleft()
-            fin_nr = self.probably_young_objects_with_finalizers.popleft()
-            singleaddr.address[0] = obj
-            self._trace_drag_out1(singleaddr)
-            obj = singleaddr.address[0]
-            self.old_objects_with_light_finalizers.append(obj)
-            self.old_objects_with_light_finalizers.append(fin_nr)
+            fq_nr = self.probably_young_objects_with_finalizers.popleft()
+            self.singleaddr.address[0] = obj
+            self._trace_drag_out1(self.singleaddr)
+            obj = self.singleaddr.address[0]
+            self.old_objects_with_finalizers.append(obj)
+            self.old_objects_with_finalizers.append(fq_nr)
 
     def deal_with_objects_with_finalizers(self):
         # Walk over list of objects with finalizers.
@@ -2635,14 +2642,17 @@
         marked = self.AddressDeque()
         pending = self.AddressStack()
         self.tmpstack = self.AddressStack()
-        while self.objects_with_finalizers.non_empty():
-            x = self.objects_with_finalizers.popleft()
+        while self.old_objects_with_finalizers.non_empty():
+            x = self.old_objects_with_finalizers.popleft()
+            fq_nr = self.old_objects_with_finalizers.popleft()
             ll_assert(self._finalization_state(x) != 1,
                       "bad finalization state 1")
             if self.header(x).tid & GCFLAG_VISITED:
                 new_with_finalizer.append(x)
+                new_with_finalizer.append(fq_nr)
                 continue
             marked.append(x)
+            marked.append(fq_nr)
             pending.append(x)
             while pending.non_empty():
                 y = pending.pop()
@@ -2662,9 +2672,11 @@
 
         while marked.non_empty():
             x = marked.popleft()
+            fq_nr = marked.popleft()
             state = self._finalization_state(x)
             ll_assert(state >= 2, "unexpected finalization state < 2")
             if state == 2:
+                # XXX use fq_nr here
                 self.run_finalizers.append(x)
                 # we must also fix the state from 2 to 3 here, otherwise
                 # we leave the GCFLAG_FINALIZATION_ORDERING bit behind
@@ -2672,12 +2684,13 @@
                 self._recursively_bump_finalization_state_from_2_to_3(x)
             else:
                 new_with_finalizer.append(x)
+                new_with_finalizer.append(fq_nr)
 
         self.tmpstack.delete()
         pending.delete()
         marked.delete()
-        self.objects_with_finalizers.delete()
-        self.objects_with_finalizers = new_with_finalizer
+        self.old_objects_with_finalizers.delete()
+        self.old_objects_with_finalizers = new_with_finalizer
 
     def _append_if_nonnull(pointer, stack):
         stack.append(pointer.address[0])
diff --git a/rpython/memory/gcwrapper.py b/rpython/memory/gcwrapper.py
--- a/rpython/memory/gcwrapper.py
+++ b/rpython/memory/gcwrapper.py
@@ -4,6 +4,7 @@
 from rpython.rtyper.annlowlevel import llhelper
 from rpython.memory import gctypelayout
 from rpython.flowspace.model import Constant
+from rpython.rlib import rgc
 
 
 class GCManagedHeap(object):
@@ -20,6 +21,7 @@
         self.llinterp = llinterp
         self.prepare_graphs(flowgraphs)
         self.gc.setup()
+        self.finalizer_queues = {}
         self.has_write_barrier_from_array = hasattr(self.gc,
                                                     'write_barrier_from_array')
 
@@ -187,6 +189,20 @@
     def thread_run(self):
         pass
 
+    def get_finalizer_queue_index(self, fq_tag):
+        assert fq_tag.expr == 'FinalizerQueue TAG'
+        fq = fq_tag.default
+        return self.finalizer_queues.setdefault(fq, len(self.finalizer_queues))
+
+    def gc_fq_next_dead(self, fq_tag):
+        index = self.get_finalizer_queue_index(fq_tag)
+        xxx
+
+    def gc_fq_register(self, fq_tag, ptr):
+        index = self.get_finalizer_queue_index(fq_tag)
+        ptr = lltype.cast_opaque_ptr(llmemory.GCREF, ptr)
+        self.gc.register_finalizer(index, ptr)
+
 # ____________________________________________________________
 
 class LLInterpRootWalker:
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
@@ -128,7 +128,7 @@
         assert res == concat(100)
         #assert simulator.current_size - curr < 16000 * INT_SIZE / 4
 
-    def test_finalizer(self):
+    def test_destructor(self):
         class B(object):
             pass
         b = B()
@@ -152,6 +152,36 @@
         res = self.interpret(f, [5])
         assert res == 6
 
+    def test_finalizer(self):
+        class B(object):
+            pass
+        b = B()
+        b.nextid = 0
+        b.num_deleted = 0
+        class A(object):
+            def __init__(self):
+                self.id = b.nextid
+                b.nextid += 1
+                fq.register_finalizer(self)
+        class FQ(rgc.FinalizerQueue):
+            Class = A
+            def finalizer_trigger(self):
+                while self.next_dead() is not None:
+                    b.num_deleted += 1
+        fq = FQ()
+        def f(x):
+            a = A()
+            i = 0
+            while i < x:
+                i += 1
+                a = A()
+            a = None
+            llop.gc__collect(lltype.Void)
+            llop.gc__collect(lltype.Void)
+            return b.num_deleted
+        res = self.interpret(f, [5])
+        assert res == 6
+
     def test_finalizer_calls_malloc(self):
         class B(object):
             pass
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -5,6 +5,7 @@
 
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import we_are_translated, enforceargs, specialize
+from rpython.rlib.objectmodel import CDefinedIntSymbolic
 from rpython.rtyper.extregistry import ExtRegistryEntry
 from rpython.rtyper.lltypesystem import lltype, llmemory
 
@@ -389,7 +390,7 @@
             from rpython.rtyper.lltypesystem.lloperation import llop
             from rpython.rtyper.rclass import OBJECTPTR
             from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance
-            ptr = llop.gc_fq_next_dead(OBJECTPTR, self)
+            ptr = llop.gc_fq_next_dead(OBJECTPTR, self._get_tag())
             return cast_base_ptr_to_instance(self.Class, ptr)
         try:
             return self._queue.popleft()
@@ -404,9 +405,16 @@
             from rpython.rtyper.rclass import OBJECTPTR
             from rpython.rtyper.annlowlevel import cast_instance_to_base_ptr
             ptr = cast_instance_to_base_ptr(obj)
-            llop.gc_fq_register(lltype.Void, self, ptr)
+            llop.gc_fq_register(lltype.Void, self._get_tag(), ptr)
             return
+        else:
+            self._untranslated_register_finalizer(obj)
 
+    @specialize.memo()
+    def _get_tag(self):
+        return CDefinedIntSymbolic('FinalizerQueue TAG', default=self)
+
+    def _untranslated_register_finalizer(self, obj):
         if hasattr(obj, '__enable_del_for_id'):
             return    # already called
 
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -720,6 +720,12 @@
     def op_gc_add_memory_pressure(self, size):
         self.heap.add_memory_pressure(size)
 
+    def op_gc_fq_next_dead(self, fq_tag):
+        return self.heap.gc_fq_next_dead(fq_tag)
+
+    def op_gc_fq_register(self, fq_tag, obj):
+        self.heap.gc_fq_register(fq_tag, obj)
+
     def op_gc_gettypeid(self, obj):
         return lloperation.llop.combine_ushort(lltype.Signed, 
self.heap.gettypeid(obj), 0)
 
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -504,6 +504,8 @@
     'gc_gettypeid'        : LLOp(),
     'gc_gcflag_extra'     : LLOp(),
     'gc_add_memory_pressure': LLOp(),
+    'gc_fq_next_dead'     : LLOp(),
+    'gc_fq_register'      : LLOp(),
 
     'gc_rawrefcount_init':              LLOp(),
     'gc_rawrefcount_create_link_pypy':  LLOp(),
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to