Author: Maciej Fijalkowski <fij...@gmail.com> Branch: gc-minimark-pinning Changeset: r54317:aa6c3180899c Date: 2012-04-12 23:31 +0200 http://bitbucket.org/pypy/pypy/changeset/aa6c3180899c/
Log: pass more of a test and write insert for support. crap ugly diff --git a/pypy/rpython/lltypesystem/llarena.py b/pypy/rpython/lltypesystem/llarena.py --- a/pypy/rpython/lltypesystem/llarena.py +++ b/pypy/rpython/lltypesystem/llarena.py @@ -394,7 +394,7 @@ arena_addr = getfakearenaaddress(arena_addr) assert arena_addr.offset == 0 assert size == arena_addr.arena.nbytes - arena_addr.arena.set_protect(inaccessible) + arena_addr.arena.set_protect(inaccessible) # ____________________________________________________________ # 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 @@ -247,6 +247,8 @@ self.nursery_top = NULL self.debug_tiny_nursery = -1 self.debug_rotating_nurseries = None + self.surviving_pinned_objects = NULL + self.nursery_barriers = NULL # # The ArenaCollection() handles the nonmovable objects allocation. if ArenaCollectionClass is None: @@ -306,7 +308,7 @@ # minor collection. self.nursery_objects_shadows = self.AddressDict() # all pinned objects that were in the nursery *before* last - # minor collect. This is a sorted stack that should be consulted when + # minor collect. This is a sorted deque that should be consulted when # considering next nursery ceiling self.nursery_barriers = self.AddressDeque() @@ -1257,6 +1259,8 @@ # # Before everything else, remove from 'old_objects_pointing_to_young' # the young arrays. + self.nursery_barriers.delete() + self.surviving_pinned_objects = self.AddressStack() if self.young_rawmalloced_objects: self.remove_young_arrays_from_old_objects_pointing_to_young() # @@ -1308,22 +1312,24 @@ # All live nursery objects are out, and the rest dies. Fill # the whole nursery with zero and reset the current nursery pointer. # self.nursery_barriers are *not* freed - # XXX sort the nursery_barriers - new_barriers = self.AddressDeque() + nursery_barriers = self.AddressDeque() prev = self.nursery size_gc_header = self.gcheaderbuilder.size_gc_header - while self.nursery_barriers.non_empty(): - next = self.nursery_barriers.popleft() - llarena.arena_reset(prev, next - prev, 2) + while self.surviving_pinned_objects.non_empty(): + next = self.surviving_pinned_objects.pop() + assert next >= prev + size = llarena.getfakearenaaddress(next) - prev + llarena.arena_reset(prev, size, 2) # clean the visited flag obj = next + size_gc_header self.header(obj).tid &= ~GCFLAG_VISITED - prev = prev + (next - prev) + (size_gc_header + + prev = prev + size + (size_gc_header + self.get_size(obj)) - new_barriers.append(next) + nursery_barriers.append(next) llarena.arena_reset(prev, self.nursery_top - prev, 2) - self.nursery_barriers.delete() - self.nursery_barriers = new_barriers + self.surviving_pinned_objects.delete() + self.surviving_pinned_objects = NULL + self.nursery_barriers = nursery_barriers self.debug_rotate_nursery() self.nursery_free = self.nursery self.nursery_barriers.append(self.nursery + self.nursery_size) @@ -1478,7 +1484,8 @@ hdr.tid |= GCFLAG_VISITED ll_assert(not self.header(obj).tid & GCFLAG_HAS_SHADOW, "support shadow with pinning") ll_assert(not self.header(obj).tid & GCFLAG_HAS_CARDS, "support cards with pinning") - self.nursery_barriers.append(obj - size_gc_header) + self.surviving_pinned_objects.insert( + llarena.getfakearenaaddress(obj - size_gc_header)) return elif self.header(obj).tid & GCFLAG_HAS_SHADOW == 0: # 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 @@ -173,6 +173,47 @@ 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 + cache[chunk_size] = AddressStack return AddressStack 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 @@ -966,5 +966,35 @@ res = self.interpret(f, [10]) assert res == 2 + def test_pinning_collect_2(self): + from pypy.rpython.lltypesystem import llmemory + + TP = lltype.GcStruct('x', ('x', lltype.Signed), ('y', lltype.Signed)) + + def f(i): + e = lltype.malloc(TP) + e.x = 3 + lltype.malloc(TP) + e2 = lltype.malloc(TP) + e2.x = 5 + rgc.pin(e2) + rgc.pin(e) + prev = llmemory.cast_ptr_to_adr(e) + prev2 = llmemory.cast_ptr_to_adr(e2) + for k in range(i): + lltype.malloc(TP) + res = int(llmemory.cast_ptr_to_adr(e) == prev) + res += int(llmemory.cast_ptr_to_adr(e2) == prev2) + rgc.unpin(e) + for k in range(i): + lltype.malloc(TP) + rgc.unpin(e2) + assert e.x == 3 # noone overwrote it + assert e2.x == 5 # noone overwrote it + return res + + res = self.interpret(f, [10]) + assert res == 2 + class TestMiniMarkGCCardMarking(TestMiniMarkGC): GC_PARAMS = {'card_page_indices': 4} 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 @@ -3,7 +3,7 @@ from pypy.rpython.memory.support import get_address_deque from pypy.rpython.test.test_llinterp import interpret -from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free, NULL class TestAddressStack(object): @@ -94,6 +94,26 @@ 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] + class TestAddressDeque: def test_big_access(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit