summaryrefslogtreecommitdiffhomepage
path: root/src/gc.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2013-05-20 17:54:07 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2013-05-20 17:54:07 +0900
commit5c0b9b703c9d1a08d7219b057b809bda4bc89f8a (patch)
treeab610a2988ef928c02bfc50e31aedc5a707f008e /src/gc.c
parent35ee85164dd19143d4b47a34f13ad2bb71fed369 (diff)
downloadmruby-5c0b9b703c9d1a08d7219b057b809bda4bc89f8a.tar.gz
mruby-5c0b9b703c9d1a08d7219b057b809bda4bc89f8a.zip
primary mruby fiber implementation
Diffstat (limited to 'src/gc.c')
-rw-r--r--src/gc.c95
1 files changed, 73 insertions, 22 deletions
diff --git a/src/gc.c b/src/gc.c
index 2e5678f7d..4837d5207 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -387,6 +387,35 @@ add_gray_list(mrb_state *mrb, struct RBasic *obj)
}
static void
+mark_context(mrb_state *mrb, struct mrb_context *c)
+{
+ size_t i;
+ size_t e;
+ mrb_callinfo *ci;
+
+ /* mark stack */
+ e = c->stack - c->stbase;
+ if (c->ci) e += c->ci->nregs;
+ if (c->stbase + e > c->stend) e = c->stend - c->stbase;
+ for (i=0; i<e; i++) {
+ mrb_gc_mark_value(mrb, c->stbase[i]);
+ }
+ /* mark ensure stack */
+ e = (c->ci) ? c->ci->eidx : 0;
+ for (i=0; i<e; i++) {
+ mrb_gc_mark(mrb, (struct RBasic*)c->ensure[i]);
+ }
+ /* mark closure */
+ for (ci = c->cibase; ci <= c->ci; ci++) {
+ if (!ci) continue;
+ mrb_gc_mark(mrb, (struct RBasic*)ci->env);
+ mrb_gc_mark(mrb, (struct RBasic*)ci->proc);
+ mrb_gc_mark(mrb, (struct RBasic*)ci->target_class);
+ }
+ if (c->prev) mark_context(mrb, c->prev);
+}
+
+static void
gc_mark_children(mrb_state *mrb, struct RBasic *obj)
{
gc_assert(is_gray(obj));
@@ -438,6 +467,15 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
}
break;
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+
+ mark_context(mrb, c);
+ ((struct RFiber*)obj)->cxt = NULL;
+ }
+ break;
+
case MRB_TT_ARRAY:
{
struct RArray *a = (struct RArray*)obj;
@@ -517,6 +555,14 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
}
break;
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+
+ mrb_free_context(mrb, c);
+ }
+ break;
+
case MRB_TT_ARRAY:
if (obj->flags & MRB_ARY_SHARED)
mrb_ary_decref(mrb, ((struct RArray*)obj)->aux.shared);
@@ -557,9 +603,7 @@ static void
root_scan_phase(mrb_state *mrb)
{
int j;
- size_t i;
- size_t e;
- mrb_callinfo *ci;
+ size_t i, e;
if (!is_minor_gc(mrb)) {
mrb->gray_list = 0;
@@ -577,25 +621,8 @@ root_scan_phase(mrb_state *mrb)
mrb_gc_mark(mrb, (struct RBasic*)mrb->top_self);
/* mark exception */
mrb_gc_mark(mrb, (struct RBasic*)mrb->exc);
- /* mark stack */
- e = mrb->stack - mrb->stbase;
- if (mrb->ci) e += mrb->ci->nregs;
- if (mrb->stbase + e > mrb->stend) e = mrb->stend - mrb->stbase;
- for (i=0; i<e; i++) {
- mrb_gc_mark_value(mrb, mrb->stbase[i]);
- }
- /* mark ensure stack */
- e = (mrb->ci) ? mrb->ci->eidx : 0;
- for (i=0; i<e; i++) {
- mrb_gc_mark(mrb, (struct RBasic*)mrb->ensure[i]);
- }
- /* mark closure */
- for (ci = mrb->cibase; ci <= mrb->ci; ci++) {
- if (!ci) continue;
- mrb_gc_mark(mrb, (struct RBasic*)ci->env);
- mrb_gc_mark(mrb, (struct RBasic*)ci->proc);
- mrb_gc_mark(mrb, (struct RBasic*)ci->target_class);
- }
+
+ mark_context(mrb, mrb->c);
/* mark irep pool */
if (mrb->irep) {
size_t len = mrb->irep_len;
@@ -643,6 +670,30 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
children += (int)obj->flags;
break;
+ case MRB_TT_FIBER:
+ {
+ struct mrb_context *c = ((struct RFiber*)obj)->cxt;
+ size_t i;
+ mrb_callinfo *ci;
+
+ /* mark stack */
+ i = c->stack - c->stbase;
+ if (c->ci) i += c->ci->nregs;
+ if (c->stbase + i > c->stend) i = c->stend - c->stbase;
+ children += i;
+
+ /* mark ensure stack */
+ children += (c->ci) ? c->ci->eidx : 0;
+
+ /* mark closure */
+ if (c->cibase) {
+ for (i=0, ci = c->cibase; ci <= c->ci; i++, ci++)
+ ;
+ }
+ children += i;
+ }
+ break;
+
case MRB_TT_ARRAY:
{
struct RArray *a = (struct RArray*)obj;