diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2021-09-17 00:08:53 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2021-09-17 00:08:53 +0300 |
commit | 8e01d31bfb9a4cdffdfe952b8e8c1d048d9e1cd3 (patch) | |
tree | a4c156268f62a6e512facf5e829b788f64cfcee2 | |
parent | 33b897fc3c011752686d6fe19f6bd184c0b6e341 (diff) | |
download | bdwgc-8e01d31bfb9a4cdffdfe952b8e8c1d048d9e1cd3.tar.gz |
Remove limit on number of heap sections
GC_heap_sects[] is a dynamic array now with the initial size of
32 elements.
* alloc.c (add_to_heap_inner): Declare old_capacity, old_heap_sects,
new_capacity, new_heap_sects local variables; define INITIAL_HEAP_SECTS
macro; resize GC_heap_sects if it is full instead of abort; recycle
old GC_heap_sects array on resize.
* include/private/gc_priv.h [!MAX_HEAP_SECTS] (MAX_HEAP_SECTS): Do not
define unless Windows or USE_PROC_FOR_LIBRARIES.
* include/private/gc_priv.h (GC_arrays._capacity_heap_sects): Add
field.
* include/private/gc_priv.h (GC_arrays._heap_sects): Change type from
fixed-size array to pointer.
-rw-r--r-- | alloc.c | 46 | ||||
-rw-r--r-- | include/private/gc_priv.h | 7 |
2 files changed, 49 insertions, 4 deletions
@@ -1349,6 +1349,8 @@ static void add_to_heap_inner(struct hblk *p, size_t bytes) { hdr * phdr; word endp; + size_t old_capacity = 0; + void *old_heap_sects = NULL; # ifdef GC_ASSERTIONS unsigned i; # endif @@ -1357,9 +1359,37 @@ static void add_to_heap_inner(struct hblk *p, size_t bytes) GC_ASSERT(bytes % HBLKSIZE == 0); GC_ASSERT(bytes > 0); GC_ASSERT(GC_all_nils != NULL); - if (GC_n_heap_sects >= MAX_HEAP_SECTS) { - ABORT("Too many heap sections: Increase MAXHINCR or MAX_HEAP_SECTS"); + + if (GC_n_heap_sects == GC_capacity_heap_sects) { + /* Allocate new GC_heap_sects with sufficient capacity. */ +# ifndef INITIAL_HEAP_SECTS +# define INITIAL_HEAP_SECTS 32 +# endif + size_t new_capacity = GC_n_heap_sects > 0 ? + (size_t)GC_n_heap_sects * 2 : INITIAL_HEAP_SECTS; + void *new_heap_sects = + GC_scratch_alloc(new_capacity * sizeof(struct HeapSect)); + + if (EXPECT(NULL == new_heap_sects, FALSE)) { + /* Retry with smaller yet sufficient capacity. */ + new_capacity = (size_t)GC_n_heap_sects + INITIAL_HEAP_SECTS; + new_heap_sects = + GC_scratch_alloc(new_capacity * sizeof(struct HeapSect)); + if (NULL == new_heap_sects) + ABORT("Insufficient memory for heap sections"); + } + old_capacity = GC_capacity_heap_sects; + old_heap_sects = GC_heap_sects; + /* Transfer GC_heap_sects contents to the newly allocated array. */ + if (GC_n_heap_sects > 0) + BCOPY(old_heap_sects, new_heap_sects, + GC_n_heap_sects * sizeof(struct HeapSect)); + GC_capacity_heap_sects = new_capacity; + GC_heap_sects = (struct HeapSect *)new_heap_sects; + GC_COND_LOG_PRINTF("Grew heap sections array to %lu elements\n", + (unsigned long)new_capacity); } + while ((word)p <= HBLKSIZE) { /* Can't handle memory near address zero. */ ++p; @@ -1421,6 +1451,18 @@ static void add_to_heap_inner(struct hblk *p, size_t bytes) if ((word)p + bytes >= (word)GC_greatest_plausible_heap_addr) { GC_greatest_plausible_heap_addr = (void *)endp; } + + if (old_capacity > 0) { +# ifndef GWW_VDB + /* Recycling may call add_to_heap_inner() again but should not */ + /* cause resizing of GC_heap_sects. */ + GC_scratch_recycle_no_gww(old_heap_sects, + old_capacity * sizeof(struct HeapSect)); +# else + /* TODO: implement GWW-aware recycling as in alloc_mark_stack */ + GC_noop1((word)old_heap_sects); +# endif + } } #if !defined(NO_DEBUGGING) diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index f8f477b0..5cd6e85e 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -1269,7 +1269,8 @@ struct roots { # define RT_SIZE (1 << LOG_RT_SIZE) /* Power of 2, may be != MAX_ROOT_SETS */ #endif -#ifndef MAX_HEAP_SECTS +#if !defined(MAX_HEAP_SECTS) && (defined(CYGWIN32) || defined(MSWIN32) \ + || defined(MSWINCE) || defined(USE_PROC_FOR_LIBRARIES)) # ifdef LARGE_CONFIG # if CPP_WORDSZ > 32 # define MAX_HEAP_SECTS 81920 @@ -1459,6 +1460,8 @@ struct _GC_arrays { # define GC_trace_addr GC_arrays._trace_addr ptr_t _trace_addr; # endif +# define GC_capacity_heap_sects GC_arrays._capacity_heap_sects + size_t _capacity_heap_sects; # define GC_n_heap_sects GC_arrays._n_heap_sects word _n_heap_sects; /* Number of separately added heap sections. */ # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32) @@ -1602,7 +1605,7 @@ struct _GC_arrays { struct HeapSect { ptr_t hs_start; size_t hs_bytes; - } _heap_sects[MAX_HEAP_SECTS]; /* Heap segments potentially */ + } *_heap_sects; /* Heap segments potentially */ /* client objects. */ # if defined(USE_PROC_FOR_LIBRARIES) # define GC_our_memory GC_arrays._our_memory |