summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2013-11-22 09:20:06 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2013-11-22 09:20:06 +0900
commit07b8a5b0427c21518c7b7cf465197dc310b9d3b0 (patch)
treebb55a8c8595ed5b8bc95a6792e0d218014c2f4c9 /src
parentb723f67b8b271ee2ace40db723d8eeff5a70f270 (diff)
downloadmruby-07b8a5b0427c21518c7b7cf465197dc310b9d3b0.tar.gz
mruby-07b8a5b0427c21518c7b7cf465197dc310b9d3b0.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/gc.c24
-rw-r--r--src/state.c8
2 files changed, 30 insertions, 2 deletions
diff --git a/src/gc.c b/src/gc.c
index a1ff4d32b..5592b48f1 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -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;
}
diff --git a/src/state.c b/src/state.c
index f8a97cb61..00e113998 100644
--- a/src/state.c
+++ b/src/state.c
@@ -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);
}