mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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.
This commit is contained in:
@@ -59,6 +59,12 @@
|
||||
/* array size for parser buffer */
|
||||
//#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 */
|
||||
//#define DISABLE_STDIO /* use of stdio */
|
||||
|
||||
|
||||
+8
-3
@@ -46,8 +46,8 @@ struct mrb_state;
|
||||
|
||||
typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud);
|
||||
|
||||
#ifndef MRB_ARENA_SIZE
|
||||
#define MRB_ARENA_SIZE 100
|
||||
#ifndef MRB_GC_ARENA_SIZE
|
||||
#define MRB_GC_ARENA_SIZE 100
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
@@ -128,7 +128,12 @@ typedef struct mrb_state {
|
||||
struct heap_page *sweeps;
|
||||
struct heap_page *free_heaps;
|
||||
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;
|
||||
|
||||
enum gc_state gc_state; /* state of gc */
|
||||
|
||||
@@ -370,10 +370,16 @@ mrb_free_heap(mrb_state *mrb)
|
||||
static void
|
||||
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 */
|
||||
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");
|
||||
#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;
|
||||
}
|
||||
@@ -1041,6 +1047,20 @@ mrb_gc_arena_save(mrb_state *mrb)
|
||||
void
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,11 @@ mrb_open_allocf(mrb_allocf f, void *ud)
|
||||
mrb->allocf = f;
|
||||
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->c = (struct mrb_context*)mrb_malloc(mrb, sizeof(struct mrb_context));
|
||||
*mrb->c = mrb_context_zero;
|
||||
@@ -191,6 +196,9 @@ mrb_close(mrb_state *mrb)
|
||||
mrb_free_symtbl(mrb);
|
||||
mrb_free_heap(mrb);
|
||||
mrb_alloca_free(mrb);
|
||||
#ifndef MRB_GC_FIXED_ARENA
|
||||
mrb_free(mrb, mrb->arena);
|
||||
#endif
|
||||
mrb_free(mrb, mrb);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user