Make mrb->arena variable sized. Use MRB_GC_FIXED_ARENA for old behavior.

You will not see "arena overflow" error anymore, but I encourage gem authors
to check your gems with MRB_GC_FIXED_ARENA to avoid memory broat.
parent b723f67b
...@@ -59,6 +59,12 @@ ...@@ -59,6 +59,12 @@
/* array size for parser buffer */ /* array size for parser buffer */
//#define MRB_PARSER_BUF_SIZE 1024 //#define MRB_PARSER_BUF_SIZE 1024
/* arena size */
//#define MRB_GC_ARENA_SIZE 100
/* fixed size GC arena */
//#define MRB_GC_FIXED_ARENA
/* -DDISABLE_XXXX to drop following features */ /* -DDISABLE_XXXX to drop following features */
//#define DISABLE_STDIO /* use of stdio */ //#define DISABLE_STDIO /* use of stdio */
......
...@@ -46,8 +46,8 @@ struct mrb_state; ...@@ -46,8 +46,8 @@ struct mrb_state;
typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud); typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud);
#ifndef MRB_ARENA_SIZE #ifndef MRB_GC_ARENA_SIZE
#define MRB_ARENA_SIZE 100 #define MRB_GC_ARENA_SIZE 100
#endif #endif
typedef struct { typedef struct {
...@@ -128,7 +128,12 @@ typedef struct mrb_state { ...@@ -128,7 +128,12 @@ typedef struct mrb_state {
struct heap_page *sweeps; struct heap_page *sweeps;
struct heap_page *free_heaps; struct heap_page *free_heaps;
size_t live; /* count of live objects */ size_t live; /* count of live objects */
struct RBasic *arena[MRB_ARENA_SIZE]; /* GC protection array */ #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;
#endif
int arena_idx; int arena_idx;
enum gc_state gc_state; /* state of gc */ enum gc_state gc_state; /* state of gc */
......
...@@ -370,10 +370,16 @@ mrb_free_heap(mrb_state *mrb) ...@@ -370,10 +370,16 @@ mrb_free_heap(mrb_state *mrb)
static void static void
gc_protect(mrb_state *mrb, struct RBasic *p) gc_protect(mrb_state *mrb, struct RBasic *p)
{ {
if (mrb->arena_idx >= MRB_ARENA_SIZE) { if (mrb->arena_idx >= MRB_GC_ARENA_SIZE) {
#ifdef MRB_GC_FIXED_ARENA
/* arena overflow error */ /* arena overflow error */
mrb->arena_idx = MRB_ARENA_SIZE - 4; /* force room in arena */ mrb->arena_idx = MRB_GC_ARENA_SIZE - 4; /* force room in arena */
mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error"); mrb_raise(mrb, E_RUNTIME_ERROR, "arena overflow error");
#else
/* extend arena */
mrb->arena_capa *= 1.5;
mrb->arena = (struct RBasic**)mrb_realloc(mrb, mrb->arena, sizeof(struct RBasic*)*mrb->arena_capa);
#endif
} }
mrb->arena[mrb->arena_idx++] = p; mrb->arena[mrb->arena_idx++] = p;
} }
...@@ -1041,6 +1047,20 @@ mrb_gc_arena_save(mrb_state *mrb) ...@@ -1041,6 +1047,20 @@ mrb_gc_arena_save(mrb_state *mrb)
void void
mrb_gc_arena_restore(mrb_state *mrb, int idx) mrb_gc_arena_restore(mrb_state *mrb, int idx)
{ {
#ifndef MRB_GC_FIXED_ARENA
int capa = mrb->arena_capa;
if (idx < capa / 2) {
capa *= 0.66;
if (capa < MRB_GC_ARENA_SIZE) {
capa = MRB_GC_ARENA_SIZE;
}
if (capa != mrb->arena_capa) {
mrb->arena = (struct RBasic**)mrb_realloc(mrb, mrb->arena, sizeof(struct RBasic*)*capa);
mrb->arena_capa = capa;
}
}
#endif
mrb->arena_idx = idx; mrb->arena_idx = idx;
} }
......
...@@ -42,6 +42,11 @@ mrb_open_allocf(mrb_allocf f, void *ud) ...@@ -42,6 +42,11 @@ mrb_open_allocf(mrb_allocf f, void *ud)
mrb->allocf = f; mrb->allocf = f;
mrb->current_white_part = MRB_GC_WHITE_A; mrb->current_white_part = MRB_GC_WHITE_A;
#ifndef MRB_GC_FIXED_ARENA
mrb->arena = (struct RBasic**)mrb_malloc(mrb, sizeof(struct RBasic*)*MRB_GC_ARENA_SIZE);
mrb->arena_capa = MRB_GC_ARENA_SIZE;
#endif
mrb_init_heap(mrb); mrb_init_heap(mrb);
mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context)); mrb->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
*mrb->c = mrb_context_zero; *mrb->c = mrb_context_zero;
...@@ -191,6 +196,9 @@ mrb_close(mrb_state *mrb) ...@@ -191,6 +196,9 @@ mrb_close(mrb_state *mrb)
mrb_free_symtbl(mrb); mrb_free_symtbl(mrb);
mrb_free_heap(mrb); mrb_free_heap(mrb);
mrb_alloca_free(mrb); mrb_alloca_free(mrb);
#ifndef MRB_GC_FIXED_ARENA
mrb_free(mrb, mrb->arena);
#endif
mrb_free(mrb, mrb); mrb_free(mrb, mrb);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment