Author: Maciej Fijalkowski <[email protected]>
Branch: gc-minimark-pinning
Changeset: r54376:3ada686cfd21
Date: 2012-04-15 20:29 +0200
http://bitbucket.org/pypy/pypy/changeset/3ada686cfd21/

Log:    a sorting attempt

diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -1,8 +1,4 @@
 
 * implement limit on no of pinned objects + replace insert with qsort
 
-* use pinning
-
-* make sure objects with shadows work
-
 * implement tracing for pinned objects (check that it works)
\ No newline at end of file
diff --git a/pypy/rpython/lltypesystem/rffi.py 
b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -2,11 +2,11 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem import ll2ctypes
-from pypy.rpython.lltypesystem.llmemory import cast_adr_to_ptr, cast_ptr_to_adr
+from pypy.rpython.lltypesystem.llmemory import cast_ptr_to_adr
 from pypy.rpython.lltypesystem.llmemory import itemoffsetof, raw_memcopy
 from pypy.annotation.model import lltype_to_annotation
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic
+from pypy.rlib.objectmodel import Symbolic, we_are_translated
 from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib import rarithmetic, rgc
 from pypy.rpython.extregistry import ExtRegistryEntry
@@ -14,7 +14,6 @@
 from pypy.rpython.tool.rfficache import platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.annlowlevel import llhelper
-from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, assert_str0
 from pypy.rlib import jit
 from pypy.rpython.lltypesystem import llmemory
@@ -715,14 +714,15 @@
         free_nonmovingbuffer call.
         """
         rgc.pin(data)
-        if rgc.can_move(data):
+        if rgc.can_move(data) or not we_are_translated():
             count = len(data)
             buf = lltype.malloc(TYPEP.TO, count, flavor='raw')
             for i in range(count):
                 buf[i] = data[i]
             return buf
         else:
-            data_start = cast_ptr_to_adr(llstrtype(data)) + \
+            ll_s = llstrtype(data)
+            data_start = cast_ptr_to_adr(ll_s) + \
                 offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0)
             return cast(TYPEP, data_start)
     get_nonmovingbuffer._annenforceargs_ = [strtype]
diff --git a/pypy/rpython/memory/gc/minimark.py 
b/pypy/rpython/memory/gc/minimark.py
--- a/pypy/rpython/memory/gc/minimark.py
+++ b/pypy/rpython/memory/gc/minimark.py
@@ -205,6 +205,10 @@
         # minimal allocated size of the nursery is 2x the following
         # number (by default, at least 132KB on 32-bit and 264KB on 64-bit).
         "large_object": (16384+512)*WORD,
+
+        # number of allowed pinned objects, must be smaller than the size
+        # of one chunk for address stack
+        "max_number_of_pinned_objects": 100,
         }
 
     def __init__(self, config,
@@ -216,6 +220,7 @@
                  major_collection_threshold=2.5,
                  growth_rate_max=2.5,   # for tests
                  card_page_indices=0,
+                 max_number_of_pinned_objects=100,
                  large_object=8*WORD,
                  ArenaCollectionClass=None,
                  **kwds):
@@ -226,6 +231,7 @@
         self.small_request_threshold = small_request_threshold
         self.major_collection_threshold = major_collection_threshold
         self.growth_rate_max = growth_rate_max
+        self.max_number_of_pinned_objects = max_number_of_pinned_objects
         self.num_major_collects = 0
         self.min_heap_size = 0.0
         self.max_heap_size = 0.0
@@ -309,6 +315,7 @@
         # minor collect. This is a sorted deque that should be consulted when
         # considering next nursery ceiling
         self.nursery_barriers = self.AddressDeque()
+        self.pinned_objects_in_nursery = 0
     
         #
         # Allocate a nursery.  In case of auto_nursery_size, start by
@@ -797,9 +804,13 @@
                 not self.header(obj).tid & GCFLAG_PINNED)
 
     def pin(self, obj):
+        if self.pinned_objects_in_nursery >= self.max_number_of_pinned_objects:
+            return
+        self.pinned_objects_in_nursery += 1
         self.header(obj).tid |= GCFLAG_PINNED
 
     def unpin(self, obj):
+        self.pinned_objects_in_nursery -= 1
         self.header(obj).tid &= ~GCFLAG_PINNED
 
     def shrink_array(self, obj, smallerlength):
@@ -1264,6 +1275,8 @@
         # the young arrays.
         self.nursery_barriers.delete()
         self.surviving_pinned_objects = self.AddressStack()
+        self.pinned_objects_in_nursery = 0
+        # we track only surviving objects, don't care about the rest
         if self.young_rawmalloced_objects:
             self.remove_young_arrays_from_old_objects_pointing_to_young()
         #
@@ -1318,6 +1331,7 @@
         nursery_barriers = self.AddressDeque()
         prev = self.nursery
         size_gc_header = self.gcheaderbuilder.size_gc_header
+        self.surviving_pinned_objects.sort()
         while self.surviving_pinned_objects.non_empty():
             next = self.surviving_pinned_objects.pop()
             assert next >= prev
@@ -1501,7 +1515,8 @@
                 return
             hdr.tid |= GCFLAG_VISITED
             ll_assert(not self.header(obj).tid & GCFLAG_HAS_CARDS, "support 
cards with pinning")
-            self.surviving_pinned_objects.insert(
+            self.pinned_objects_in_nursery += 1
+            self.surviving_pinned_objects.append(
                 llarena.getfakearenaaddress(obj - size_gc_header))
             return
             #
diff --git a/pypy/rpython/memory/support.py b/pypy/rpython/memory/support.py
--- a/pypy/rpython/memory/support.py
+++ b/pypy/rpython/memory/support.py
@@ -1,6 +1,5 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rlib.objectmodel import free_non_gc_object, we_are_translated
-from pypy.rlib.rarithmetic import r_uint, LONG_BIT
 from pypy.rlib.debug import ll_assert
 from pypy.tool.identity_dict import identity_dict
 
@@ -59,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={}):
@@ -68,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"
@@ -173,46 +195,9 @@
                 chunk.items[count] = got
                 got = next
 
-        def insert(self, addr):
-            """ Insert addr in the already sorted stack to make sure
-            the smallest one is on top
-            """
-            if self.used_in_last_chunk == 0:
-                self.append(addr)
-                return
-            got = self.pop()
-            read = self.used_in_last_chunk - 1
-            if read == -1 and got <= addr:
-                self.append(addr)
-                self.append(got)
-                return
-            read_chunk = self.chunk
-            self.append(got)
-            if got > addr:
-                self.append(addr)
-                return
-            write = self.used_in_last_chunk
-            if self.used_in_last_chunk == chunk_size:
-                self.enlarge()
-                write = 0
-            self.used_in_last_chunk += 1
-            write_chunk = self.chunk
-            while got < addr and not read_chunk is null_chunk:
-                write_chunk.items[write] = got
-                write -= 1
-                if write < 0:
-                    write_chunk = write_chunk.next
-                    write = chunk_size - 1
-                got = read_chunk.items[read]
-                read -= 1
-                if read < 0:
-                    read_chunk = read_chunk.next
-                    read = chunk_size - 1
-            if got < addr:
-                write_chunk.items[write] = got
-                write_chunk.items[0] = addr
-            else:
-                write_chunk.items[write] = addr
+        def sort(self):
+            ll_assert(self.chunk.next == null_chunk, "too big for sorting")
+            sort_chunk(self.chunk, self.used_in_last_chunk - 1)
 
     cache[chunk_size] = AddressStack
     return AddressStack
diff --git a/pypy/rpython/memory/test/test_support.py 
b/pypy/rpython/memory/test/test_support.py
--- a/pypy/rpython/memory/test/test_support.py
+++ b/pypy/rpython/memory/test/test_support.py
@@ -1,3 +1,5 @@
+
+import random
 from pypy.rlib.objectmodel import free_non_gc_object
 from pypy.rpython.memory.support import get_address_stack
 from pypy.rpython.memory.support import get_address_deque
@@ -94,25 +96,20 @@
             assert a == addrs[i]
         assert not ll.non_empty()
 
-    def test_insert(self):
-        AddressStack = get_address_stack(chunk_size=5)
-        ll = AddressStack()
-        lla = llarena.arena_malloc(10, 2)
-        addrs = [lla + i for i in range(10)]
-        ll.insert(addrs[2])
-        ll.insert(addrs[1])
-        ll.insert(addrs[5])
-        ll.insert(addrs[4])
-        ll.insert(addrs[6])
-        ll.insert(addrs[9])
-        ll.insert(addrs[0])
-        ll.insert(addrs[8])
-        ll.insert(addrs[7])
-        ll.insert(addrs[3])
-        expected = range(10)
-        for i in expected:
-            a = ll.pop()
-            assert a == addrs[i]
+    def test_sort(self):
+        AddressStack = get_address_stack(chunk_size=15)
+        for _ in range(13):
+            ll = AddressStack()
+            lla = llarena.arena_malloc(10, 2)
+            addrs = [lla + i for i in range(10)]
+            random.shuffle(addrs)
+            for i in addrs:
+                ll.append(i)
+            ll.sort()
+            expected = range(10)
+            for i in expected:
+                a = ll.pop()
+                assert a == addrs[i]
 
 
 class TestAddressDeque:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to