diff options
Diffstat (limited to 'src/gc/sms.c')
-rw-r--r-- | src/gc/sms.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/src/gc/sms.c b/src/gc/sms.c index a2ab18e..eb76dab 100644 --- a/src/gc/sms.c +++ b/src/gc/sms.c @@ -50,6 +50,9 @@ static const struct object_header *hdrc(const void *ptr) { return &((const struct object_header *)ptr)[-1]; } +static size_t collect_amount[5] = {0}; +static size_t collect_amount_i = 0; + void gc_init(void) {} static void gc_mark(const struct value initial_value) { @@ -213,15 +216,38 @@ static void gc_sweep(void) { } } -void gc_collect(void) { - fprintf(stderr, "gc_collect()... "); +static const char *string_of_gc_collect_reason(enum gc_collect_reason reason) { + switch (reason) { + case GC_COLLECT_MANUAL: + return "GC_COLLECT_MANUAL"; + case GC_COLLECT_LIMIT: + return "GC_COLLECT_LIMIT"; + case GC_COLLECT_OOM: + return "GC_COLLECT_OOM"; + default: + return "???"; + } +} + +void gc_collect(enum gc_collect_reason reason) { + debugf("gc_collect(%s)... ", string_of_gc_collect_reason(reason)); for (size_t i = 0; i < root_stack_depth; i++) gc_mark(*root_stack[i]); const size_t before = live_bytes; gc_sweep(); const size_t after = live_bytes; fprintf(stderr, "collected %zu bytes\n", before - after); - assume(live_bytes < limit_bytes); + + collect_amount[collect_amount_i++] = before - after; + const size_t collect_amount_count = + sizeof(collect_amount) / sizeof(collect_amount[0]); + collect_amount_i %= collect_amount_count; + size_t i; + for (i = 0; i < collect_amount_count; i++) + if (collect_amount[i] > before / 50) + break; + if (i == collect_amount_count) + todo("OOM: GC was not productive"); } struct object *gc_alloc(size_t value_slot_count, size_t untraced_slot_count) { @@ -232,10 +258,10 @@ struct object *gc_alloc(size_t value_slot_count, size_t untraced_slot_count) { sizeof(struct object_header) + (value_slot_count + untraced_slot_count) * sizeof(uintptr_t); if ((live_bytes += total_bytes) >= limit_bytes) - gc_collect(); + gc_collect(GC_COLLECT_LIMIT); struct object_header *header = malloc(total_bytes); if (!header) { - gc_collect(); + gc_collect(GC_COLLECT_OOM); header = malloc(total_bytes); if (!header) todo("OOM"); |