From 897cf066952978ccbae1d57bbc14a03c7b98a1e1 Mon Sep 17 00:00:00 2001 From: Yukihiro Matsumoto Date: Wed, 1 Feb 1995 19:48:24 +0900 Subject: version 0.65 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.65.tar.gz Wed Feb 1 19:48:24 1995 Yukihiro Matsumoto (matz@ix-02) * string.c(str_replace): 置き換える文字列の長さが等しい時メモリコ ピーをしない. * string.c(rindex): バグ修正. Mon Jan 30 11:23:05 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y(value_expr): ifのチェックを追加. * gc.c(gc_mark): free cellの扱いにバグ. * parse.y: 文法の変更(よりシンプルに).例外を減らした. Thu Jan 26 00:52:55 1995 Yukihiro Matsumoto (matz@dyna) * parse.y: 引数として連想配列を置くことができるように.この場合, 連想配列リテラルが最終引数となる. * parse.y: 配列参照の`[]'内が空でもよいことにした. Tue Jan 24 14:45:15 1995 Yukihiro Matsumoto (matz@ix-02) * class.c(rb_include_module): `-v'を指定した時にはincludeしたモジュー ルとクラス定数が衝突していないかチェックする. Mon Jan 23 10:42:09 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y(rb_class2name): メタクラスに関するbug fix. * dict.c: Dict[..]で辞書の生成が出来るように. * array.c: Array[..]で配列の生成が出来るように. * parse.y: 辞書の表現として{a,b,..}という形式も許すように. Fri Jan 20 10:28:38 1995 Yukihiro Matsumoto (matz@ix-02) * re.c(Regexp.quote): 正規表現をエスケープするメソッド. * 無駄なrb_intern()を減らした. * parse.y: `!', `!=', `!~'を特殊演算子にする.よってこれらは再定義 できなくなった. Wed Jan 18 13:20:41 1995 Yukihiro Matsumoto (matz@ix-02) * parse.y: 文法の整理(unless,untilをなくした). Tue Jan 17 11:11:27 1995 Yukihiro Matsumoto (matz@ix-02) * eval.c: defでメソッド再定義時にはスーパークラスのメソッドの可視 性を継承する.最初の定義の時は今までと同じデフォルト(トップレベ ルで関数的,クラス定義内で通常メソッド). * object.c(Class::new): オブジェクトの生成時に関数的メ ソッドinit_objectが必ず呼ばれるように変更. * eval.c: 未定義のメソッドに対してunknownメソッドが呼ばれるように なった.エラー表示が今までと同じになるようにenvを調節している. Fri Jan 13 14:40:30 1995 Yukihiro Matsumoto (matz@ix-02) * gc.c: gcを若干書き換えて整理した.が,あまり変化はなかったようだ. * parse.y(yylex): symbolを\symから:symに変更した. Thu Jan 12 01:39:28 1995 Yukihiro Matsumoto (matz@dyna) * eval.c: 新規関数 rb_eval_string(). * gc.c: gc_mark()を一部非再帰化. * variable.c(rb_ivar_{get,set}): インスタンス変数のアクセス周りで チェックが足りなかった. * variable.c: クラス定数とインスタンス変数でハッシュテーブルを共有 するようにした. * ruby.h: iv_tblをRBasicからRObjectとRClassへ移動した.これにより, ObjectとClass,Moduleしかインスタンス変数を持てなくなる.が,メモ リ効率は若干向上する. --- gc.c | 166 ++++++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 84 insertions(+), 82 deletions(-) (limited to 'gc.c') diff --git a/gc.c b/gc.c index af6741f6ca..ec07c0fa95 100644 --- a/gc.c +++ b/gc.c @@ -3,7 +3,7 @@ gc.c - $Author: matz $ - $Date: 1995/01/10 10:42:37 $ + $Date: 1995/01/12 08:54:47 $ created at: Tue Oct 5 09:44:46 JST 1993 Copyright (C) 1994 Yukihiro Matsumoto @@ -164,7 +164,7 @@ rb_global_variable(var) Global_List = tmp; } -struct RVALUE { +typedef struct RVALUE { union { struct { UINT flag; /* always 0 for freed obj */ @@ -185,50 +185,53 @@ struct RVALUE { struct RCons cons; struct SCOPE scope; } as; -} *freelist = Qnil; +} RVALUE; -struct heap_block { - struct heap_block *next; - struct RVALUE *beg; - struct RVALUE *end; - struct RVALUE body[1]; -} *heap_link = Qnil; +RVALUE *freelist = Qnil; -#define SEG_SLOTS 10000 -#define SEG_SIZE (SEG_SLOTS*sizeof(struct RVALUE)) +#define HEAPS_INCREMENT 10 +static RVALUE **heaps; +static int heaps_length = 0; +static int heaps_used = 0; + +#define HEAP_SLOTS 10000 #define FREE_MIN 512 static void add_heap() { - struct heap_block *block; - struct RVALUE *p, *pend; - - block = (struct heap_block*)malloc(sizeof(*block) + SEG_SIZE); - if (block == Qnil) Fatal("can't alloc memory"); - block->next = heap_link; - block->beg = &block->body[0]; - block->end = block->beg + SEG_SLOTS; - p = block->beg; pend = block->end; + RVALUE *p, *pend; + + if (heaps_used == heaps_length) { + /* Realloc heaps */ + heaps_length += HEAPS_INCREMENT; + heaps = (heaps_used)? + (RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE)): + (RVALUE**)malloc(heaps_length*sizeof(RVALUE)); + if (heaps == Qnil) Fatal("can't alloc memory"); + } + + p = heaps[heaps_used++] = (RVALUE*)malloc(sizeof(RVALUE)*HEAP_SLOTS); + if (p == Qnil) Fatal("can't alloc memory"); + pend = p + HEAP_SLOTS; + while (p < pend) { p->as.free.flag = 0; p->as.free.next = freelist; freelist = p; p++; } - heap_link = block; } struct RBasic * newobj() { struct RBasic *obj; - if (heap_link == Qnil) add_heap(); if (freelist) { retry: obj = (struct RBasic*)freelist; freelist = freelist->as.free.next; - memset(obj, 0, sizeof(struct RVALUE)); + memset(obj, 0, sizeof(RVALUE)); return obj; } if (dont_gc) add_heap(); @@ -259,16 +262,17 @@ static VALUE *stack_start_ptr; static long looks_pointerp(p) - struct RVALUE *p; + register RVALUE *p; { - struct heap_block *heap = heap_link; - - if (FIXNUM_P(p)) return FALSE; - while (heap) { - if (heap->beg <= p && p < heap->end - && ((((char*)p)-((char*)heap->beg))%sizeof(struct RVALUE)) == 0) + register RVALUE *heap_org; + register long i, j, n; + + /* if p looks as a SCM pointer mark location */ + for (i=0; i < heaps_used; i++) { + heap_org = heaps[i]; + if (heap_org <= p && p < heap_org + HEAP_SLOTS + && ((((char*)p)-((char*)heap_org))%sizeof(RVALUE)) == 0) return TRUE; - heap = heap->next; } return FALSE; } @@ -349,11 +353,13 @@ gc_mark_maybe(obj) void gc_mark(obj) - register struct RVALUE *obj; + register RVALUE *obj; { - if (obj == Qnil) return; - if (FIXNUM_P(obj)) return; - if (obj->as.basic.flags & FL_MARK) return; + Top: + if (obj == Qnil) return; /* nil not marked */ + if (FIXNUM_P(obj)) return; /* fixnum not marked */ + if (obj->as.basic.flags == 0) return; /* free cell */ + if (obj->as.basic.flags & FL_MARK) return; /* marked */ obj->as.basic.flags |= FL_MARK; @@ -362,21 +368,34 @@ gc_mark(obj) case T_FIXNUM: Bug("gc_mark() called for broken object"); break; + + case T_NODE: + if (looks_pointerp(obj->as.node.u1.node)) { + gc_mark(obj->as.node.u1.node); + } + if (looks_pointerp(obj->as.node.u2.node)) { + gc_mark(obj->as.node.u2.node); + } + if (looks_pointerp(obj->as.node.u3.node)) { + obj = (RVALUE*)obj->as.node.u3.node; + goto Top; + } + return; /* no need to mark class. */ } + gc_mark(obj->as.basic.class); switch (obj->as.basic.flags & T_MASK) { case T_ICLASS: gc_mark(obj->as.class.super); - if (obj->as.class.c_tbl) mark_tbl(obj->as.class.c_tbl); + if (obj->as.class.iv_tbl) mark_tbl(obj->as.class.iv_tbl); mark_tbl(obj->as.class.m_tbl); break; case T_CLASS: gc_mark(obj->as.class.super); case T_MODULE: - 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); + if (obj->as.class.iv_tbl) mark_tbl(obj->as.class.iv_tbl); break; case T_ARRAY: @@ -402,6 +421,9 @@ gc_mark(obj) break; case T_OBJECT: + if (obj->as.object.iv_tbl) mark_tbl(obj->as.object.iv_tbl); + break; + case T_REGEXP: case T_FLOAT: case T_BIGNUM: @@ -427,20 +449,12 @@ gc_mark(obj) case T_CONS: gc_mark(obj->as.cons.car); - gc_mark(obj->as.cons.cdr); - break; - - case T_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 */ + obj = (RVALUE*)obj->as.cons.cdr; + goto Top; default: Bug("gc_mark(): unknown data type %d", obj->as.basic.flags & T_MASK); } - if (obj->as.basic.iv_tbl) mark_tbl(obj->as.basic.iv_tbl); - gc_mark(obj->as.basic.class); } #define MIN_FREE_OBJ 512 @@ -450,19 +464,19 @@ static void obj_free(); static void gc_sweep() { - struct heap_block *heap = heap_link; int freed = 0; + int i; freelist = Qnil; - while (heap) { - struct RVALUE *p, *pend; - struct RVALUE *nfreelist; + for (i = 0; i < heaps_used; i++) { + RVALUE *p, *pend; + RVALUE *nfreelist; int n = 0; nfreelist = freelist; - p = heap->beg; pend = heap->end; + p = heaps[i]; pend = p + HEAP_SLOTS; + while (p < pend) { - if (!(p->as.basic.flags & FL_MARK)) { if (p->as.basic.flags) obj_free(p); p->as.free.flag = 0; @@ -470,31 +484,12 @@ gc_sweep() nfreelist = p; n++; } - RBASIC(p)->flags &= ~FL_MARK; + else + RBASIC(p)->flags &= ~FL_MARK; p++; } - if (n == SEG_SLOTS) { - struct heap_block *link = heap_link; - if (heap != link) { - while (link) { - if (link->next && link->next == heap) { - link->next = heap->next; - break; - } - link = link->next; - } - if (link == Qnil) { - Bug("non-existing heap at 0x%x", heap); - } - } - free(heap); - heap = link; - } - else { - freed += n; - freelist = nfreelist; - } - heap = heap->next; + freed += n; + freelist = nfreelist; } if (freed < FREE_MIN) { add_heap(); @@ -503,7 +498,7 @@ gc_sweep() static void obj_free(obj) - struct RVALUE *obj; + RVALUE *obj; { switch (obj->as.basic.flags & T_MASK) { case T_NIL: @@ -514,13 +509,13 @@ obj_free(obj) switch (obj->as.basic.flags & T_MASK) { case T_OBJECT: + if (obj->as.object.iv_tbl) st_free_table(obj->as.object.iv_tbl); break; case T_MODULE: case T_CLASS: rb_clear_cache2(obj); st_free_table(obj->as.class.m_tbl); - if (obj->as.class.c_tbl) - st_free_table(obj->as.class.c_tbl); + if (obj->as.object.iv_tbl) st_free_table(obj->as.object.iv_tbl); break; case T_STRING: if (obj->as.string.orig == Qnil) free(obj->as.string.ptr); @@ -570,7 +565,6 @@ obj_free(obj) default: Bug("gc_sweep(): unknown data type %d", obj->as.basic.flags & T_MASK); } - if (obj->as.basic.iv_tbl) st_free_table(obj->as.basic.iv_tbl); } void @@ -626,13 +620,21 @@ gc() dont_gc--; } -Init_stack() +void +init_stack() { VALUE start; stack_start_ptr = &start; } +void +init_heap() +{ + init_stack(); + add_heap(); +} + Init_GC() { M_GC = rb_define_module("GC"); -- cgit v1.2.3