Index: array.c
===================================================================
RCS file: /src/ruby/array.c,v
retrieving revision 1.50
diff -u -r1.50 array.c
--- array.c	2001/06/19 04:35:13	1.50
+++ array.c	2001/06/19 15:04:28
@@ -262,6 +262,7 @@
     if (idx >= RARRAY(ary)->len) {
 	RARRAY(ary)->len = idx + 1;
     }
+    GC_CHECK_REF(ary, val);
     RARRAY(ary)->ptr[idx] = val;
 }
 
@@ -344,6 +345,7 @@
     MEMMOVE(RARRAY(ary)->ptr+1, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
 
     RARRAY(ary)->len++;
+    GC_CHECK_REF(ary, item);
     RARRAY(ary)->ptr[0] = item;
 
     return ary;
@@ -1063,7 +1065,10 @@
 
     rb_ary_modify(ary);
     for (i = 0; i < RARRAY(ary)->len; i++) {
-	RARRAY(ary)->ptr[i] = rb_yield(RARRAY(ary)->ptr[i]);
+	VALUE tmp;
+	tmp = rb_yield(RARRAY(ary)->ptr[i]);
+	GC_CHECK_REF(ary, tmp);
+	RARRAY(ary)->ptr[i] = tmp;	
     }
     return ary;
 }
Index: class.c
===================================================================
RCS file: /src/ruby/class.c,v
retrieving revision 1.18
diff -u -r1.18 class.c
--- class.c	2001/05/30 09:12:33	1.18
+++ class.c	2001/06/19 15:04:30
@@ -34,12 +34,14 @@
 }
 
 static int
-clone_method(mid, body, tbl)
+clone_method(mid, body, clone)
     ID mid;
     NODE *body;
-    st_table *tbl;
+    struct RClass *clone;
 {
-    st_insert(tbl, mid, NEW_METHOD(body->nd_body, body->nd_noex));
+    NODE *tmp = NEW_METHOD(body->nd_body, body->nd_noex);
+    GC_REFRESH(clone, tmp);
+    st_insert(clone->m_tbl, mid, tmp);
     return ST_CONTINUE;
 }
 
@@ -56,7 +58,7 @@
     }
     if (RCLASS(module)->m_tbl) {
 	clone->m_tbl = st_init_numtable();
-	st_foreach(RCLASS(module)->m_tbl, clone_method, clone->m_tbl);
+	st_foreach(RCLASS(module)->m_tbl, clone_method, clone);
     }
 
     return (VALUE)clone;
@@ -102,7 +104,7 @@
 	    clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
 	}
 	clone->m_tbl = st_init_numtable();
-	st_foreach(RCLASS(klass)->m_tbl, clone_method, clone->m_tbl);
+	st_foreach(RCLASS(klass)->m_tbl, clone_method, clone);
 	FL_SET(clone, FL_SINGLETON);
 	return (VALUE)clone;
     }
@@ -125,13 +127,15 @@
     ID id;
     VALUE super;
 {
-    VALUE klass;
+    VALUE klass, tmp;
 
     if (!super) super = rb_cObject;
     klass = rb_class_new(super);
     rb_name_class(klass, id);
     /* make metaclass */
-    RBASIC(klass)->klass = rb_singleton_class_new(RBASIC(super)->klass);
+    tmp = rb_singleton_class_new(RBASIC(super)->klass);
+    GC_REFRESH(klass, tmp);
+    RBASIC(klass)->klass = tmp;
     rb_singleton_class_attached(RBASIC(klass)->klass, klass);
     rb_funcall(super, rb_intern("inherited"), 1, klass);
 
@@ -261,9 +265,11 @@
     klass->m_tbl = RCLASS(module)->m_tbl;
     klass->super = super;
     if (TYPE(module) == T_ICLASS) {
+	GC_REFRESH(klass, RBASIC(module)->klass);/*gc?*/
 	RBASIC(klass)->klass = RBASIC(module)->klass;
     }
     else {
+	GC_REFRESH(klass, module);/*gc?*/
 	RBASIC(klass)->klass = module;
     }
 
@@ -274,7 +280,7 @@
 rb_include_module(klass, module)
     VALUE klass, module;
 {
-    VALUE p;
+    VALUE p, tmp;
     int changed = 0;
 
     rb_frozen_class_p(klass);
@@ -306,7 +312,9 @@
 		return;
 	    }
 	}
-	RCLASS(klass)->super = include_class_new(module, RCLASS(klass)->super);
+	tmp = include_class_new(module, RCLASS(klass)->super);
+	GC_REFRESH(klass, tmp);
+	RCLASS(klass)->super = tmp;
 	klass = RCLASS(klass)->super;
 	module = RCLASS(module)->super;
 	changed = 1;
@@ -604,6 +612,7 @@
     }
     else {
 	klass = rb_singleton_class_new(RBASIC(obj)->klass);
+	GC_REFRESH(obj, klass);
 	RBASIC(obj)->klass = klass;
 	rb_singleton_class_attached(klass, obj);
     }
Index: eval.c
===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.187
diff -u -r1.187 eval.c
--- eval.c	2001/06/19 07:33:08	1.187
+++ eval.c	2001/06/19 15:05:01
@@ -233,6 +233,7 @@
     }
     if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
     body = NEW_METHOD(node, noex);
+    GC_REFRESH(klass, body);
     st_insert(RCLASS(klass)->m_tbl, mid, body);
 }
 
@@ -689,6 +690,7 @@
 	    if (n == 2) break;
 	}
 	if (vars->id == id) {
+	    GC_REFRESH(vars, value);
 	    vars->val = value;
 	    return;
 	}
@@ -699,6 +701,7 @@
     }
     else {
 	vars = new_dvar(id, value, ruby_dyna_vars->next);
+	GC_REFRESH(ruby_dyna_vars, vars);
 	ruby_dyna_vars->next = vars;
     }
 }
@@ -1573,7 +1576,7 @@
     ID name, def;
 {
     VALUE origin;
-    NODE *orig, *body;
+    NODE *orig, *body, *tmp;
 
     rb_frozen_class_p(klass);
     if (name == def) return;
@@ -1597,8 +1600,9 @@
 	body = body->nd_head;
     }
 
-    st_insert(RCLASS(klass)->m_tbl, name,
-	      NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
+    tmp = NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex);
+    GC_REFRESH(klass, tmp);
+    st_insert(RCLASS(klass)->m_tbl, name, tmp);
     rb_clear_cache_by_id(name);
     if (FL_TEST(klass, FL_SINGLETON)) {
 	rb_funcall(rb_iv_get(klass, "__attached__"),
@@ -2479,6 +2483,7 @@
 	    nd_type(node->nd_end) == NODE_LIT && FIXNUM_P(node->nd_end->nd_lit))
 	{
 	    nd_set_type(node, NODE_LIT);
+	    GC_REFRESH(node, result);
 	    node->nd_lit = result;
 	}
 	else {
@@ -2624,6 +2629,7 @@
 	    if (node->nd_tbl) {
 		VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
 		*vars++ = (VALUE)node;
+		GC_REFRESH(ruby_scope, node);
 		ruby_scope->local_vars = vars;
 		rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
 		ruby_scope->local_tbl = node->nd_tbl;
@@ -2721,6 +2727,7 @@
 	if (ruby_scope->local_vars == 0)
 	    rb_bug("unexpected local variable assignment");
 	result = rb_eval(self, node->nd_value);
+	GC_REFRESH(ruby_scope, result);
 	ruby_scope->local_vars[node->nd_cnt] = result;
 	break;
 
@@ -2813,6 +2820,7 @@
 	    rb_bug("unexpected block argument");
 	if (rb_block_given_p()) {
 	    result = rb_f_lambda();
+	    GC_REFRESH(ruby_scope, result);
 	    ruby_scope->local_vars[node->nd_cnt] = result;
 	}
 	else {
@@ -2895,7 +2903,9 @@
 	    i = node->nd_alen;
 	    ary = rb_ary_new2(i);
 	    for (i=0;node;node=node->nd_next) {
-		RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
+		VALUE tmp = rb_eval(self, node->nd_head);
+		GC_REFRESH(ary, tmp);
+		RARRAY(ary)->ptr[i++] = tmp;
 		RARRAY(ary)->len = i;
 	    }
 
@@ -2913,7 +2923,7 @@
       case NODE_DREGX_ONCE:
 	{
 	    VALUE str, str2;
-	    NODE *list = node->nd_next;
+	    NODE *list = node->nd_next, *tmp;
 
 	    str = rb_str_new3(node->nd_lit);
 	    while (list) {
@@ -2927,9 +2937,11 @@
 			ruby_errinfo = Qnil;
 			ruby_sourceline = nd_line(node);
 			ruby_in_eval++;
-			list->nd_head = compile(list->nd_head->nd_lit,
-						ruby_sourcefile,
-						ruby_sourceline);
+			tmp = compile(list->nd_head->nd_lit,
+				      ruby_sourcefile,
+				      ruby_sourceline);
+			GC_REFRESH(list, tmp);
+			list->nd_head = tmp;
 			ruby_eval_tree = 0;
 			ruby_in_eval--;
 			if (ruby_nerrs > 0) {
@@ -2955,6 +2967,7 @@
 		result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
 				 node->nd_cflag);
 		nd_set_type(node, NODE_LIT);
+		GC_REFRESH(node, result);
 		node->nd_lit = result;
 		break;
 	      case NODE_DXSTR:
@@ -3279,6 +3292,7 @@
     if (node->nd_tbl) {
 	VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);
 	*vars++ = (VALUE)node;
+	GC_REFRESH(ruby_scope, node);
 	ruby_scope->local_vars = vars;
 	rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
 	ruby_scope->local_tbl = node->nd_tbl;
@@ -3804,6 +3818,7 @@
       case NODE_LASGN:
 	if (ruby_scope->local_vars == 0)
 	    rb_bug("unexpected local variable assignment");
+	GC_REFRESH(ruby_scope, val);
 	ruby_scope->local_vars[lhs->nd_cnt] = val;
 	break;
 
@@ -4407,6 +4422,7 @@
 		local_vars = TMP_ALLOC(body->nd_tbl[0]+1);
 		*local_vars++ = (VALUE)body;
 		rb_mem_clear(local_vars, body->nd_tbl[0]);
+		GC_REFRESH(ruby_scope, body);
 		ruby_scope->local_tbl = body->nd_tbl;
 		ruby_scope->local_vars = local_vars;
 	    }
Index: gc.c
===================================================================
RCS file: /src/ruby/gc.c,v
retrieving revision 1.69
diff -u -r1.69 gc.c
--- gc.c	2001/06/12 05:31:46	1.69
+++ gc.c	2001/06/19 15:05:06
@@ -248,18 +248,33 @@
 	struct RVarmap varmap; 
 	struct SCOPE   scope;
     } as;
+    struct RVALUE *next;
 } RVALUE;
 
+static struct ref_list {
+  RVALUE *ptr;
+  struct ref_list *next;
+} *referencedlist = 0, *newdatalist = 0;
+
 static RVALUE *freelist = 0;
+static RVALUE *recycledlist = 0;
+static RVALUE *newlist = 0;
+static RVALUE *refreshedlist = 0;
 static RVALUE *deferred_final_list = 0;
+static RVALUE *datalist = 0;
 
 #define HEAPS_INCREMENT 10
 static RVALUE **heaps;
 static int heaps_length = 0;
 static int heaps_used   = 0;
 
+#define ON 1
+#define OFF 0
+static int need_call_major_gc = 0;
+
 #define HEAP_SLOTS 10000
 #define FREE_MIN  4096
+#define FREE_MIN_MINOR  2000
 
 static RVALUE *himem, *lomem;
 
@@ -291,17 +306,26 @@
     }
 }
 #define RANY(o) ((RVALUE*)(o))
-
+#define OBJ_SIZE 5
 VALUE
 rb_newobj()
 {
     VALUE obj;
-
-    if (!freelist) rb_gc();
 
-    obj = (VALUE)freelist;
-    freelist = freelist->as.free.next;
-    MEMZERO((void*)obj, RVALUE, 1);
+    if (!freelist && !recycledlist) rb_gc();
+    
+    if (freelist) {
+	obj = (VALUE)freelist;
+	freelist = freelist->as.free.next;
+	RANY(obj)->next = newlist;
+	newlist = RANY(obj);
+	MEMZERO((void*)obj, VALUE, OBJ_SIZE);
+    }
+    else {
+	obj = (VALUE)recycledlist;
+	recycledlist = recycledlist->as.free.next;
+	MEMZERO((void*)obj, VALUE, OBJ_SIZE);
+    }
     return obj;
 }
 
@@ -312,12 +336,21 @@
     RUBY_DATA_FUNC dmark;
     RUBY_DATA_FUNC dfree;
 {
+    struct ref_list *tmp;
+
     NEWOBJ(data, struct RData);
     OBJSETUP(data, klass, T_DATA);
     data->data = datap;
     data->dfree = dfree;
     data->dmark = dmark;
 
+    if (dmark) {
+	tmp = ALLOC(struct ref_list);
+	tmp->next = newdatalist;
+	tmp->ptr = (RVALUE *)data;
+	newdatalist = tmp;
+    }
+
     return (VALUE)data;
 }
 
@@ -390,6 +423,30 @@
     st_foreach(tbl, mark_entry, 0);
 }
 
+void
+rb_gc_refresh(obj)
+     void *obj;
+{
+    RVALUE *tmp = RANY(obj);
+
+    tmp->as.basic.flags &= ~FL_MARK;
+    tmp->next = refreshedlist;
+    refreshedlist = tmp;
+}
+
+void
+rb_gc_check_ref(obj)
+     void *obj;
+{
+    RVALUE *p = RANY(obj);
+    struct ref_list *tmp;
+
+    tmp = ALLOC(struct ref_list);
+    tmp->next = referencedlist;
+    tmp->ptr = p;
+    referencedlist = tmp;
+}
+
 static int
 mark_hashentry(key, value)
     VALUE key;
@@ -669,30 +726,98 @@
 static void
 gc_sweep()
 {
-    RVALUE *p, *pend, *final_list;
+    RVALUE *p, *pend, *final_list, *tmplist;
+    struct ref_list *rlist, *rtmp;
     int freed = 0;
     int i, used = heaps_used;
 
     if (ruby_in_compile) {
 	/* should not reclaim nodes during compilation */
-	for (i = 0; i < used; i++) {
-	    p = heaps[i]; pend = p + HEAP_SLOTS;
-	    while (p < pend) {
-		if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE)
-		    rb_gc_mark((VALUE)p);
-		p++;
-	    }
+	for (p = newlist; p; p = p->next) {
+	    if (!(p->as.basic.flags&FL_MARK) && BUILTIN_TYPE(p) == T_NODE)
+		rb_gc_mark((VALUE)p);
 	}
     }
 
-    freelist = 0;
     final_list = deferred_final_list;
     deferred_final_list = 0;
-    for (i = 0; i < used; i++) {
-	int n = 0;
+    recycledlist = 0;
+    if (need_call_major_gc) { /* major gc*/
+	for (i = 0; i < used; i++) {
+	    int n = 0;
 
-	p = heaps[i]; pend = p + HEAP_SLOTS;
-	while (p < pend) {
+	    p = heaps[i]; pend = p + HEAP_SLOTS;
+	    while (p < pend) {
+		if (!(p->as.basic.flags & FL_MARK)) {
+		    if (p->as.basic.flags) {
+			obj_free((VALUE)p);
+		    }
+		    if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
+			p->as.free.flags = FL_MARK; /* remain marked */
+			p->as.free.next = final_list;
+			final_list = p;
+		    }
+		    else {
+			p->as.free.flags = 0;
+			p->as.free.next = freelist;
+			freelist = p;
+		    }
+		    n++;
+		}
+		else if (RBASIC(p)->flags == FL_MARK) {
+		    /* objects to be finalized */
+		    /* do notning remain marked */
+		}
+		else {
+		}
+		p++;
+	    }
+	    freed += n;
+	}
+	need_call_major_gc = OFF;
+	if (freed < FREE_MIN) {
+	    add_heap();
+	}
+	/*----- datalist -----*/
+	tmplist = 0;
+	rlist = newdatalist;
+	while (rlist) {
+	    p = rlist->ptr;
+	    if (p->as.basic.flags & FL_MARK) {
+		p->as.basic.flags &= ~FL_MARK;
+		p->next = tmplist;
+		tmplist = p;
+	    }
+	    rtmp = rlist;
+	    rlist = rlist->next;
+	    free(rtmp);
+	}
+	newdatalist = 0;
+	/* clear datalist */
+	while (datalist) {
+	    p = datalist;
+	    datalist = datalist->next;
+	    if (p->as.basic.flags & FL_MARK) {
+		p->as.basic.flags &= ~FL_MARK;
+		p->next = tmplist;
+		tmplist = p;
+	    }
+	    else {
+		obj_free((VALUE)p);
+		p->as.free.flags = 0;
+		p->as.free.next = freelist;
+		freelist = p;
+	    }
+	}
+	datalist = tmplist;
+    }
+    else { /*minor gc*/
+	/* datalist */
+	for (p = datalist; p; p = p->next)
+	    rb_gc_mark((VALUE)p);
+	    
+	for (p = newlist; p; p = pend) {
+	    pend = p->next;
 	    if (!(p->as.basic.flags & FL_MARK)) {
 		if (p->as.basic.flags) {
 		    obj_free((VALUE)p);
@@ -707,22 +832,47 @@
 		    p->as.free.next = freelist;
 		    freelist = p;
 		}
-		n++;
+		freed++;
 	    }
 	    else if (RBASIC(p)->flags == FL_MARK) {
 		/* objects to be finalized */
 		/* do notning remain marked */
 	    }
 	    else {
-		RBASIC(p)->flags &= ~FL_MARK;
+		/* Maybe, no need*/
+		/*p->flags &= ~FL_MARK;*/
 	    }
-	    p++;
 	}
-	freed += n;
-    }
-    if (freed < FREE_MIN) {
-	add_heap();
+	newlist = 0;
+	if (freed < FREE_MIN_MINOR) {
+	    need_call_major_gc = ON;
+	}
+	/*----- datalist -----*/
+    	tmplist = 0;
+	rlist = newdatalist;
+	while (rlist) {
+	    p = rlist->ptr;
+	    if (p->as.basic.flags & FL_MARK) {
+		p->as.basic.flags &= ~FL_MARK;
+		p->next = tmplist;
+		tmplist = p;
+	    }
+	    rtmp = rlist;
+	    rlist = rlist->next;
+	    free(rtmp);
+	}
+	newdatalist = 0;
+	/* join datalist */
+	while (datalist) {
+	    p = datalist;
+	    datalist = datalist->next;
+	    p->as.basic.flags &= ~FL_MARK;
+	    p->next = tmplist;
+	    tmplist = p;
+	}
+	datalist = tmplist;
     }
+
     during_gc = 0;
 
     /* clear finalization list */
@@ -748,9 +898,16 @@
 rb_gc_force_recycle(p)
     VALUE p;
 {
-    RANY(p)->as.free.flags = 0;
-    RANY(p)->as.free.next = freelist;
-    freelist = RANY(p);
+    if (RANY(p)->as.basic.flags & FL_MARK) {
+	RANY(p)->as.free.flags = 0;
+	RANY(p)->as.free.next = freelist;
+	freelist = RANY(p);
+    }
+    else {
+	RANY(p)->as.free.flags = 0;
+	RANY(p)->as.free.next = recycledlist;
+	recycledlist = RANY(p);
+    }
 }
 
 static void
@@ -932,6 +1089,8 @@
 rb_gc()
 {
     struct gc_list *list;
+    struct ref_list *rlist, *rtmp;
+    struct RVALUE *p, *pend;
     struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug??  */
     jmp_buf save_regs_gc_mark;
 #ifdef C_ALLOCA
@@ -959,6 +1118,31 @@
 
     if (during_gc) return;
     during_gc++;
+    
+    /* check old gc */
+    if (need_call_major_gc) {
+	int i;
+	/* clear flags of all objects in heap */
+	for (i = 0; i < heaps_used; i++) {
+	    p = heaps[i]; pend = p + HEAP_SLOTS;
+	    while (p < pend) {
+		p->as.basic.flags &= ~FL_MARK;
+		p++;
+	    }
+	}
+	/* reset lists */
+	freelist = 0;
+	refreshedlist = 0;
+	newlist = 0;
+	/* clear referenced list */
+	rlist = referencedlist;
+	while (rlist){
+	    rtmp = rlist;
+	    rlist = rlist->next;
+	    free(rtmp);
+	}
+	referencedlist = 0;
+    }    
 
     /* mark frame stack */
     for (frame = ruby_frame; frame; frame = frame->prev) {
@@ -1002,7 +1186,23 @@
     /* mark generic instance variables for special constants */
     rb_mark_generic_ivar_tbl();
 
+    /* mark refreshedlist objects */
+    for (p = refreshedlist; p; p = p->next) {
+	rb_gc_mark((VALUE)p);
+    }
+    refreshedlist = 0;
+    /* mark referenced list*/
+    rlist = referencedlist;
+    while (rlist){
+	rb_gc_mark((VALUE)rlist->ptr);
+	rtmp = rlist;
+	rlist = rlist->next;
+	free(rtmp);
+    }
+    referencedlist = 0;
+
     gc_sweep();
+    if (!freelist && !recycledlist) rb_gc();
 }
 
 VALUE
Index: hash.c
===================================================================
RCS file: /src/ruby/hash.c,v
retrieving revision 1.48
diff -u -r1.48 hash.c
--- hash.c	2001/06/12 05:31:46	1.48
+++ hash.c	2001/06/19 15:05:11
@@ -341,6 +341,7 @@
     VALUE hash, ifnone;
 {
     rb_hash_modify(hash);
+    GC_REFRESH(hash, ifnone);
     RHASH(hash)->ifnone = ifnone;
     return hash;
 }
@@ -500,11 +501,15 @@
     VALUE hash, key, val;
 {
     rb_hash_modify(hash);
+    GC_CHECK_REF(hash, val);
     if (TYPE(key) != T_STRING || st_lookup(RHASH(hash)->tbl, key, 0)) {
-	st_insert(RHASH(hash)->tbl, key, val);
+	if (!st_insert(RHASH(hash)->tbl, key, val))
+	    GC_CHECK_REF(hash, key);
     }
     else {
-	st_add_direct(RHASH(hash)->tbl, rb_str_new4(key), val);
+	VALUE nkey = rb_str_new4(key);
+	GC_CHECK_REF(hash, nkey);
+	st_add_direct(RHASH(hash)->tbl, nkey, val);	
     }
     return val;
 }
@@ -1408,7 +1413,9 @@
 	    v = getenv(RSTRING(argv[i])->ptr);
 	}
 	if (v) {
-	    RARRAY(indexes)->ptr[i] = rb_tainted_str_new2(v);
+	    VALUE tmp = rb_tainted_str_new2(v);
+	    GC_CHECK_REF(indexes, tmp);
+	    RARRAY(indexes)->ptr[i] = tmp;
 	}
 	else {
 	    RARRAY(indexes)->ptr[i] = Qnil;
Index: intern.h
===================================================================
RCS file: /src/ruby/intern.h,v
retrieving revision 1.51
diff -u -r1.51 intern.h
--- intern.h	2001/06/19 04:35:13	1.51
+++ intern.h	2001/06/19 15:05:13
@@ -191,6 +191,20 @@
 void rb_gc_force_recycle _((VALUE));
 void rb_gc _((void));
 void rb_gc_call_finalizer_at_exit _((void));
+void rb_gc_refresh();
+void rb_gc_check_ref();
+#define GC_REFRESH(from, to)				\
+do {                                                            \
+    if (!SPECIAL_CONST_P(to) && !(RBASIC(to)->flags&FL_MARK) &&	\
+	(RBASIC(from)->flags&FL_MARK)) 				\
+	rb_gc_refresh(from);					\
+} while (0);
+#define GC_CHECK_REF(from, to)				\
+do {                                                            \
+    if (!SPECIAL_CONST_P(to) && !(RBASIC(to)->flags&FL_MARK) &&	\
+	(RBASIC(from)->flags&FL_MARK)) 				\
+	rb_gc_check_ref(to);					\
+} while (0);
 /* hash.c */
 VALUE rb_hash _((VALUE));
 VALUE rb_hash_new _((void));
Index: io.c
===================================================================
RCS file: /src/ruby/io.c,v
retrieving revision 1.88
diff -u -r1.88 io.c
--- io.c	2001/06/19 04:35:13	1.88
+++ io.c	2001/06/19 15:05:23
@@ -1939,6 +1939,7 @@
 	rb_io_binmode(io);
     }
 
+    GC_REFRESH(io, RBASIC(nfile)->klass);
     RBASIC(io)->klass = RBASIC(nfile)->klass;
     return io;
 }
Index: marshal.c
===================================================================
RCS file: /src/ruby/marshal.c,v
retrieving revision 1.37
diff -u -r1.37 marshal.c
--- marshal.c	2001/06/05 07:19:38	1.37
+++ marshal.c	2001/06/19 15:05:30
@@ -799,6 +799,7 @@
 	    if (rb_special_const_p(v)) {
 		rb_raise(rb_eArgError, "dump format error (user class)");
 	    }
+	    GC_REFRESH(v, c);
 	    RBASIC(v)->klass = c;
 	    return v;
 	}
Index: object.c
===================================================================
RCS file: /src/ruby/object.c,v
retrieving revision 1.52
diff -u -r1.52 object.c
--- object.c	2001/06/05 07:50:59	1.52
+++ object.c	2001/06/19 15:05:32
@@ -632,7 +632,8 @@
 {
     VALUE mod = rb_module_new();
 
-    RBASIC(mod)->klass = klass;
+    GC_REFRESH(mod, klass);
+    RBASIC(mod)->klass = klass;/*gc?*/
     rb_obj_call_init(klass, 0, 0);
     return mod;
 }
@@ -642,7 +643,7 @@
     int argc;
     VALUE *argv;
 {
-    VALUE super, klass;
+    VALUE super, klass, tmp;
 
     if (rb_scan_args(argc, argv, "01", &super) == 0) {
 	super = rb_cObject;
@@ -653,7 +654,9 @@
     }
     klass = rb_class_new(super);
     /* make metaclass */
-    RBASIC(klass)->klass = rb_singleton_class_new(RBASIC(super)->klass);
+    tmp = rb_singleton_class_new(RBASIC(super)->klass);
+    GC_REFRESH(klass, tmp);
+    RBASIC(klass)->klass = tmp;   
     rb_singleton_class_attached(RBASIC(klass)->klass, klass);
     rb_obj_call_init(klass, argc, argv);
     rb_funcall(super, rb_intern("inherited"), 1, klass);
Index: parse.y
===================================================================
RCS file: /src/ruby/parse.y,v
retrieving revision 1.109
diff -u -r1.109 parse.y
--- parse.y	2001/06/08 14:20:20	1.109
+++ parse.y	2001/06/19 15:05:47
@@ -421,6 +421,7 @@
 		| mlhs '=' command_call
 		    {
 			value_expr($3);
+			GC_REFRESH($1, $3);
 			$1->nd_value = $3;
 			$$ = $1;
 		    }
@@ -431,6 +432,7 @@
 		| mlhs '=' mrhs
 		    {
 			value_expr($3);
+			GC_REFRESH($1, $3);
 			$1->nd_value = $3;
 			$$ = $1;
 		    }
@@ -694,6 +696,7 @@
 		| variable tOP_ASGN {$$ = assignable($1, 0);} arg
 		    {
 			if ($2 == tOROP) {
+			    GC_REFRESH($<node>3, $4);
 			    $<node>3->nd_value = $4;
 			    $$ = NEW_OP_ASGN_OR(gettable($1), $<node>3);
 			    if (is_instance_id($1)) {
@@ -701,13 +704,16 @@
 			    }
 			}
 			else if ($2 == tANDOP) {
+			    GC_REFRESH($<node>3, $4);
 			    $<node>3->nd_value = $4;
 			    $$ = NEW_OP_ASGN_AND(gettable($1), $<node>3);
 			}
 			else {
 			    $$ = $<node>3;
 			    if ($$) {
-				$$->nd_value = call_op(gettable($1),$2,1,$4);
+				NODE *tmp = call_op(gettable($1),$2,1,$4);
+				GC_REFRESH($$, tmp);
+				$$->nd_value = tmp;
 			    }
 			}
 			fixpos($$, $4);
@@ -804,7 +810,9 @@
 			      case T_FLOAT:
 			      case T_BIGNUM:
 				if (RTEST(rb_funcall($1->nd_lit,'<',1,INT2FIX(0)))) {
-				    $1->nd_lit = rb_funcall($1->nd_lit,rb_intern("-@"),0,0);
+				    VALUE tmp = rb_funcall($1->nd_lit,rb_intern("-@"),0,0);
+				    GC_REFRESH($1, tmp);
+				    $1->nd_lit = tmp;
 				    need_negate = Qtrue;
 				}
 			      default:
@@ -1249,7 +1257,9 @@
 		    }
 		| operation brace_block
 		    {
-			$2->nd_iter = NEW_FCALL($1, 0);
+			NODE *tmp = NEW_FCALL($1, 0);
+			GC_REFRESH($2, tmp);
+			$2->nd_iter = tmp;
 			$$ = $2;
 		    }
 		| method_call
@@ -1258,6 +1268,7 @@
 			if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
 			    rb_compile_error("both block arg and actual block given");
 			}
+			GC_REFRESH($2, $1);
 			$2->nd_iter = $1;
 			$$ = $2;
 		        fixpos($$, $1);
@@ -1512,6 +1523,7 @@
 			if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
 			    rb_compile_error("both block arg and actual block given");
 			}
+			GC_REFRESH($2, $1);
 			$2->nd_iter = $1;
 			$$ = $2;
 		        fixpos($$, $2);
@@ -1665,13 +1677,16 @@
 		    }
 		| string tDSTRING
 		    {
+			NODE *tmp;
 		        if (nd_type($1) == NODE_STR) {
 			    $$ = NEW_DSTR($1->nd_lit);
 			}
 			else {
 			    $$ = $1;
 			}
-			$2->nd_head = NEW_STR($2->nd_lit);
+			tmp = NEW_STR($2->nd_lit);
+			GC_REFRESH($2, tmp);
+			$2->nd_head = tmp;
 			nd_set_type($2, NODE_ARRAY);
 			list_concat($$, $2);
 		    }
@@ -4052,7 +4067,9 @@
 	tail = NEW_BLOCK(tail);
 	tail->nd_end = tail;
     }
+    GC_REFRESH(end, tail);
     end->nd_next = tail;
+    GC_REFRESH(head, tail->nd_end);
     head->nd_end = tail->nd_end;
     return head;
 }
@@ -4061,7 +4078,7 @@
 list_append(head, tail)
     NODE *head, *tail;
 {
-    NODE *last;
+    NODE *last, *tmp;
 
     if (head == 0) return NEW_LIST(tail);
 
@@ -4070,7 +4087,9 @@
 	last = last->nd_next;
     }
 
-    last->nd_next = NEW_LIST(tail);
+    tmp = NEW_LIST(tail);
+    GC_REFRESH(last, tmp);
+    last->nd_next = tmp;
     head->nd_alen += 1;
     return head;
 }
@@ -4085,7 +4104,8 @@
     while (last->nd_next) {
 	last = last->nd_next;
     }
-
+    
+    GC_REFRESH(last, tail);
     last->nd_next = tail;
     head->nd_alen += tail->nd_alen;
 
@@ -4313,6 +4333,8 @@
 node_assign(lhs, rhs)
     NODE *lhs, *rhs;
 {
+    NODE *tmp;
+
     if (!lhs) return 0;
 
     value_expr(rhs);
@@ -4326,11 +4348,14 @@
       case NODE_CDECL:
       case NODE_CVDECL:
       case NODE_CVASGN:
+	GC_REFRESH(lhs, rhs);
 	lhs->nd_value = rhs;
 	break;
 
       case NODE_CALL:
-	lhs->nd_args = arg_add(lhs->nd_args, rhs);
+	tmp = arg_add(lhs->nd_args, rhs);
+	GC_REFRESH(lhs, tmp);
+	lhs->nd_args = tmp;
 	break;
 
       default:
@@ -4594,6 +4619,7 @@
     NODE *node;
     int logop;
 {
+    NODE *tmp;
     enum node_type type = nd_type(node);
 
     assign_in_cond(node);
@@ -4613,8 +4639,12 @@
 
       case NODE_DOT2:
       case NODE_DOT3:
-	node->nd_beg = range_op(node->nd_beg, logop);
-	node->nd_end = range_op(node->nd_end, logop);
+	tmp = range_op(node->nd_beg, logop);
+	GC_REFRESH(node, tmp);
+	node->nd_beg = tmp;
+	tmp = range_op(node->nd_end, logop);
+	GC_REFRESH(node, tmp);
+	node->nd_end = tmp;
 	if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
 	else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
 	node->nd_cnt = local_append(0);
@@ -4639,7 +4669,9 @@
 {
     if (node == 0) return 0;
     if (nd_type(node) == NODE_NEWLINE){
-	node->nd_next = cond0(node->nd_next, logop);
+	NODE *tmp = cond0(node->nd_next, logop);
+	GC_REFRESH(node, tmp);
+	node->nd_next = tmp;
 	return node;
     }
     return cond0(node, logop);
@@ -4685,6 +4717,7 @@
     NODE *node2;
 {
     if (node2) {
+	GC_REFRESH(node2, node1);
 	node2->nd_head = node1;
 	return node2;
     }
@@ -4719,7 +4752,9 @@
     NODE *a;
 {
     if (a && nd_type(a) == NODE_BLOCK_PASS) {
-	a->nd_iter = NEW_CALL(r,m,a->nd_head);
+	NODE *tmp = NEW_CALL(r,m,a->nd_head);
+	GC_REFRESH(a, tmp);
+	a->nd_iter = tmp;
 	return a;
     }
     return NEW_CALL(r,m,a);
@@ -4731,7 +4766,9 @@
     NODE *a;
 {
     if (a && nd_type(a) == NODE_BLOCK_PASS) {
-	a->nd_iter = NEW_FCALL(m,a->nd_head);
+	NODE *tmp = NEW_FCALL(m,a->nd_head);
+	GC_REFRESH(a, tmp);
+	a->nd_iter = tmp;
 	return a;
     }
     return NEW_FCALL(m,a);
@@ -4742,7 +4779,9 @@
     NODE *a;
 {
     if (a && nd_type(a) == NODE_BLOCK_PASS) {
-	a->nd_iter = NEW_SUPER(a->nd_head);
+	NODE *tmp = NEW_SUPER(a->nd_head);
+	GC_REFRESH(a, tmp);
+	a->nd_iter = tmp;
 	return a;
     }
     return NEW_SUPER(a);
Index: re.c
===================================================================
RCS file: /src/ruby/re.c,v
retrieving revision 1.43
diff -u -r1.43 re.c
--- re.c	2001/05/30 09:12:34	1.43
+++ re.c	2001/06/19 15:05:52
@@ -600,7 +600,7 @@
     int pos, reverse;
 {
     int result;
-    VALUE match;
+    VALUE match, tmp;
     static struct re_registers regs;
     int range;
 
@@ -646,7 +646,9 @@
 	match = match_alloc();
     }
     re_copy_registers(RMATCH(match)->regs, &regs);
-    RMATCH(match)->str = rb_str_new4(str);
+    tmp = rb_str_new4(str);
+    GC_REFRESH(match, tmp);
+    RMATCH(match)->str = tmp;    
     rb_backref_set(match);
 
     OBJ_INFECT(match, re);
Index: string.c
===================================================================
RCS file: /src/ruby/string.c,v
retrieving revision 1.67
diff -u -r1.67 string.c
--- string.c	2001/05/30 09:12:34	1.67
+++ string.c	2001/06/19 15:06:01
@@ -124,6 +124,7 @@
 
 	str->len = RSTRING(orig)->len;
 	str->ptr = RSTRING(orig)->ptr;
+	GC_REFRESH(orig, str);
 	RSTRING(orig)->orig = (VALUE)str;
 	str->orig = 0;
 	OBJ_INFECT(str, orig);
@@ -206,12 +207,21 @@
 rb_str_associate(str, add)
     VALUE str, add;
 {
+    VALUE tmp;
+
     if (!FL_TEST(str, STR_NO_ORIG)) {
 	if (RSTRING(str)->orig) {
 	    rb_str_modify(str);
 	}
+<<<<<<< string.c
+	tmp = rb_ary_new();
+	GC_REFRESH(str, tmp);
+	RSTRING(str)->orig = tmp;	
+	FL_SET(str, STR_NO_ORIG);
+=======
 	RSTRING(str)->orig = rb_ary_new();
 	FL_SET(str, STR_NO_ORIG|STR_ASSOC);
+>>>>>>> 1.67
     }
     rb_ary_push(RSTRING(str)->orig, add);
 }
Index: struct.c
===================================================================
RCS file: /src/ruby/struct.c,v
retrieving revision 1.22
diff -u -r1.22 struct.c
--- struct.c	2001/05/30 09:12:34	1.22
+++ struct.c	2001/06/19 15:06:03
@@ -477,6 +477,7 @@
     len = RARRAY(member)->len;
     for (i=0; i<len; i++) {
 	if (SYM2ID(RARRAY(member)->ptr[i]) == id) {
+	    GC_REFRESH(s, val);
 	    RSTRUCT(s)->ptr[i] = val;
 	    return val;
 	}
@@ -505,6 +506,7 @@
 		 i, RSTRUCT(s)->len);
     }
     if (OBJ_FROZEN(s)) rb_error_frozen("Struct");
+    GC_REFRESH(s, val);
     return RSTRUCT(s)->ptr[i] = val;
 }
 
Index: variable.c
===================================================================
RCS file: /src/ruby/variable.c,v
retrieving revision 1.40
diff -u -r1.40 variable.c
--- variable.c	2001/06/08 16:15:03	1.40
+++ variable.c	2001/06/19 15:06:07
@@ -153,6 +153,7 @@
 
 	if (st_lookup(ROBJECT(klass)->iv_tbl, classid, &path)) {
 	    path = rb_str_new2(rb_id2name(SYM2ID(path)));
+	    GC_REFRESH(klass, path);
 	    st_insert(ROBJECT(klass)->iv_tbl, classpath, path);
 	    st_delete(RCLASS(klass)->iv_tbl, &classid, 0);
 	}
@@ -924,6 +925,7 @@
       case T_CLASS:
       case T_MODULE:
 	if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable();
+	GC_REFRESH(obj, val);
 	st_insert(ROBJECT(obj)->iv_tbl, id, val);
 	break;
       default:
@@ -1293,6 +1295,7 @@
 	rb_warn("already initialized %s %s", dest, rb_id2name(id));
     }
 
+    GC_REFRESH(klass, val);
     st_insert(RCLASS(klass)->iv_tbl, id, val);
 }
 
@@ -1315,6 +1318,7 @@
     
     while (tmp) {
 	if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
+	    GC_REFRESH(tmp, val);
 	    st_insert(RCLASS(tmp)->iv_tbl, id, val);
 	    return;
 	}
@@ -1323,6 +1327,7 @@
     /* pre-defined class */
     if (st_lookup(rb_class_tbl, id, 0)) {
 	st_delete(rb_class_tbl, id, 0);
+	GC_REFRESH(rb_cObject, val);
 	st_insert(RCLASS(rb_cObject)->iv_tbl, id, val);
 	return;
     }
@@ -1333,6 +1338,7 @@
 
 	st_delete(autoload_tbl, &id, &modname);
 	free(modname);
+	GC_REFRESH(rb_cObject, val);
 	st_insert(RCLASS(rb_cObject)->iv_tbl, id, val);
 	return;
     }
@@ -1396,6 +1402,7 @@
 	if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
 	    if (!OBJ_TAINTED(tmp) && rb_safe_level() >= 4)
 		rb_raise(rb_eSecurityError, "Insecure: can't modify class variable");
+	    GC_REFRESH(tmp, val);
 	    st_insert(RCLASS(tmp)->iv_tbl,id,val);
 	    return;
 	}
@@ -1419,6 +1426,7 @@
 	if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,0)) {
 	    if (!OBJ_TAINTED(tmp) && rb_safe_level() >= 4)
 		rb_raise(rb_eSecurityError, "Insecure: can't modify class variable");
+	    GC_REFRESH(tmp, val);
 	    st_insert(RCLASS(tmp)->iv_tbl,id,val);
 	    return;
 	}
