summaryrefslogtreecommitdiff
path: root/alloc.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2021-09-17 00:08:53 +0300
committerIvan Maidanski <ivmai@mail.ru>2021-09-17 00:08:53 +0300
commit8e01d31bfb9a4cdffdfe952b8e8c1d048d9e1cd3 (patch)
treea4c156268f62a6e512facf5e829b788f64cfcee2 /alloc.c
parent33b897fc3c011752686d6fe19f6bd184c0b6e341 (diff)
downloadbdwgc-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.
Diffstat (limited to 'alloc.c')
-rw-r--r--alloc.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/alloc.c b/alloc.c
index ce804e3f..f269dbfe 100644
--- a/alloc.c
+++ b/alloc.c
@@ -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)