[pypy-svn] r24539 - in pypy/dist/pypy/rpython/memory: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Mar 18 19:14:30 CET 2006


Author: cfbolz
Date: Sat Mar 18 19:14:28 2006
New Revision: 24539

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/support.py
   pypy/dist/pypy/rpython/memory/test/test_gc.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_support.py
Log:
make the linked list implementation less braindead: don't allocate a cell of 8
byte for every append. use bigger chunks and also reuse them. This made some
changes necessary: Fix the deferred refcounting, because it inspected the
linked list directly in a non-valid way.  Reset the FreeList in some tests,
because the annotator tries to make a pbc out of it, which is a bad idea, since
it contains non-NULL address constants.


Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Sat Mar 18 19:14:28 2006
@@ -387,15 +387,15 @@
         else:
             self.collecting = True
         roots = self.get_roots()
-        curr = roots.first
-        while 1:
-            root = curr.address[1]
+        roots_copy = AddressLinkedList()
+        curr = roots.pop()
+        while curr != NULL:
 ##             print "root", root, root.address[0]
 ##             assert self.refcount(root.address[0]) >= 0, "refcount negative"
-            self.incref(root.address[0])
-            if curr.address[0] == NULL:
-                break
-            curr = curr.address[0]
+            self.incref(curr.address[0])
+            roots_copy.append(curr)
+            curr = roots.pop()
+        roots = roots_copy
         dealloc_list = AddressLinkedList()
         self.length_zero_ref_counts = 0
         while 1:

Modified: pypy/dist/pypy/rpython/memory/support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/support.py	(original)
+++ pypy/dist/pypy/rpython/memory/support.py	Sat Mar 18 19:14:28 2006
@@ -5,31 +5,59 @@
 
 INT_SIZE = sizeof(lltype.Signed)
 
+CHUNK_SIZE = 30
+
+class FreeList(object):
+    _alloc_flavor_ = "raw"
+
+    def __init__(self, size):
+        self.free_list = NULL
+        self.size = size
+
+    def get(self):
+        if self.free_list == NULL:
+            return raw_malloc(self.size * INT_SIZE)
+        result = self.free_list
+        self.free_list = result.address[0]
+        return result
+
+    def put(self, chunk):
+        chunk.address[0] = self.free_list
+        self.free_list = chunk
+
 class AddressLinkedList(object):
     _alloc_flavor_ = "raw"
+    
+    unused_chunks = FreeList(CHUNK_SIZE + 2)
+    
     def __init__(self):
-        self.first = NULL
-        self.last = NULL
+        self.chunk = NULL
 
     def append(self, addr):
         if addr == NULL:
             return
-        new = raw_malloc(2 * INT_SIZE)
-        if self.first == NULL:
-            self.first = new
-        else:
-            self.last.address[0] = new
-        self.last = new
-        new.address[0] = NULL
-        new.address[1] = addr
+        if self.chunk == NULL or self.chunk.signed[1] == CHUNK_SIZE:
+            new = AddressLinkedList.unused_chunks.get()
+            new.address[0] = self.chunk
+            new.signed[1] = 0
+            self.chunk = new
+        used_chunks = self.chunk.signed[1]
+        self.chunk.signed[1] += 1
+        self.chunk.address[used_chunks + 2] = addr
         
     def pop(self):
-        if self.first == NULL:
-            return NULL
-        result = self.first.address[1]
-        next = self.first.address[0]
-        raw_free(self.first)
-        self.first = next
+        used_chunks = self.chunk.signed[1]
+        if used_chunks == 0:
+            old = self.chunk
+            previous = old.address[0]
+            if previous == NULL:
+                return NULL
+            self.chunk = previous
+            AddressLinkedList.unused_chunks.put(old)
+            used_chunks = self.chunk.signed[1]
+        result = self.chunk.address[used_chunks + 1]
+        self.chunk.address[used_chunks + 1] = NULL
+        self.chunk.signed[1] = used_chunks - 1
         return result
 
     def free(self):

Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gc.py	Sat Mar 18 19:14:28 2006
@@ -6,7 +6,7 @@
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.rpython.memory.gc import GCError, MarkSweepGC, SemiSpaceGC
 from pypy.rpython.memory.gc import DeferredRefcountingGC, DummyGC
-from pypy.rpython.memory.support import AddressLinkedList, INT_SIZE
+from pypy.rpython.memory.support import AddressLinkedList, INT_SIZE, CHUNK_SIZE, FreeList
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL
 from pypy.rpython.memory.simulator import MemorySimulatorError
 from pypy.rpython.memory import gclltype
@@ -97,6 +97,7 @@
 
 class TestMarkSweepGCRunningOnLLinterp(TestMarkSweepGC):
     def setup_class(cls):
+        AddressLinkedList.unused_chunks = FreeList(CHUNK_SIZE + 2) # 'leaks' but well
         cls.prep_old = gclltype.prepare_graphs_and_create_gc
         gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
     def teardown_class(cls):
@@ -111,6 +112,7 @@
 
 class TestSemiSpaceGCRunningOnLLinterp(TestMarkSweepGC):
     def setup_class(cls):
+        AddressLinkedList.unused_chunks = FreeList(CHUNK_SIZE + 2) # 'leaks' but well
         cls.prep_old = gclltype.prepare_graphs_and_create_gc
         gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
         gclltype.use_gc = SemiSpaceGC
@@ -130,6 +132,7 @@
 
 class TestDeferredRefcountingGCRunningOnLLinterp(TestMarkSweepGC):
     def setup_class(cls):
+        AddressLinkedList.unused_chunks = FreeList(CHUNK_SIZE + 2) # 'leaks' but well
         cls.prep_old = gclltype.prepare_graphs_and_create_gc
         gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
         gclltype.use_gc = DeferredRefcountingGC
@@ -148,6 +151,7 @@
 
 class TestDummyGCRunningOnLLinterp(TestMarkSweepGC):
     def setup_class(cls):
+        AddressLinkedList.unused_chunks = FreeList(CHUNK_SIZE + 2) # 'leaks' but well
         cls.prep_old = gclltype.prepare_graphs_and_create_gc
         gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
         gclltype.use_gc = DummyGC

Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py	Sat Mar 18 19:14:28 2006
@@ -1,4 +1,4 @@
-from pypy.rpython.memory import gctransform
+from pypy.rpython.memory import gctransform, support
 from pypy.objspace.flow.model import c_last_exception, Variable
 from pypy.rpython.memory.gctransform import var_needsgc, var_ispyobj
 from pypy.translator.translator import TranslationContext, graphof
@@ -620,6 +620,7 @@
 # tests for FrameworkGCTransformer
 
 def test_framework_simple():
+    support.AddressLinkedList.unused_chunks = support.FreeList(support.CHUNK_SIZE + 2) # 'leaks' but well
     def g(x):
         return x + 1
     class A(object):

Modified: pypy/dist/pypy/rpython/memory/test/test_support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_support.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_support.py	Sat Mar 18 19:14:28 2006
@@ -1,5 +1,5 @@
 from pypy.rpython.objectmodel import free_non_gc_object
-from pypy.rpython.memory.support import AddressLinkedList
+from pypy.rpython.memory.support import AddressLinkedList, FreeList, CHUNK_SIZE
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL
 from pypy.rpython.memory.test.test_llinterpsim import interpret
 
@@ -11,11 +11,11 @@
         ll.append(addr + 1)
         ll.append(addr + 2)
         a = ll.pop()
-        assert a == addr
+        assert a - addr == 2
         a = ll.pop()
         assert a - addr == 1
         a = ll.pop()
-        assert a - addr == 2
+        assert a == addr
         assert ll.pop() == NULL
         assert ll.pop() == NULL
         ll.append(addr)
@@ -28,6 +28,25 @@
         ll.free()
         free_non_gc_object(ll)
         raw_free(addr)
+
+    def test_big_access(self):
+        addr = raw_malloc(1)
+        ll = AddressLinkedList()
+        for i in range(1000):
+            print i
+            ll.append(addr + i)
+        for i in range(1000)[::-1]:
+            a = ll.pop()
+            assert a - addr == i
+        for i in range(1000):
+            print i
+            ll.append(addr + i)
+        for i in range(1000)[::-1]:
+            a = ll.pop()
+            assert a - addr == i
+        ll.free()
+        free_non_gc_object(ll)
+        raw_free(addr)
         
 def test_linked_list_annotate():
     def f():
@@ -37,14 +56,24 @@
         ll.append(addr + 1)
         ll.append(addr + 2)
         a = ll.pop()
-        res = a == addr
+        res = (a - addr == 2)
         a = ll.pop()
         res = res and (a - addr == 1)
         a = ll.pop()
-        res = res and (a - addr == 2)
+        res = res and a == addr
         res = res and (ll.pop() == NULL)
         res = res and (ll.pop() == NULL)
         ll.append(addr)
+        for i in range(100):
+            ll.append(addr + i)
+        for i in range(99, -1, -1):
+            a = ll.pop()
+            res = res and (a - addr == i)
+        for i in range(100):
+            ll.append(addr + i)
+        for i in range(99, -1, -1):
+            a = ll.pop()
+            res = res and (a - addr == i)
         ll.free()
         free_non_gc_object(ll)
         ll = AddressLinkedList()
@@ -59,5 +88,8 @@
 ##     res = a.build_types(f, [])
 ##     a.translator.specialize()
 ##     a.translator.view()
+    assert f()
+    # grumpf: make sure that we don't get a polluted class attribute
+    AddressLinkedList.unused_chunks = FreeList(CHUNK_SIZE + 2)
     res = interpret(f, [])
     assert res



More information about the Pypy-commit mailing list