Files
mruby-mruby/include/mruby/gc.h
Yukihiro "Matz" Matsumoto f0b3fdfb14 gc.c: replace threshold model with debt-based GC trigger
Replace the threshold-based GC trigger (gc->threshold vs gc->live)
with a debt model (gc->gc_debt). Each allocation increments debt;
each GC step decrements by GC_STEP_SIZE. When a cycle completes,
credit is proportional to live_after_mark * interval_ratio, giving
a natural feedback loop that adapts to allocation rate.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-23 19:25:23 +09:00

86 lines
2.9 KiB
C

/**
** @file mruby/gc.h - garbage collector for mruby
**
** See Copyright Notice in mruby.h
*/
#ifndef MRUBY_GC_H
#define MRUBY_GC_H
#include "common.h"
/**
* Uncommon memory management stuffs.
*/
MRB_BEGIN_DECL
#define MRB_EACH_OBJ_OK 0
#define MRB_EACH_OBJ_BREAK 1
typedef int (mrb_each_object_callback)(mrb_state *mrb, struct RBasic *obj, void *data);
void mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, void *data);
size_t mrb_objspace_page_slot_size(void);
MRB_API void mrb_free_context(mrb_state *mrb, struct mrb_context *c);
#ifndef MRB_GC_ARENA_SIZE
#define MRB_GC_ARENA_SIZE 100
#endif
#ifndef MRB_GRAY_STACK_SIZE
#define MRB_GRAY_STACK_SIZE 1024
#endif
typedef enum {
MRB_GC_STATE_ROOT = 0,
MRB_GC_STATE_MARK,
MRB_GC_STATE_SWEEP
} mrb_gc_state;
typedef struct mrb_gc {
struct mrb_heap_page *heaps; /* all heaps pages */
struct mrb_heap_page *free_heaps;/* heaps for allocation */
struct mrb_heap_page *sweeps; /* page where sweep starts */
struct mrb_heap_region *regions; /* contiguous heap regions */
struct RBasic *gray_stack[MRB_GRAY_STACK_SIZE]; /* stack of gray objects */
size_t gray_stack_top; /* top index of gray stack */
mrb_bool gray_overflow:1; /* gray stack overflowed; needs heap rescan */
size_t live; /* count of live objects */
size_t live_after_mark; /* old generation objects */
mrb_int gc_debt; /* <0:credit, >0:needs GC */
size_t oldgen_threshold; /* threshold to kick major GC */
mrb_gc_state state; /* current state of gc */
int interval_ratio;
int step_ratio;
int current_white_part :2; /* make white object by white_part */
mrb_bool iterating :1; /* currently iterating over objects */
mrb_bool disabled :1; /* GC disabled */
mrb_bool generational :1; /* generational GC mode */
mrb_bool full :1; /* major GC mode */
mrb_bool out_of_memory :1; /* out-of-memory error occurred */
size_t step_limit; /* 0=unlimited, >0=absolute step cap */
size_t malloc_increase; /* malloc bytes since last GC cycle */
size_t malloc_threshold; /* 0=disabled, >0=bytes to trigger GC */
#ifdef MRB_GC_FIXED_ARENA
struct RBasic *arena[MRB_GC_ARENA_SIZE]; /* GC protection array */
#else
struct RBasic **arena; /* GC protection array */
int arena_capa; /* size of protection array */
#endif
int arena_idx;
#ifdef MRB_GC_STATS
uint32_t gc_total_count; /* total GC invocations */
uint32_t minor_gc_count; /* minor GC count */
uint32_t major_gc_count; /* major GC count */
#endif
} mrb_gc;
MRB_API mrb_bool mrb_object_dead_p(mrb_state *mrb, struct RBasic *object);
MRB_API int mrb_gc_add_region(mrb_state *mrb, void *start, size_t size);
#define MRB_GC_RED 7
MRB_END_DECL
#endif /* MRUBY_GC_H */