[pypy-commit] pypy gc-incminimark-pinning: Merge gc-incminimark-pinning-countlimit into gc-incminimark-pinning.
groggi
noreply at buildbot.pypy.org
Mon Jun 2 17:24:56 CEST 2014
Author: Gregor Wegberg <code at gregorwegberg.com>
Branch: gc-incminimark-pinning
Changeset: r71865:d72628c24e5e
Date: 2014-05-30 17:05 +0200
http://bitbucket.org/pypy/pypy/changeset/d72628c24e5e/
Log: Merge gc-incminimark-pinning-countlimit into gc-incminimark-pinning.
We have to limit the amount of pinned objects by the number of
pinned objects as AddressStack does not support sorting over
multiple chunks!
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -256,6 +256,11 @@
# so we trade it by cleaning it bit-by-bit, as we progress through
# nursery. Has to fit at least one large object
"nursery_cleanup": 32768 * WORD,
+
+ # Number of objects that are allowed to be pinned in the nursery
+ # at the same time. Must be lesser than or equal to the chunk size
+ # of an AddressStack.
+ "max_number_of_pinned_objects": 100,
}
def __init__(self, config,
@@ -268,6 +273,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):
@@ -284,6 +290,7 @@
self.max_heap_size = 0.0
self.max_heap_size_already_raised = False
self.max_delta = float(r_uint(-1))
+ self.max_number_of_pinned_objects = max_number_of_pinned_objects
#
self.card_page_indices = card_page_indices
if self.card_page_indices > 0:
@@ -965,6 +972,8 @@
# Reason: It would be possible that the first caller unpins
# while the second caller thinks it's still pinned.
return False
+ if self.pinned_objects_in_nursery >= self.max_number_of_pinned_objects:
+ return False
self.header(obj).tid |= GCFLAG_PINNED
self.pinned_objects_in_nursery += 1
@@ -979,7 +988,6 @@
self.header(obj).tid &= ~GCFLAG_PINNED
self.pinned_objects_in_nursery -= 1
-
def shrink_array(self, obj, smallerlength):
#
# Only objects in the nursery can be "resized". Resizing them
diff --git a/rpython/memory/gc/test/test_object_pinning.py b/rpython/memory/gc/test/test_object_pinning.py
--- a/rpython/memory/gc/test/test_object_pinning.py
+++ b/rpython/memory/gc/test/test_object_pinning.py
@@ -33,6 +33,7 @@
# XXX test with multiple mallocs, and only part of them is pinned
+
class TestIncminimark(PinningGCTest):
from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass
@@ -213,6 +214,50 @@
py.test.raises(Exception, self.malloc, S)
- # XXX test/define what happens if we try to pin an object that is too
- # big for the nursery and will be raw-malloc'ed.
+class TestIncminimarkFewPinnedObjects(BaseDirectGCTest):
+ from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass
+ GC_PARAMS = {'max_number_of_pinned_objects': 5
+ }
+
+ def test_pinning_limit(self):
+ for instance_nr in xrange(self.GC_PARAMS['max_number_of_pinned_objects']):
+ ptr = self.malloc(S)
+ adr = llmemory.cast_ptr_to_adr(ptr)
+ ptr.someInt = 100 + instance_nr
+ self.stackroots.append(ptr)
+ self.gc.pin(adr)
+ #
+ # now we reached the maximum amount of pinned objects
+ ptr = self.malloc(S)
+ adr = llmemory.cast_ptr_to_adr(ptr)
+ self.stackroots.append(ptr)
+ assert not self.gc.pin(adr)
+
+
+class TestIncminimarkManyPinnedObjects(BaseDirectGCTest):
+ from rpython.memory.gc.incminimark import IncrementalMiniMarkGC as GCClass
+
+ GC_PARAMS_PLENTY_PINNED_OBJECTS = {'max_number_of_pinned_objects': 50
+ }
+
+ def get_max_nursery_objects(self, TYPE):
+ typeid = self.get_type_id(TYPE)
+ size = self.gc.fixed_size(typeid) + self.gc.gcheaderbuilder.size_gc_header
+ raw_size = llmemory.raw_malloc_usage(size)
+ return self.gc.nursery_size // raw_size
+
+ def test_full_pinned_nursery_pin_fail(self):
+ object_mallocs = self.get_max_nursery_objects(S)
+ # just to be sure we do not run into the limit as we test not the limiter
+ # but rather the case of a nursery full with pinned objects.
+ assert object_mallocs < self.gc.max_number_of_pinned_objects
+ for instance_nr in xrange(object_mallocs):
+ ptr = self.malloc(S)
+ adr = llmemory.cast_ptr_to_adr(ptr)
+ ptr.someInt = 100 + instance_nr
+ self.stackroots.append(ptr)
+ self.gc.pin(adr)
+ #
+ # nursery should be full now, at least no space for another `S`. Next malloc should fail.
+ py.test.raises(Exception, self.malloc, S)
More information about the pypy-commit
mailing list