/* freeelist of fragment structures */
static SgenFragment *fragment_freelist = NULL;
-/* Allocator cursors */
-static char *nursery_last_pinned_end = NULL;
-
char *sgen_nursery_start;
char *sgen_nursery_end;
/* good sizes are 512KB-1MB: larger ones increase a lot memzeroing time */
-size_t sgen_nursery_size = (1 << 22);
-/* The number of trailing 0 bits in sgen_nursery_size */
-int sgen_nursery_bits = 22;
+size_t sgen_nursery_size;
+/*
+ * Maximum size that we can resize the nursery to.
+ * If sgen_nursery_default_size == sgen_nursery_max_size then we are not
+ * dynamically resizing the nursery
+ */
+size_t sgen_nursery_max_size;
+size_t sgen_nursery_min_size;
+/* The number of trailing 0 bits in sgen_nursery_max_size */
+int sgen_nursery_bits;
+
char *sgen_space_bitmap;
size_t sgen_space_bitmap_size;
char *p = frag->fragment_next;
char *end = p + size;
- if (end > frag->fragment_end)
+ if (end > frag->fragment_end || end > (sgen_nursery_start + sgen_nursery_size))
return NULL;
/* p = frag->fragment_next must happen before */
restart:
for (frag = (SgenFragment *)unmask (allocator->alloc_head); unmask (frag); frag = (SgenFragment *)unmask (frag->next)) {
+ size_t frag_size = frag->fragment_end - frag->fragment_next;
+
+ if (frag->fragment_next >= (sgen_nursery_start + sgen_nursery_size))
+ continue;
+
HEAVY_STAT (++stat_alloc_iterations);
- if (size <= (size_t)(frag->fragment_end - frag->fragment_next)) {
+ if (size <= frag_size) {
void *p = par_alloc_from_fragment (allocator, frag, size);
if (!p) {
HEAVY_STAT (++stat_alloc_retries);
return NULL;
}
-void*
-sgen_fragment_allocator_serial_alloc (SgenFragmentAllocator *allocator, size_t size)
-{
- SgenFragment *frag;
- SgenFragment **previous;
-#ifdef NALLOC_DEBUG
- InterlockedIncrement (&alloc_count);
-#endif
-
- previous = &allocator->alloc_head;
-
- for (frag = *previous; frag; frag = *previous) {
- char *p = (char *)serial_alloc_from_fragment (previous, frag, size);
-
- HEAVY_STAT (++stat_alloc_iterations);
-
- if (p) {
-#ifdef NALLOC_DEBUG
- add_alloc_record (p, size, FIXED_ALLOC);
-#endif
- return p;
- }
- previous = &frag->next;
- }
- return NULL;
-}
-
void*
sgen_fragment_allocator_serial_range_alloc (SgenFragmentAllocator *allocator, size_t desired_size, size_t minimum_size, size_t *out_alloc_size)
{
for (frag = (SgenFragment *)unmask (allocator->alloc_head); frag; frag = (SgenFragment *)unmask (frag->next)) {
size_t frag_size = frag->fragment_end - frag->fragment_next;
+ if (frag->fragment_next >= (sgen_nursery_start + sgen_nursery_size))
+ continue;
+
HEAVY_STAT (++stat_alloc_range_iterations);
if (desired_size <= frag_size) {
if (min_frag) {
void *p;
- size_t frag_size;
+ size_t frag_size = min_frag->fragment_end - min_frag->fragment_next;
- frag_size = min_frag->fragment_end - min_frag->fragment_next;
if (frag_size < minimum_size)
goto restart;
allocator->region_head = allocator->alloc_head = prev;
}
+/*
+ * We split fragments at the border of the current nursery limit. When we
+ * allocate from the nursery we only consider fragments that start in the
+ * current nursery section. We build fragments for the entire nursery in
+ * order to facilitate scanning it for objects (adding a nursery frag also
+ * marks a region in the nursery as being free)
+ */
+static void
+add_nursery_frag_checks (SgenFragmentAllocator *allocator, char *frag_start, char *frag_end)
+{
+ char *nursery_limit = sgen_nursery_start + sgen_nursery_size;
+
+ if (frag_start < nursery_limit && frag_end > nursery_limit) {
+ add_nursery_frag (allocator, nursery_limit - frag_start, frag_start, nursery_limit);
+ add_nursery_frag (allocator, frag_end - nursery_limit, nursery_limit, frag_end);
+ } else {
+ add_nursery_frag (allocator, frag_end - frag_start, frag_start, frag_end);
+ }
+}
+
mword
sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpin_queue)
{
g_assert (frag_size >= 0);
g_assert (size > 0);
if (frag_size && size)
- add_nursery_frag (&mutator_allocator, frag_size, frag_start, frag_end);
+ add_nursery_frag_checks (&mutator_allocator, frag_start, frag_end);
frag_size = size;
#ifdef NALLOC_DEBUG
frag_start = frag_end + frag_size;
}
- nursery_last_pinned_end = frag_start;
frag_end = sgen_nursery_end;
frag_size = frag_end - frag_start;
if (frag_size)
- add_nursery_frag (&mutator_allocator, frag_size, frag_start, frag_end);
+ add_nursery_frag_checks (&mutator_allocator, frag_start, frag_end);
/* Now it's safe to release the fragments exclude list. */
sgen_minor_collector.build_fragments_release_exclude_head ();
return fragment_total;
}
-char *
-sgen_nursery_alloc_get_upper_alloc_bound (void)
-{
- /*FIXME we need to calculate the collector upper bound as well, but this must be done in the previous GC. */
- return sgen_nursery_end;
-}
-
/*** Nursery memory allocation ***/
void
sgen_nursery_retire_region (void *address, ptrdiff_t size)
}
void
-sgen_nursery_allocator_set_nursery_bounds (char *start, char *end)
+sgen_nursery_allocator_set_nursery_bounds (char *start, size_t min_size, size_t max_size)
{
sgen_nursery_start = start;
- sgen_nursery_end = end;
+ sgen_nursery_end = start + max_size;
+
+ sgen_nursery_size = min_size;
+ sgen_nursery_min_size = min_size;
+ sgen_nursery_max_size = max_size;
+
+ sgen_nursery_bits = 0;
+ while (ONE_P << (++ sgen_nursery_bits) != sgen_nursery_max_size)
+ ;
/*
* This will not divide evenly for tiny nurseries (<4kb), so we make sure to be on
* the right side of things and round up. We could just do a MIN(1,x) instead,
* since the nursery size must be a power of 2.
*/
- sgen_space_bitmap_size = (end - start + SGEN_TO_SPACE_GRANULE_IN_BYTES * 8 - 1) / (SGEN_TO_SPACE_GRANULE_IN_BYTES * 8);
+ sgen_space_bitmap_size = (sgen_nursery_end - sgen_nursery_start + SGEN_TO_SPACE_GRANULE_IN_BYTES * 8 - 1) / (SGEN_TO_SPACE_GRANULE_IN_BYTES * 8);
sgen_space_bitmap = (char *)g_malloc0 (sgen_space_bitmap_size);
/* Setup the single first large fragment */
- sgen_minor_collector.init_nursery (&mutator_allocator, start, end);
+ sgen_minor_collector.init_nursery (&mutator_allocator, sgen_nursery_start, sgen_nursery_end);
}
+void
+sgen_resize_nursery (gboolean need_shrink)
+{
+ size_t major_size;
+
+ if (sgen_nursery_min_size == sgen_nursery_max_size)
+ return;
+
+ major_size = major_collector.get_num_major_sections () * major_collector.section_size + los_memory_usage;
+ /*
+ * We attempt to use a larger nursery size, as long as it doesn't
+ * exceed a certain percentage of the major heap.
+ *
+ * FIXME
+ * Commit memory when expanding and release it when shrinking (which
+ * would only be possible if there aren't any pinned objects in the
+ * section).
+ */
+ if ((sgen_nursery_size * 2) < (major_size / SGEN_DEFAULT_ALLOWANCE_NURSERY_SIZE_RATIO) &&
+ (sgen_nursery_size * 2) <= sgen_nursery_max_size && !need_shrink) {
+ if ((nursery_section->end_data - nursery_section->data) == sgen_nursery_size)
+ nursery_section->end_data += sgen_nursery_size;
+ sgen_nursery_size *= 2;
+ } else if ((sgen_nursery_size > (major_size / SGEN_DEFAULT_ALLOWANCE_NURSERY_SIZE_RATIO) || need_shrink) &&
+ (sgen_nursery_size / 2) >= sgen_nursery_min_size) {
+ sgen_nursery_size /= 2;
+ }
+}
+
+
#endif