なかだです。

At Sat, 15 Sep 2001 15:50:11 +0900,
Nobuyoshi-Nakada wrote:
>  struct BLOCKでコピーされるのでスタックに置いておくのはダメで
> した。

 SCOPE同様GCで管理しないと無理そうなので、NODE_MEMOを流用しま
した。env.h, eval.c, gc.cのみなので、intern.h, parse.y, re.cの
分は[ruby-dev:14764]のパッチを使ってください。

 それともう一つ、NODE_FLIP{2,3}で内部的に使う変数もスレッドで
共有されているような気がしますが、これは仕様通り?


Index: env.h =================================================================== RCS file: /cvs/ruby/src/ruby/env.h,v retrieving revision 1.7 diff -u -2 -p -r1.7 env.h --- env.h 2001/02/14 05:51:57 1.7 +++ env.h 2001/09/15 04:36:05 @@ -18,4 +18,5 @@ extern struct FRAME { int argc; VALUE *argv; + VALUE fvars; ID last_func; VALUE last_class; Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.203 diff -u -2 -p -r1.203 eval.c --- eval.c 2001/09/08 14:17:09 1.203 +++ eval.c 2001/09/15 10:42:29 @@ -133,4 +133,9 @@ static VALUE safe_getter _((void)); static void safe_setter _((VALUE val)); +#define NEW_FVARS() ((VALUE)rb_node_newnode(NODE_MEMO, Qnil, Qnil, Qnil)) +#define FVARS() ((NODE *)(ruby_frame)->fvars) +#define fv_lastline u2.value +#define fv_lastmatch u3.value + void rb_secure(level) @@ -520,4 +525,5 @@ static struct SCOPE *top_scope; _frame.argc = 0; \ _frame.argv = 0; \ + _frame.fvars = ruby_frame->fvars; \ _frame.flags = FRAME_ALLOCA; \ ruby_frame = &_frame; \ @@ -1027,6 +1033,4 @@ ruby_init() Init_heap(); PUSH_SCOPE(); - ruby_scope->local_vars = 0; - ruby_scope->local_tbl = 0; top_scope = ruby_scope; /* default visibility is private at toplevel */ @@ -1036,4 +1040,5 @@ ruby_init() if ((state = EXEC_TAG()) == 0) { rb_call_inits(); + frame.fvars = NEW_FVARS(); ruby_class = rb_cObject; ruby_frame->self = ruby_top_self; @@ -1280,4 +1285,5 @@ rb_eval_string_wrap(str, state) ruby_frame->last_func = 0; ruby_frame->last_class = 0; + ruby_frame->fvars = NEW_FVARS(); ruby_frame->self = self; ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_wrapper,0,0); @@ -1345,4 +1351,5 @@ rb_eval_cmd(cmd, arg) ruby_frame->last_func = 0; ruby_frame->last_class = 0; + ruby_frame->fvars = NEW_FVARS(); ruby_frame->self = ruby_top_self; ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_wrapper,0,0); @@ -1708,7 +1715,34 @@ copy_node_scope(node, rval) POP_ITER();\ } + +#define LAST_LINE FVARS()->fv_lastline +#define MATCH_DATA FVARS()->fv_lastmatch + +VALUE +rb_backref_get() +{ + return MATCH_DATA; +} + +void +rb_backref_set(val) + VALUE val; +{ + MATCH_DATA = val; +} -#define MATCH_DATA ruby_scope->local_vars[node->nd_cnt] +VALUE +rb_lastline_get() +{ + return LAST_LINE; +} +void +rb_lastline_set(val) + VALUE val; +{ + LAST_LINE = val; +} + static char* is_defined _((VALUE, NODE*, char*)); @@ -2663,4 +2697,5 @@ rb_eval(self, n) frame = *ruby_frame; frame.tmp = ruby_frame; + frame.fvars = NEW_FVARS(); ruby_frame = &frame; @@ -4479,4 +4514,5 @@ rb_call0(klass, recv, id, argc, argv, bo ruby_scope->local_tbl = 0; } + ruby_frame->fvars = NEW_FVARS(); b2 = body = body->nd_next; @@ -4519,11 +4555,10 @@ rb_call0(klass, recv, id, argc, argv, bo } ruby_frame->argc = opt; - ruby_frame->argv = local_vars+2; + ruby_frame->argv = local_vars; } if (local_vars) { if (i > 0) { - /* +2 for $_ and $~ */ - MEMCPY(local_vars+2, argv, VALUE, i); + MEMCPY(local_vars, argv, VALUE, i); } argv += i; argc -= i; @@ -5277,4 +5312,5 @@ rb_load(fname, wrap) ruby_frame->self = self; ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0); + ruby_frame->fvars = NEW_FVARS(); PUSH_SCOPE(); /* default visibility is private at loading toplevel */ @@ -5852,5 +5888,5 @@ rb_f_local_variables() if (tbl) { n = *tbl++; - for (i=2; i<n; i++) { /* skip first 2 ($_ and $~) */ + for (i=0; i<n; i++) { if (tbl[i] == 0) continue; /* skip flip states */ rb_ary_push(ary, rb_str_new2(rb_id2name(tbl[i]))); @@ -5924,4 +5960,5 @@ call_end_proc(data) ruby_frame->last_func = 0; ruby_frame->last_class = 0; + ruby_frame->fvars = NEW_FVARS(); proc_call(data, rb_ary_new2(0)); POP_FRAME(); @@ -5934,4 +5971,5 @@ rb_f_END() PUSH_FRAME(); ruby_frame->argc = 0; + ruby_frame->fvars = NEW_FVARS(); rb_set_end_proc(call_end_proc, rb_f_lambda()); POP_FRAME(); @@ -7074,6 +7112,4 @@ struct thread { VALUE errinfo; VALUE last_status; - VALUE last_line; - VALUE last_match; int safe; @@ -7169,6 +7205,4 @@ thread_mark(th) rb_gc_mark((VALUE)th->dyna_vars); rb_gc_mark(th->errinfo); - rb_gc_mark(th->last_line); - rb_gc_mark(th->last_match); rb_mark_tbl(th->locals); @@ -7268,5 +7302,4 @@ rb_thread_save_context(th) VALUE *pos; int len; - static VALUE tval; len = stack_length(&pos); @@ -7279,5 +7312,5 @@ rb_thread_save_context(th) } th->stk_len = len; - FLUSH_REGISTER_WINDOWS; + FLUSH_REGISTER_WINDOWS; MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len); @@ -7296,10 +7329,4 @@ rb_thread_save_context(th) th->errinfo = ruby_errinfo; th->last_status = rb_last_status; - tval = rb_lastline_get(); - rb_lastline_set(th->last_line); - th->last_line = tval; - tval = rb_backref_get(); - rb_backref_set(th->last_match); - th->last_match = tval; th->safe = ruby_safe_level; @@ -7402,11 +7429,4 @@ rb_thread_restore_context(th, exit) MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len); - tval = rb_lastline_get(); - rb_lastline_set(tmp->last_line); - tmp->last_line = tval; - tval = rb_backref_get(); - rb_backref_set(tmp->last_match); - tmp->last_match = tval; - longjmp(tmp->context, ex); } @@ -8211,6 +8231,4 @@ rb_thread_abort_exc_set(thread, val) th->errinfo = Qnil;\ th->last_status = 0;\ - th->last_line = 0;\ - th->last_match = 0;\ th->abort = 0;\ th->priority = 0;\ @@ -8255,6 +8273,4 @@ int rb_thread_tick = THREAD_TICK; #endif -#define SCOPE_SHARED FL_USER1 - #if defined(HAVE_SETITIMER) static int thread_init = 0; @@ -8322,5 +8338,4 @@ rb_thread_start_0(fn, arg, th_arg) } scope_dup(ruby_scope); - FL_SET(ruby_scope, SCOPE_SHARED); if (!th->next) { @@ -8398,10 +8413,4 @@ rb_thread_create(fn, arg) } -int -rb_thread_scope_shared_p() -{ - return FL_TEST(ruby_scope, SCOPE_SHARED); -} - static VALUE rb_thread_yield(arg, th) @@ -8409,4 +8418,5 @@ rb_thread_yield(arg, th) rb_thread_t th; { + ruby_block->frame.fvars = NEW_FVARS(); scope_dup(ruby_block->scope); return rb_yield_0(mvalue_to_svalue(arg), 0, 0, Qtrue); Index: gc.c =================================================================== RCS file: /cvs/ruby/src/ruby/gc.c,v retrieving revision 1.72 diff -u -2 -p -r1.72 gc.c --- gc.c 2001/07/20 15:19:28 1.72 +++ gc.c 2001/09/15 00:03:19 @@ -908,4 +908,5 @@ rb_gc_mark_frame(frame) { mark_locations_array(frame->argv, frame->argc); + rb_gc_mark(frame->fvars); rb_gc_mark(frame->cbase); }
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦