summaryrefslogtreecommitdiff
path: root/src/gc/sms.c
diff options
context:
space:
mode:
authorNathan Ringo <nathan@remexre.com>2024-11-28 22:33:47 -0600
committerNathan Ringo <nathan@remexre.com>2024-11-28 22:33:47 -0600
commitb3149099a17d392289db9699b5b5d83444d25173 (patch)
tree24e84d2ca1469bd87b4379ea2b701218d0465d8f /src/gc/sms.c
parent16e22f9cb39a254bccd20613f7c2cfef75ae15a7 (diff)
Prevent 3DS hangs.
Diffstat (limited to 'src/gc/sms.c')
-rw-r--r--src/gc/sms.c36
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");