From: nobu.nakada@... Date: 2001-12-31T00:48:17+09:00 Subject: [ruby-dev:15609] Re: filename within eval なかだです。 At Sun, 30 Dec 2001 02:21:19 +0900, Nobuyoshi-Nakada wrote: > rb_f_eval(),specific_eval()でファイル名を指定したStringがGCされ > てしまうのが原因のようです。 > > [ruby-talk:28803]や[ruby-talk:29211]+[ruby-talk:29341]でも直り > ますが、とりあえずこんな感じでも一応直ります。 もうちょっとマシ…かどうかはともかく、新しい手を考えてみました。 たぶんGCもそれほど遅くはならないと思います。 Index: gc.c =================================================================== RCS file: /cvs/ruby/src/ruby/gc.c,v retrieving revision 1.82 diff -u -2 -p -u -r1.82 gc.c --- gc.c 2001/12/11 03:48:08 1.82 +++ gc.c 2001/12/30 15:46:01 @@ -430,4 +430,34 @@ init_mark_stack() static void rb_gc_mark_children(VALUE ptr); +static st_table *source_filenames; + +char * +rb_source_filename(f) + const char *f; +{ + VALUE name; + + if (!st_lookup(source_filenames, f, &name)) { + long len = strlen(f); + char *ptr = RSTRING(name = rb_str_new(0, sizeof(VALUE) + len))->ptr; + *(VALUE *)ptr = name; + MEMCPY(ptr += sizeof(VALUE), f, char, len); + OBJ_FREEZE(name); + st_add_direct(source_filenames, ptr, name); + return ptr; + } + return RSTRING(name)->ptr + sizeof(VALUE); +} + +static void +mark_source_filename(f) + const char *f; +{ + if (f) { + VALUE name = *(VALUE *)(f - sizeof(VALUE)); + FL_SET(name, FL_MARK); + } +} + static void gc_mark_all() @@ -606,4 +636,5 @@ rb_gc_mark_children(ptr) case T_NODE: + mark_source_filename(obj->as.node.nd_file); switch (nd_type(obj)) { case NODE_IF: /* 1,2,3 */ @@ -830,4 +861,11 @@ rb_gc_mark_children(ptr) static void obj_free _((VALUE)); +static enum st_retval +sweep_tbl_value(key, value) + VALUE key, value; +{ + return FL_TEST(value, FL_MARK) ? ST_CONTINUE : ST_DELETE; +} + static void gc_sweep() @@ -849,4 +887,6 @@ gc_sweep() } + st_foreach(source_filenames, sweep_tbl_value, 0); + freelist = 0; final_list = deferred_final_list; @@ -1514,3 +1554,5 @@ Init_GC() rb_gc_unregister_address(&rb_mObSpace); finalizers = rb_ary_new(); + + source_filenames = st_init_strtable(); } Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.137 diff -u -2 -p -u -r1.137 parse.y --- parse.y 2001/12/22 02:51:00 1.137 +++ parse.y 2001/12/30 15:25:02 @@ -2111,4 +2111,6 @@ int ruby__end__seen; static VALUE ruby_debug_lines; +extern char *rb_source_filename _((const char *)); + static NODE* yycompile(f, line) @@ -2119,4 +2121,6 @@ yycompile(f, line) NODE *node = 0; + f = rb_source_filename(f); + if (!compile_for_eval && rb_safe_level() == 0 && rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) { @@ -2229,5 +2233,5 @@ rb_compile_file(f, file, start) ruby_sourceline = start - 1; - return yycompile(strdup(f), start); + return yycompile(f, start); } -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦