[pypy-commit] pypy gc-incminimark-pinning: added sort() to AddressStack using fijal's work in gc-minimark-pinning

groggi noreply at buildbot.pypy.org
Mon Jun 2 17:23:53 CEST 2014


Author: Gregor Wegberg <code at gregorwegberg.com>
Branch: gc-incminimark-pinning
Changeset: r71815:cc3d72cc6edb
Date: 2014-05-12 16:04 +0200
http://bitbucket.org/pypy/pypy/changeset/cc3d72cc6edb/

Log:	added sort() to AddressStack using fijal's work in gc-minimark-
	pinning

	This was implemented by Maciej Fijalkowski in the gc-minimark-
	pinning branch. See commits:
	* 3ada686cfd218cac6f08e857c9cb4ec43cd68102
	* d4a2fdd9a4ac012675a7a29b10364cb0db079954

diff --git a/rpython/memory/support.py b/rpython/memory/support.py
--- a/rpython/memory/support.py
+++ b/rpython/memory/support.py
@@ -58,7 +58,30 @@
 
     unused_chunks = FreeList()
     cache[chunk_size] = unused_chunks, null_chunk
-    return unused_chunks, null_chunk
+
+    def partition(array, left, right):
+        last_item = array[right]
+        pivot = last_item
+        storeindex = left
+        for i in range(left, right):
+            if array[i] >= pivot:
+                array[i], array[storeindex] = array[storeindex], array[i]
+                storeindex += 1
+        # Move pivot to its final place
+        array[storeindex], array[right] = last_item, array[storeindex]
+        return storeindex
+
+    def quicksort(array, left, right):
+        # sort array[left:right+1] (i.e. bounds included)
+        if right > left:
+            pivotnewindex = partition(array, left, right)
+            quicksort(array, left, pivotnewindex - 1)
+            quicksort(array, pivotnewindex + 1, right)
+
+    def sort_chunk(chunk, size):
+        quicksort(chunk.items, 0, size - 1)
+        
+    return unused_chunks, null_chunk, sort_chunk
 
 
 def get_address_stack(chunk_size=DEFAULT_CHUNK_SIZE, cache={}):
@@ -67,7 +90,7 @@
     except KeyError:
         pass
 
-    unused_chunks, null_chunk = get_chunk_manager(chunk_size)
+    unused_chunks, null_chunk, sort_chunk = get_chunk_manager(chunk_size)
 
     class AddressStack(object):
         _alloc_flavor_ = "raw"
@@ -174,6 +197,13 @@
                 chunk.items[count] = got
                 got = next
 
+        def sort(self):
+            """Sorts the items in the AddressStack.  They must not be more
+            than one chunk of them.  This results in a **reverse** order,
+            so that the first pop()ped items are the smallest ones."""
+            ll_assert(self.chunk.next == null_chunk, "too big for sorting")
+            sort_chunk(self.chunk, self.used_in_last_chunk)
+
     cache[chunk_size] = AddressStack
     return AddressStack
 
diff --git a/rpython/memory/test/test_support.py b/rpython/memory/test/test_support.py
--- a/rpython/memory/test/test_support.py
+++ b/rpython/memory/test/test_support.py
@@ -3,9 +3,11 @@
 from rpython.memory.support import get_address_deque
 
 from rpython.rtyper.test.test_llinterp import interpret
-from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.rtyper.lltypesystem import lltype, llmemory, llarena
 from rpython.rtyper.lltypesystem.llmemory import raw_malloc, raw_free, NULL
 
+import random
+
 class TestAddressStack(object):
     def test_simple_access(self):
         AddressStack = get_address_stack()
@@ -106,6 +108,23 @@
             assert b == a
             assert ll.length() == i
 
+    def test_sort(self):
+        AddressStack = get_address_stack(chunk_size=15)
+        lla = llarena.arena_malloc(10, 2)
+        addrs = [lla + i for i in range(10)]
+        for _ in range(13):
+            ll = AddressStack()
+            addr_copy = addrs[:]
+            random.shuffle(addr_copy)
+            for i in addr_copy:
+                ll.append(i)
+            ll.sort()
+            expected = range(10)
+            for i in expected:
+                a = ll.pop()
+                assert a == addrs[i]
+
+
 
 class TestAddressDeque:
     def test_big_access(self):


More information about the pypy-commit mailing list