Index: EcnlProtoTool/trunk/mruby-2.1.1/src/gc.c
===================================================================
--- EcnlProtoTool/trunk/mruby-1.3.0/src/gc.c	(revision 331)
+++ EcnlProtoTool/trunk/mruby-2.1.1/src/gc.c	(revision 439)
@@ -11,4 +11,5 @@
 #include <mruby/class.h>
 #include <mruby/data.h>
+#include <mruby/istruct.h>
 #include <mruby/hash.h>
 #include <mruby/proc.h>
@@ -110,10 +111,14 @@
     struct RRange range;
     struct RData data;
+    struct RIStruct istruct;
     struct RProc proc;
     struct REnv env;
+    struct RFiber fiber;
     struct RException exc;
     struct RBreak brk;
 #ifdef MRB_WORD_BOXING
+#ifndef MRB_WITHOUT_FLOAT
     struct RFloat floatv;
+#endif
     struct RCptr cptr;
 #endif
@@ -176,5 +181,5 @@
 #define GC_STEP_SIZE 1024
 
-/* white: 011, black: 100, gray: 000 */
+/* white: 001 or 010, black: 100, gray: 000 */
 #define GC_GRAY 0
 #define GC_WHITE_A 1
@@ -273,7 +278,35 @@
 }
 
+MRB_API void*
+mrb_alloca(mrb_state *mrb, size_t size)
+{
+  struct RString *s;
+  s = (struct RString*)mrb_obj_alloc(mrb, MRB_TT_STRING, mrb->string_class);
+  return s->as.heap.ptr = (char*)mrb_malloc(mrb, size);
+}
+
+static mrb_bool
+heap_p(mrb_gc *gc, struct RBasic *object)
+{
+  mrb_heap_page* page;
+
+  page = gc->heaps;
+  while (page) {
+    RVALUE *p;
+
+    p = objects(page);
+    if (&p[0].as.basic <= object && object <= &p[MRB_HEAP_PAGE_SIZE].as.basic) {
+      return TRUE;
+    }
+    page = page->next;
+  }
+  return FALSE;
+}
+
 MRB_API mrb_bool
 mrb_object_dead_p(mrb_state *mrb, struct RBasic *object) {
-  return is_dead(&mrb->gc, object);
+  mrb_gc *gc = &mrb->gc;
+  if (!heap_p(gc, object)) return TRUE;
+  return is_dead(gc, object);
 }
 
@@ -343,5 +376,6 @@
 #define DEFAULT_GC_INTERVAL_RATIO 200
 #define DEFAULT_GC_STEP_RATIO 200
-#define DEFAULT_MAJOR_GC_INC_RATIO 200
+#define MAJOR_GC_INC_RATIO 120
+#define MAJOR_GC_TOOMANY 10000
 #define is_generational(gc) ((gc)->generational)
 #define is_major_gc(gc) (is_generational(gc) && (gc)->full)
@@ -374,5 +408,5 @@
 static void obj_free(mrb_state *mrb, struct RBasic *obj, int end);
 
-void
+static void
 free_heap(mrb_state *mrb, mrb_gc *gc)
 {
@@ -413,5 +447,5 @@
   if (gc->arena_idx >= gc->arena_capa) {
     /* extend arena */
-    gc->arena_capa = (int)(gc->arena_capa * 1.5);
+    gc->arena_capa = (int)(gc->arena_capa * 3 / 2);
     gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*gc->arena_capa);
   }
@@ -441,8 +475,11 @@
 mrb_gc_register(mrb_state *mrb, mrb_value obj)
 {
-  mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
-  mrb_value table = mrb_gv_get(mrb, root);
-
-  if (mrb_nil_p(table) || mrb_type(table) != MRB_TT_ARRAY) {
+  mrb_sym root;
+  mrb_value table;
+
+  if (mrb_immediate_p(obj)) return;
+  root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+  table = mrb_gv_get(mrb, root);
+  if (mrb_nil_p(table) || !mrb_array_p(table)) {
     table = mrb_ary_new(mrb);
     mrb_gv_set(mrb, root, table);
@@ -455,11 +492,14 @@
 mrb_gc_unregister(mrb_state *mrb, mrb_value obj)
 {
-  mrb_sym root = mrb_intern_lit(mrb, GC_ROOT_NAME);
-  mrb_value table = mrb_gv_get(mrb, root);
+  mrb_sym root;
+  mrb_value table;
   struct RArray *a;
   mrb_int i;
 
+  if (mrb_immediate_p(obj)) return;
+  root = mrb_intern_lit(mrb, GC_ROOT_NAME);
+  table = mrb_gv_get(mrb, root);
   if (mrb_nil_p(table)) return;
-  if (mrb_type(table) != MRB_TT_ARRAY) {
+  if (!mrb_array_p(table)) {
     mrb_gv_set(mrb, root, mrb_nil_value());
     return;
@@ -467,8 +507,11 @@
   a = mrb_ary_ptr(table);
   mrb_ary_modify(mrb, a);
-  for (i = 0; i < a->len; i++) {
-    if (mrb_obj_eq(mrb, a->ptr[i], obj)) {
-      a->len--;
-      memmove(&a->ptr[i], &a->ptr[i + 1], (a->len - i) * sizeof(a->ptr[i]));
+  for (i = 0; i < ARY_LEN(a); i++) {
+    if (mrb_ptr(ARY_PTR(a)[i]) == mrb_ptr(obj)) {
+      mrb_int len = ARY_LEN(a)-1;
+      mrb_value *ptr = ARY_PTR(a);
+
+      ARY_SET_LEN(a, len);
+      memmove(&ptr[i], &ptr[i + 1], (len - i) * sizeof(mrb_value));
       break;
     }
@@ -480,5 +523,5 @@
 {
   struct RBasic *p;
-  static const RVALUE RVALUE_zero = { { { MRB_TT_FALSE } } };
+  static const RVALUE RVALUE_zero = { { { NULL, NULL, MRB_TT_FALSE } } };
   mrb_gc *gc = &mrb->gc;
 
@@ -501,5 +544,5 @@
         ttype != MRB_TT_ENV &&
         ttype != tt) {
-      mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %S", mrb_obj_value(cls));
+      mrb_raisef(mrb, E_TYPE_ERROR, "allocation failure of %C", cls);
     }
   }
@@ -543,4 +586,26 @@
 }
 
+static int
+ci_nregs(mrb_callinfo *ci)
+{
+  struct RProc *p = ci->proc;
+  int n = 0;
+
+  if (!p) {
+    if (ci->argc < 0) return 3;
+    return ci->argc+2;
+  }
+  if (!MRB_PROC_CFUNC_P(p) && p->body.irep) {
+    n = p->body.irep->nregs;
+  }
+  if (ci->argc < 0) {
+    if (n < 3) n = 3; /* self + args + blk */
+  }
+  if (ci->argc > n) {
+    n = ci->argc + 2; /* self + blk */
+  }
+  return n;
+}
+
 static void
 mark_context_stack(mrb_state *mrb, struct mrb_context *c)
@@ -549,13 +614,9 @@
   size_t e;
   mrb_value nil;
-  int nregs;
 
   if (c->stack == NULL) return;
   e = c->stack - c->stbase;
   if (c->ci) {
-    nregs = c->ci->argc + 2;
-    if (c->ci->nregs > nregs)
-      nregs = c->ci->nregs;
-    e += nregs;
+    e += ci_nregs(c->ci);
   }
   if (c->stbase + e > c->stend) e = c->stend - c->stbase;
@@ -579,4 +640,7 @@
   int i;
   mrb_callinfo *ci;
+
+ start:
+  if (c->status == MRB_FIBER_TERMINATED) return;
 
   /* mark VM stack */
@@ -592,6 +656,5 @@
   }
   /* mark ensure stack */
-  for (i=0; i<c->esize; i++) {
-    if (c->ensure[i] == NULL) break;
+  for (i=0; i<c->eidx; i++) {
     mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]);
   }
@@ -599,5 +662,6 @@
   mrb_gc_mark(mrb, (struct RBasic*)c->fib);
   if (c->prev) {
-    mark_context(mrb, c->prev);
+    c = c->prev;
+    goto start;
   }
 }
@@ -614,5 +678,5 @@
     {
       struct RClass *c = (struct RClass*)obj;
-      if (MRB_FLAG_TEST(c, MRB_FLAG_IS_ORIGIN))
+      if (MRB_FLAG_TEST(c, MRB_FL_CLASS_IS_ORIGIN))
         mrb_gc_mark_mt(mrb, c);
       mrb_gc_mark(mrb, (struct RBasic*)((struct RClass*)obj)->super);
@@ -641,6 +705,6 @@
       struct RProc *p = (struct RProc*)obj;
 
-      mrb_gc_mark(mrb, (struct RBasic*)p->env);
-      mrb_gc_mark(mrb, (struct RBasic*)p->target_class);
+      mrb_gc_mark(mrb, (struct RBasic*)p->upper);
+      mrb_gc_mark(mrb, (struct RBasic*)p->e.env);
     }
     break;
@@ -651,9 +715,6 @@
       mrb_int i, len;
 
-      if (MRB_ENV_STACK_SHARED_P(e)) {
-        if (e->cxt.c->fib) {
-          mrb_gc_mark(mrb, (struct RBasic*)e->cxt.c->fib);
-        }
-        break;
+      if (MRB_ENV_STACK_SHARED_P(e) && e->cxt && e->cxt->fib) {
+        mrb_gc_mark(mrb, (struct RBasic*)e->cxt->fib);
       }
       len = MRB_ENV_STACK_LEN(e);
@@ -677,6 +738,6 @@
       size_t i, e;
 
-      for (i=0,e=a->len; i<e; i++) {
-        mrb_gc_mark_value(mrb, a->ptr[i]);
+      for (i=0,e=ARY_LEN(a); i<e; i++) {
+        mrb_gc_mark_value(mrb, ARY_PTR(a)[i]);
       }
     }
@@ -689,15 +750,12 @@
 
   case MRB_TT_STRING:
+    if (RSTR_FSHARED_P(obj)) {
+      struct RString *s = (struct RString*)obj;
+      mrb_gc_mark(mrb, (struct RBasic*)s->as.heap.aux.fshared);
+    }
     break;
 
   case MRB_TT_RANGE:
-    {
-      struct RRange *r = (struct RRange*)obj;
-
-      if (r->edges) {
-        mrb_gc_mark_value(mrb, r->edges->beg);
-        mrb_gc_mark_value(mrb, r->edges->end);
-      }
-    }
+    mrb_gc_mark_range(mrb, (struct RRange*)obj);
     break;
 
@@ -728,4 +786,5 @@
     return;
 
+#ifndef MRB_WITHOUT_FLOAT
   case MRB_TT_FLOAT:
 #ifdef MRB_WORD_BOXING
@@ -733,4 +792,5 @@
 #else
     return;
+#endif
 #endif
 
@@ -748,8 +808,10 @@
     mrb_gc_free_mt(mrb, (struct RClass*)obj);
     mrb_gc_free_iv(mrb, (struct RObject*)obj);
+    mrb_mc_clear_by_class(mrb, (struct RClass*)obj);
     break;
   case MRB_TT_ICLASS:
-    if (MRB_FLAG_TEST(obj, MRB_FLAG_IS_ORIGIN))
+    if (MRB_FLAG_TEST(obj, MRB_FL_CLASS_IS_ORIGIN))
       mrb_gc_free_mt(mrb, (struct RClass*)obj);
+    mrb_mc_clear_by_class(mrb, (struct RClass*)obj);
     break;
   case MRB_TT_ENV:
@@ -759,5 +821,6 @@
       if (MRB_ENV_STACK_SHARED_P(e)) {
         /* cannot be freed */
-        return;
+        e->stack = NULL;
+        break;
       }
       mrb_free(mrb, e->stack);
@@ -770,15 +833,17 @@
       struct mrb_context *c = ((struct RFiber*)obj)->cxt;
 
-      if (!end && c && c != mrb->root_c) {
-        mrb_callinfo *ci = c->ci;
-        mrb_callinfo *ce = c->cibase;
-
-        while (ce <= ci) {
-          struct REnv *e = ci->env;
-          if (e && !is_dead(&mrb->gc, e) &&
-              e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) {
-            mrb_env_unshare(mrb, e);
+      if (c && c != mrb->root_c) {
+        if (!end && c->status != MRB_FIBER_TERMINATED) {
+          mrb_callinfo *ci = c->ci;
+          mrb_callinfo *ce = c->cibase;
+
+          while (ce <= ci) {
+            struct REnv *e = ci->env;
+            if (e && !mrb_object_dead_p(mrb, (struct RBasic*)e) &&
+                e->tt == MRB_TT_ENV && MRB_ENV_STACK_SHARED_P(e)) {
+              mrb_env_unshare(mrb, e);
+            }
+            ci--;
           }
-          ci--;
         }
         mrb_free_context(mrb, c);
@@ -789,7 +854,7 @@
   case MRB_TT_ARRAY:
     if (ARY_SHARED_P(obj))
-      mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared);
-    else
-      mrb_free(mrb, ((struct RArray*)obj)->ptr);
+      mrb_ary_decref(mrb, ((struct RArray*)obj)->as.heap.aux.shared);
+    else if (!ARY_EMBED_P(obj))
+      mrb_free(mrb, ((struct RArray*)obj)->as.heap.ptr);
     break;
 
@@ -808,5 +873,9 @@
 
       if (!MRB_PROC_CFUNC_P(p) && p->body.irep) {
-        mrb_irep_decref(mrb, p->body.irep);
+        mrb_irep *irep = p->body.irep;
+        if (end) {
+          mrb_irep_cutref(mrb, irep);
+        }
+        mrb_irep_decref(mrb, irep);
       }
     }
@@ -814,5 +883,5 @@
 
   case MRB_TT_RANGE:
-    mrb_free(mrb, ((struct RRange*)obj)->edges);
+    mrb_gc_free_range(mrb, ((struct RRange*)obj));
     break;
 
@@ -858,6 +927,9 @@
   mrb_gc_mark(mrb, (struct RBasic*)mrb->array_class);
   mrb_gc_mark(mrb, (struct RBasic*)mrb->hash_class);
-
+  mrb_gc_mark(mrb, (struct RBasic*)mrb->range_class);
+
+#ifndef MRB_WITHOUT_FLOAT
   mrb_gc_mark(mrb, (struct RBasic*)mrb->float_class);
+#endif
   mrb_gc_mark(mrb, (struct RBasic*)mrb->fixnum_class);
   mrb_gc_mark(mrb, (struct RBasic*)mrb->true_class);
@@ -918,5 +990,5 @@
 
   case MRB_TT_ENV:
-    children += (int)obj->flags;
+    children += MRB_ENV_STACK_LEN(obj);
     break;
 
@@ -927,8 +999,12 @@
       mrb_callinfo *ci;
 
-      if (!c) break;
+      if (!c || c->status == MRB_FIBER_TERMINATED) break;
+
       /* mark stack */
       i = c->stack - c->stbase;
-      if (c->ci) i += c->ci->nregs;
+
+      if (c->ci) {
+        i += ci_nregs(c->ci);
+      }
       if (c->stbase + i > c->stend) i = c->stend - c->stbase;
       children += i;
@@ -949,5 +1025,5 @@
     {
       struct RArray *a = (struct RArray*)obj;
-      children += a->len;
+      children += ARY_LEN(a);
     }
     break;
@@ -1190,6 +1266,15 @@
 
     if (is_major_gc(gc)) {
-      gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+      size_t threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
+
       gc->full = FALSE;
+      if (threshold < MAJOR_GC_TOOMANY) {
+        gc->majorgc_old_threshold = threshold;
+      }
+      else {
+        /* too many objects allocated during incremental GC, */
+        /* instead of increasing threshold, invoke full GC. */
+        mrb_full_gc(mrb);
+      }
     }
     else if (is_minor_gc(gc)) {
@@ -1229,5 +1314,5 @@
 
   if (is_generational(gc)) {
-    gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+    gc->majorgc_old_threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
     gc->full = FALSE;
   }
@@ -1240,32 +1325,4 @@
 {
   mrb_full_gc(mrb);
-}
-
-MRB_API int
-mrb_gc_arena_save(mrb_state *mrb)
-{
-  return mrb->gc.arena_idx;
-}
-
-MRB_API void
-mrb_gc_arena_restore(mrb_state *mrb, int idx)
-{
-  mrb_gc *gc = &mrb->gc;
-
-#ifndef MRB_GC_FIXED_ARENA
-  int capa = gc->arena_capa;
-
-  if (idx < capa / 2) {
-    capa = (int)(capa * 0.66);
-    if (capa < MRB_GC_ARENA_SIZE) {
-      capa = MRB_GC_ARENA_SIZE;
-    }
-    if (capa != gc->arena_capa) {
-      gc->arena = (struct RBasic**)mrb_realloc(mrb, gc->arena, sizeof(struct RBasic*)*capa);
-      gc->arena_capa = capa;
-    }
-  }
-#endif
-  gc->arena_idx = idx;
 }
 
@@ -1407,5 +1464,5 @@
 
   mrb_get_args(mrb, "i", &ratio);
-  mrb->gc.interval_ratio = ratio;
+  mrb->gc.interval_ratio = (int)ratio;
   return mrb_nil_value();
 }
@@ -1440,5 +1497,5 @@
 
   mrb_get_args(mrb, "i", &ratio);
-  mrb->gc.step_ratio = ratio;
+  mrb->gc.step_ratio = (int)ratio;
   return mrb_nil_value();
 }
@@ -1458,5 +1515,5 @@
   else if (!is_generational(gc) && enable) {
     incremental_gc_until(mrb, gc, MRB_GC_STATE_ROOT);
-    gc->majorgc_old_threshold = gc->live_after_mark/100 * DEFAULT_MAJOR_GC_INC_RATIO;
+    gc->majorgc_old_threshold = gc->live_after_mark/100 * MAJOR_GC_INC_RATIO;
     gc->full = FALSE;
   }
@@ -1523,4 +1580,5 @@
   mrb_bool iterating = mrb->gc.iterating;
 
+  mrb_full_gc(mrb);
   mrb->gc.iterating = TRUE;
   if (iterating) {
@@ -1535,5 +1593,5 @@
       gc_each_objects(mrb, &mrb->gc, callback, data);
       mrb->jmp = prev_jmp;
-      mrb->gc.iterating = iterating; 
+      mrb->gc.iterating = iterating;
    } MRB_CATCH(&c_jmp) {
       mrb->gc.iterating = iterating;
@@ -1554,4 +1612,7 @@
 {
   struct RClass *gc;
+
+  mrb_static_assert(sizeof(RVALUE) <= sizeof(void*) * 6,
+                    "RVALUE size must be within 6 words");
 
   gc = mrb_define_module(mrb, "GC");
