Author: Armin Rigo <[email protected]>
Branch: concurrent-marksweep
Changeset: r47926:1ff0ad13030d
Date: 2011-10-10 19:19 +0200
http://bitbucket.org/pypy/pypy/changeset/1ff0ad13030d/

Log:    Support for weakrefs.

diff --git a/pypy/rpython/memory/gc/concurrentms.py 
b/pypy/rpython/memory/gc/concurrentms.py
--- a/pypy/rpython/memory/gc/concurrentms.py
+++ b/pypy/rpython/memory/gc/concurrentms.py
@@ -199,7 +199,7 @@
     def malloc_fixedsize_clear(self, typeid, size,
                                needs_finalizer=False, contains_weakptr=False):
         assert not needs_finalizer  # XXX
-        assert not contains_weakptr # XXX
+        # contains_weakptr: detected during collection
         size_gc_header = self.gcheaderbuilder.size_gc_header
         totalsize = size_gc_header + size
         rawtotalsize = raw_malloc_usage(totalsize)
@@ -733,11 +733,14 @@
         self.gray_objects.append(root.address[0])
 
     def collector_sweep(self):
-        self._collect_sweep_large_objects()
         n = 1
         while n < self.pagelists_length:
             self._collect_sweep_pages(n)
             n += 1
+        # do this *after* the other one, so that objects are not free'd
+        # before we get a chance to inspect if they contain objects that
+        # are still alive (needed for weakrefs)
+        self._collect_sweep_large_objects()
 
     def _collect_sweep_large_objects(self):
         block = self.collect_pages[0]
@@ -774,7 +777,8 @@
         object_size = n << WORD_POWER_2
         linked_list = self.NULL
         first_loc_in_linked_list = self.NULL
-        nonmarked = self.other_mark(self.current_mark)
+        marked = self.current_mark
+        nonmarked = self.other_mark(marked)
         while page != self.NULL:
             i = self.page_size - object_size
             limit = raw_malloc_usage(self.HDRSIZE)
@@ -783,8 +787,9 @@
             while i >= limit:
                 adr = pageadr + i
                 hdr = llmemory.cast_adr_to_ptr(adr, self.HDRPTR)
+                mark = hdr.tid & 0xFF
                 #
-                if (hdr.tid & 0xFF) == nonmarked:
+                if mark == nonmarked:
                     # the location contains really an object (and is not just
                     # part of a linked list of free locations), and moreover
                     # the object is still not marked.  Free it by inserting
@@ -805,6 +810,26 @@
                     llarena.arena_reset(adr + size_of_int,
                                         object_size - size_of_int, 2)
                 #
+                elif mark == marked:
+                    # the location contains really an object, which is marked.
+                    # check the typeid to see if it's a weakref.  XXX could
+                    # be faster
+                    tid = hdr.tid
+                    type_id = llop.extract_high_ushort(llgroup.HALFWORD, tid)
+                    wroffset = self.weakpointer_offset(type_id)
+                    if wroffset >= 0:
+                        size_gc_header = self.gcheaderbuilder.size_gc_header
+                        obj = adr + size_gc_header
+                        pointing_to = (obj + wroffset).address[0]
+                        if pointing_to != llmemory.NULL:
+                            pt_adr = pointing_to - size_gc_header
+                            pt_hdr = llmemory.cast_adr_to_ptr(pt_adr,
+                                                              self.HDRPTR)
+                            if (pt_hdr.tid & 0xFF) == nonmarked:
+                                # this weakref points to an object that is 
still
+                                # not marked, so clear it
+                                (obj + wroffset).address[0] = llmemory.NULL
+                #
                 i -= object_size
             #
             page = self.cast_int_to_hdrptr(page.tid)
diff --git a/pypy/rpython/memory/test/test_gc.py 
b/pypy/rpython/memory/test/test_gc.py
--- a/pypy/rpython/memory/test/test_gc.py
+++ b/pypy/rpython/memory/test/test_gc.py
@@ -931,20 +931,3 @@
 class TestMostlyConcurrentMarkSweepGC(GCTest):
     from pypy.rpython.memory.gc.concurrentms \
             import MostlyConcurrentMarkSweepGC as GCClass
-
-    def test_finalizer_order(self):
-        py.test.skip("in-progress")
-    def test_from_objwithfinalizer_to_youngobj(self):
-        py.test.skip("in-progress")
-    def test_finalizer(self):
-        py.test.skip("in-progress")
-    def test_finalizer_calls_malloc(self):
-        py.test.skip("in-progress")
-    def test_finalizer_calls_collect(self):
-        py.test.skip("in-progress")
-    def test_finalizer_resurrects(self):
-        py.test.skip("in-progress")
-    def test_weakref(self):
-        py.test.skip("in-progress")
-    def test_weakref_to_object_with_finalizer(self):
-        py.test.skip("in-progress")
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to