summaryrefslogtreecommitdiff
path: root/gc.c
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1995-01-10 00:58:20 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 22:09:31 +0900
commit5d828b25d4ae30a000c054a724ac248dadbb97b3 (patch)
tree080fc6e3b41b9c59cf5def77ae619a82e7e252db /gc.c
parentbd0c733b77b561f4d12daccebf06a7c71917000b (diff)
version 0.64v0_64
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.64.tar.gz Tue Jan 10 00:58:20 1995 Yukihiro Matsumoto (matz@dyna) * eval.c: レシーバと引数は常にiterではない. * cons.c(aref,aset): negative offset対応. Mon Jan 9 14:40:39 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: foo{..}の形式において,fooをローカル変数やクラス名では なく,引数なしの関数型メソッド呼び出しとみなすようにした. * list.c -> cons.c: 名称変更(クラス名も). * list.c: a::b::c::nilをリスト(a b c)とみなすlisp形式から,a::b::c をリスト(a b c)とみなすruby形式に変更.[], []=, eachもそれに会わ せた仕様とする. * list.c: consペアとしての機能を強調.仕様変更. Sat Jan 7 01:26:26 1995 Yukihiro Matsumoto (matz@dyna) * eval.c: 自己代入の不具合修正. * eval.c(masign): 多重代入が配列もリストもとれるようにした. * list.c: assocを2要素の配列からList(CONSペア)に変更した. Fri Jan 6 13:42:12 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: a[b]+=cやa.b+=cなどの自己代入形式で,aやbを2度評価しな くなった. * eval.c: iterator設定のバグフィックス. * list.c: Listクラスを新設. Thu Jan 5 13:55:00 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: SCOPEのメモリリークをなくした. * eval.c: built-inメソッドへの引数の引き渡し方を変更して,配列の生 成数を減らした. * re.c: match-dataを毎回生成することをやめた.`$~'をアクセスした時 にon-demandで生成する. * string.c etc: 不必要なmemmoveをmemcpyに置換. * parse.y: =~, !~は副作用があるのでコンパイル時に展開できない. Tue Jan 3 02:04:36 1995 Yukihiro Matsumoto (matz@dyna) * eval.c: rest引数のbug fix. * eval.c,gc.c: scopeをオブジェクトにした. * eval.c: envとscopeの扱いを変更した. Wed Dec 28 09:46:57 1994 Yukihiro Matsumoto (matz@ix-02) * parse.y: evalでローカル変数が追加された場合に対応した. * parse.y: 演算子を含むaliasのbug fix. Tue Dec 27 16:45:20 1994 Yukihiro Matsumoto (matz@ix-02) * parse.y: def A Bをalias A Bに変更. * eval.c: alias関係のbug修正.nodeをオブジェクト化した時にenbugし たようだ. * signal.c: システムコールの再定義を止めた. * io.c(select): write/exceptのフラグ設定にバグ. * Makefile.in: static link用オプションをMake変数として独立させた.
Diffstat (limited to 'gc.c')
-rw-r--r--gc.c152
1 files changed, 86 insertions, 66 deletions
diff --git a/gc.c b/gc.c
index 780d1902f8..af6741f6ca 100644
--- a/gc.c
+++ b/gc.c
@@ -3,7 +3,7 @@
gc.c -
$Author: matz $
- $Date: 1994/12/19 08:39:19 $
+ $Date: 1995/01/10 10:42:37 $
created at: Tue Oct 5 09:44:46 JST 1993
Copyright (C) 1994 Yukihiro Matsumoto
@@ -170,6 +170,7 @@ struct RVALUE {
UINT flag; /* always 0 for freed obj */
struct RVALUE *next;
} free;
+ struct RBasic basic;
struct RObject object;
struct RClass class;
struct RFloat flonum;
@@ -181,6 +182,8 @@ struct RVALUE {
struct RStruct rstruct;
struct RBignum bignum;
struct RNode node;
+ struct RCons cons;
+ struct SCOPE scope;
} as;
} *freelist = Qnil;
@@ -193,8 +196,7 @@ struct heap_block {
#define SEG_SLOTS 10000
#define SEG_SIZE (SEG_SLOTS*sizeof(struct RVALUE))
-
-static int heap_size;
+#define FREE_MIN 512
static void
add_heap()
@@ -203,7 +205,7 @@ add_heap()
struct RVALUE *p, *pend;
block = (struct heap_block*)malloc(sizeof(*block) + SEG_SIZE);
- if (block == Qnil) Fatal("cant alloc memory");
+ if (block == Qnil) Fatal("can't alloc memory");
block->next = heap_link;
block->beg = &block->body[0];
block->end = block->beg + SEG_SLOTS;
@@ -215,7 +217,6 @@ add_heap()
p++;
}
heap_link = block;
- heap_size += SEG_SLOTS;
}
struct RBasic *
@@ -227,8 +228,7 @@ newobj()
retry:
obj = (struct RBasic*)freelist;
freelist = freelist->as.free.next;
- obj->flags = 0;
- obj->iv_tbl = Qnil;
+ memset(obj, 0, sizeof(struct RVALUE));
return obj;
}
if (dont_gc) add_heap();
@@ -349,40 +349,40 @@ gc_mark_maybe(obj)
void
gc_mark(obj)
- register struct RBasic *obj;
+ register struct RVALUE *obj;
{
if (obj == Qnil) return;
if (FIXNUM_P(obj)) return;
- if (obj->flags & FL_MARK) return;
+ if (obj->as.basic.flags & FL_MARK) return;
- obj->flags |= FL_MARK;
+ obj->as.basic.flags |= FL_MARK;
- switch (obj->flags & T_MASK) {
+ switch (obj->as.basic.flags & T_MASK) {
case T_NIL:
case T_FIXNUM:
Bug("gc_mark() called for broken object");
break;
}
- switch (obj->flags & T_MASK) {
+ switch (obj->as.basic.flags & T_MASK) {
case T_ICLASS:
- gc_mark(RCLASS(obj)->super);
- if (RCLASS(obj)->c_tbl) mark_tbl(RCLASS(obj)->c_tbl);
- mark_tbl(RCLASS(obj)->m_tbl);
+ gc_mark(obj->as.class.super);
+ if (obj->as.class.c_tbl) mark_tbl(obj->as.class.c_tbl);
+ mark_tbl(obj->as.class.m_tbl);
break;
case T_CLASS:
- gc_mark(RCLASS(obj)->super);
+ gc_mark(obj->as.class.super);
case T_MODULE:
- if (RCLASS(obj)->c_tbl) mark_tbl(RCLASS(obj)->c_tbl);
- mark_tbl(RCLASS(obj)->m_tbl);
- gc_mark(RBASIC(obj)->class);
+ if (obj->as.class.c_tbl) mark_tbl(obj->as.class.c_tbl);
+ mark_tbl(obj->as.class.m_tbl);
+ gc_mark(obj->as.basic.class);
break;
case T_ARRAY:
{
- int i, len = RARRAY(obj)->len;
- VALUE *ptr = RARRAY(obj)->ptr;
+ int i, len = obj->as.array.len;
+ VALUE *ptr = obj->as.array.ptr;
for (i=0; i < len; i++)
gc_mark(ptr[i]);
@@ -390,15 +390,15 @@ gc_mark(obj)
break;
case T_DICT:
- mark_dict(RDICT(obj)->tbl);
+ mark_dict(obj->as.dict.tbl);
break;
case T_STRING:
- if (RSTRING(obj)->orig) gc_mark(RSTRING(obj)->orig);
+ if (obj->as.string.orig) gc_mark(obj->as.string.orig);
break;
case T_DATA:
- if (RDATA(obj)->dmark) (*RDATA(obj)->dmark)(DATA_PTR(obj));
+ if (obj->as.data.dmark) (*obj->as.data.dmark)(DATA_PTR(obj));
break;
case T_OBJECT:
@@ -409,30 +409,38 @@ gc_mark(obj)
case T_STRUCT:
{
- int i, len = RSTRUCT(obj)->len;
- struct kv_pair *ptr = RSTRUCT(obj)->tbl;
+ int i, len = obj->as.rstruct.len;
+ struct kv_pair *ptr = obj->as.rstruct.tbl;
for (i=0; i < len; i++)
gc_mark(ptr[i].value);
}
break;
+ case T_SCOPE:
+ {
+ struct SCOPE *scope = (struct SCOPE*)obj;
+ if (scope->local_vars)
+ mark_locations_array(scope->local_vars, scope->local_tbl[0]);
+ }
+ break;
+
case T_CONS:
- gc_mark(RCONS(obj)->car);
- gc_mark(RCONS(obj)->cdr);
+ gc_mark(obj->as.cons.car);
+ gc_mark(obj->as.cons.cdr);
break;
case T_NODE:
- gc_mark_maybe(RNODE(obj)->u1.node);
- gc_mark_maybe(RNODE(obj)->u2.node);
- gc_mark_maybe(RNODE(obj)->u3.node);
+ gc_mark_maybe(obj->as.node.u1.node);
+ gc_mark_maybe(obj->as.node.u2.node);
+ gc_mark_maybe(obj->as.node.u3.node);
return; /* no need to mark class & tbl */
default:
- Bug("gc_mark(): unknown data type %d", obj->flags & T_MASK);
+ Bug("gc_mark(): unknown data type %d", obj->as.basic.flags & T_MASK);
}
- if (obj->iv_tbl) mark_tbl(obj->iv_tbl);
- gc_mark(obj->class);
+ if (obj->as.basic.iv_tbl) mark_tbl(obj->as.basic.iv_tbl);
+ gc_mark(obj->as.basic.class);
}
#define MIN_FREE_OBJ 512
@@ -455,8 +463,8 @@ gc_sweep()
p = heap->beg; pend = heap->end;
while (p < pend) {
- if (!(RBASIC(p)->flags & FL_MARK)) {
- if (RBASIC(p)->flags) obj_free(p);
+ if (!(p->as.basic.flags & FL_MARK)) {
+ if (p->as.basic.flags) obj_free(p);
p->as.free.flag = 0;
p->as.free.next = nfreelist;
nfreelist = p;
@@ -480,7 +488,6 @@ gc_sweep()
}
}
free(heap);
- heap_size -= SEG_SLOTS;
heap = link;
}
else {
@@ -489,78 +496,88 @@ gc_sweep()
}
heap = heap->next;
}
- if (freed < heap_size/4) {
+ if (freed < FREE_MIN) {
add_heap();
}
}
static void
obj_free(obj)
- struct RBasic *obj;
+ struct RVALUE *obj;
{
- switch (obj->flags & T_MASK) {
+ switch (obj->as.basic.flags & T_MASK) {
case T_NIL:
case T_FIXNUM:
Bug("obj_free() called for broken object");
break;
}
- switch (obj->flags & T_MASK) {
+ switch (obj->as.basic.flags & T_MASK) {
case T_OBJECT:
break;
case T_MODULE:
case T_CLASS:
rb_clear_cache2(obj);
- st_free_table(RCLASS(obj)->m_tbl);
- if (RCLASS(obj)->c_tbl)
- st_free_table(RCLASS(obj)->c_tbl);
+ st_free_table(obj->as.class.m_tbl);
+ if (obj->as.class.c_tbl)
+ st_free_table(obj->as.class.c_tbl);
break;
case T_STRING:
- if (RSTRING(obj)->orig == Qnil) free(RSTRING(obj)->ptr);
+ if (obj->as.string.orig == Qnil) free(obj->as.string.ptr);
break;
case T_ARRAY:
- free(RARRAY(obj)->ptr);
+ free(obj->as.array.ptr);
break;
case T_DICT:
- st_free_table(RDICT(obj)->tbl);
+ st_free_table(obj->as.dict.tbl);
break;
case T_REGEXP:
- reg_free(RREGEXP(obj)->ptr);
- free(RREGEXP(obj)->str);
+ reg_free(obj->as.regexp.ptr);
+ free(obj->as.regexp.str);
break;
case T_DATA:
- if (RDATA(obj)->dfree) (*RDATA(obj)->dfree)(DATA_PTR(obj));
+ if (obj->as.data.dfree) (*obj->as.data.dfree)(DATA_PTR(obj));
free(DATA_PTR(obj));
break;
case T_ICLASS:
/* iClass shares table with the module */
case T_FLOAT:
+ case T_CONS:
break;
case T_STRUCT:
- free(RSTRUCT(obj)->name);
- free(RSTRUCT(obj)->tbl);
+ free(obj->as.rstruct.name);
+ free(obj->as.rstruct.tbl);
break;
case T_BIGNUM:
- free(RBIGNUM(obj)->digits);
+ free(obj->as.bignum.digits);
break;
case T_NODE:
- if (nd_type(obj) == NODE_SCOPE && RNODE(obj)->nd_tbl) {
- free(RNODE(obj)->nd_tbl);
+ if (nd_type(obj) == NODE_SCOPE && obj->as.node.nd_tbl) {
+ free(obj->as.node.nd_tbl);
}
return; /* no need to free iv_tbl */
+
+ case T_SCOPE:
+ {
+ struct SCOPE *scope = (struct SCOPE*)obj;
+ if (scope->local_vars)
+ free(scope->local_vars);
+ if (scope->local_tbl)
+ free(scope->local_tbl);
+ }
+ break;
+
default:
- Bug("gc_sweep(): unknown data type %d", obj->flags & T_MASK);
+ Bug("gc_sweep(): unknown data type %d", obj->as.basic.flags & T_MASK);
}
- if (obj->iv_tbl) st_free_table(obj->iv_tbl);
+ if (obj->as.basic.iv_tbl) st_free_table(obj->as.basic.iv_tbl);
}
void
-gc_mark_scope(scope)
- struct SCOPE *scope;
+gc_mark_env(env)
+ struct ENVIRON *env;
{
- if (scope->local_vars && scope->var_ary == Qnil)
- mark_locations_array(scope->local_vars, scope->local_tbl[0]);
- gc_mark(scope->var_ary);
+ mark_locations_array(env->argv, env->argc);
}
void
@@ -568,7 +585,6 @@ gc()
{
struct gc_list *list;
struct ENVIRON *env;
- struct SCOPE *scope;
int i, max;
jmp_buf save_regs_gc_mark;
VALUE stack_end;
@@ -576,9 +592,13 @@ gc()
if (dont_gc) return;
dont_gc++;
- /* mark scope stack */
- for (scope = the_scope; scope; scope = scope->prev) {
- gc_mark_scope(scope);
+#ifdef C_ALLOCA
+ alloca(0);
+#endif
+
+ /* mark env stack */
+ for (env = the_env; env; env = env->prev) {
+ gc_mark_env(env);
}
FLUSH_REGISTER_WINDOWS;