なかだです。

At Sat, 8 Sep 2001 23:14:51 +0900,
Nobuyoshi-Nakada wrote:
>  今やっぱりFRAMEに持ってこうというところがそもそも間違ってるよ
> うなので、むしろSCOPEのlocal_varsからスレッドローカル変数を独立
> させる方向で考えるべきかという気になってます。

 SCOPEはObjectだからサイズを増やせないですね。一応なんとかうま
く行きそうな感じですが、かなり不安です。

# というか激しくでかすぎ。

(1) SCOPE#local_varsからFRAME#fvarsに関数スコープな変数を移動
(2) FRAME同士は、例外を除いてNODE_SCOPE単位でfvarsを共有する
(3) 例外として、rb_eval_string_wrap()、rb_eval_cmd()、load、
    END{}、スレッド生成時には新しいfvarsを作る


Index: env.h =================================================================== RCS file: /cvs/ruby/src/ruby/env.h,v retrieving revision 1.7 diff -u -2 -p -u -r1.7 env.h --- env.h 2001/02/14 05:51:57 1.7 +++ env.h 2001/09/09 17:28:55 @@ -14,8 +14,15 @@ #define ENV_H +enum funcvar_type { + fvar_lastline, + fvar_backref, + funcvar_last +}; + extern struct FRAME { VALUE self; 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 -u -r1.203 eval.c --- eval.c 2001/09/08 14:17:09 1.203 +++ eval.c 2001/09/09 18:14:50 @@ -133,4 +133,14 @@ static VALUE safe_getter _((void)); static void safe_setter _((VALUE val)); +#define INIT_FVARS(fv) (fill_nil(fv, funcvar_last), (fv)) + +static void +fill_nil(v, i) + VALUE *v; + int i; +{ + do *v++ = Qnil; while (--i > 0); +} + void rb_secure(level) @@ -520,4 +530,5 @@ static struct SCOPE *top_scope; _frame.argc = 0; \ _frame.argv = 0; \ + _frame.fvars = ruby_frame->fvars; \ _frame.flags = FRAME_ALLOCA; \ ruby_frame = &_frame; \ @@ -1009,4 +1020,5 @@ ruby_init() static struct FRAME frame; static struct iter iter; + static VALUE funcvars[funcvar_last]; int state; @@ -1015,4 +1027,5 @@ ruby_init() initialized = 1; + frame.fvars = INIT_FVARS(funcvars); ruby_frame = top_frame = &frame; ruby_iter = &iter; @@ -1027,6 +1040,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 */ @@ -1272,4 +1283,5 @@ rb_eval_string_wrap(str, state) VALUE wrapper = ruby_wrapper; VALUE val; + VALUE funcvars[funcvar_last]; PUSH_CLASS(); @@ -1280,4 +1292,5 @@ rb_eval_string_wrap(str, state) ruby_frame->last_func = 0; ruby_frame->last_class = 0; + ruby_frame->fvars = INIT_FVARS(funcvars); ruby_frame->self = self; ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_wrapper,0,0); @@ -1332,4 +1345,5 @@ rb_eval_cmd(cmd, arg) int state; VALUE val; /* OK */ + VALUE funcvars[funcvar_last]; struct SCOPE *saved_scope; volatile int safe = ruby_safe_level; @@ -1345,4 +1359,5 @@ rb_eval_cmd(cmd, arg) ruby_frame->last_func = 0; ruby_frame->last_class = 0; + ruby_frame->fvars = INIT_FVARS(funcvars); ruby_frame->self = ruby_top_self; ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_wrapper,0,0); @@ -1708,6 +1723,33 @@ copy_node_scope(node, rval) POP_ITER();\ } + +#define LAST_LINE ruby_frame->fvars[fvar_lastline] +#define MATCH_DATA ruby_frame->fvars[fvar_backref] + +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*)); @@ -2660,7 +2702,9 @@ rb_eval(self, n) struct FRAME frame; NODE *saved_cref = 0; + VALUE funcvars[funcvar_last]; frame = *ruby_frame; frame.tmp = ruby_frame; + frame.fvars = INIT_FVARS(funcvars); ruby_frame = &frame; @@ -4459,4 +4503,5 @@ rb_call0(klass, recv, id, argc, argv, bo int state; VALUE *local_vars; /* OK */ + VALUE funcvars[funcvar_last]; NODE *saved_cref = 0; @@ -4479,4 +4524,5 @@ rb_call0(klass, recv, id, argc, argv, bo ruby_scope->local_tbl = 0; } + ruby_frame->fvars = INIT_FVARS(funcvars); b2 = body = body->nd_next; @@ -4519,11 +4565,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; @@ -5236,4 +5281,5 @@ rb_load(fname, wrap) { VALUE tmp; + VALUE funcvars[funcvar_last]; int state; volatile ID last_func; @@ -5277,4 +5323,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 = INIT_FVARS(funcvars); PUSH_SCOPE(); /* default visibility is private at loading toplevel */ @@ -5852,5 +5899,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]))); @@ -5919,4 +5966,5 @@ call_end_proc(data) VALUE data; { + VALUE funcvars[funcvar_last]; PUSH_ITER(ITER_NOT); PUSH_FRAME(); @@ -5924,4 +5972,5 @@ call_end_proc(data) ruby_frame->last_func = 0; ruby_frame->last_class = 0; + ruby_frame->fvars = INIT_FVARS(funcvars); proc_call(data, rb_ary_new2(0)); POP_FRAME(); @@ -5932,6 +5981,8 @@ static void rb_f_END() { + VALUE funcvars[funcvar_last]; PUSH_FRAME(); ruby_frame->argc = 0; + ruby_frame->fvars = INIT_FVARS(funcvars); rb_set_end_proc(call_end_proc, rb_f_lambda()); POP_FRAME(); @@ -7074,6 +7125,4 @@ struct thread { VALUE errinfo; VALUE last_status; - VALUE last_line; - VALUE last_match; int safe; @@ -7169,6 +7218,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); @@ -7210,8 +7257,14 @@ rb_gc_mark_threads() { rb_thread_t th; + int i; + VALUE *p; /* static global mark */ rb_gc_mark((VALUE)ruby_cref); + p = top_frame->fvars; + i = funcvar_last; + do {rb_gc_mark(*p++);} while (--i > 0); + if (!curr_thread) return; FOREACH_THREAD(th) { @@ -7296,10 +7349,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 +7449,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 +8251,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 +8293,4 @@ int rb_thread_tick = THREAD_TICK; #endif -#define SCOPE_SHARED FL_USER1 - #if defined(HAVE_SETITIMER) static int thread_init = 0; @@ -8322,5 +8358,4 @@ rb_thread_start_0(fn, arg, th_arg) } scope_dup(ruby_scope); - FL_SET(ruby_scope, SCOPE_SHARED); if (!th->next) { @@ -8398,10 +8433,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 +8438,6 @@ rb_thread_yield(arg, th) rb_thread_t th; { + VALUE funcvars[funcvar_last]; + ruby_block->frame.fvars = INIT_FVARS(funcvars); scope_dup(ruby_block->scope); return rb_yield_0(mvalue_to_svalue(arg), 0, 0, Qtrue); Index: intern.h =================================================================== RCS file: /cvs/ruby/src/ruby/intern.h,v retrieving revision 1.64 diff -u -2 -p -u -r1.64 intern.h --- intern.h 2001/09/05 22:31:07 1.64 +++ intern.h 2001/09/09 15:39:32 @@ -134,4 +134,8 @@ VALUE rb_dvar_ref _((ID)); void rb_dvar_asgn _((ID, VALUE)); void rb_dvar_push _((ID, VALUE)); +VALUE rb_backref_get _((void)); +void rb_backref_set _((VALUE)); +VALUE rb_lastline_get _((void)); +void rb_lastline_set _((VALUE)); VALUE rb_eval_cmd _((VALUE, VALUE)); int rb_respond_to _((VALUE, ID)); @@ -171,5 +175,4 @@ VALUE rb_thread_wakeup _((VALUE)); VALUE rb_thread_run _((VALUE)); VALUE rb_thread_create _((VALUE (*)(ANYARGS), void*)); -int rb_thread_scope_shared_p _((void)); void rb_thread_interrupt _((void)); void rb_thread_trap_eval _((VALUE, int)); @@ -270,8 +273,4 @@ int rb_is_const_id _((ID)); int rb_is_instance_id _((ID)); int rb_is_class_id _((ID)); -VALUE rb_backref_get _((void)); -void rb_backref_set _((VALUE)); -VALUE rb_lastline_get _((void)); -void rb_lastline_set _((VALUE)); VALUE rb_sym_all_symbols _((void)); /* process.c */ Index: parse.y =================================================================== RCS file: /cvs/ruby/src/ruby/parse.y,v retrieving revision 1.119 diff -u -2 -p -u -r1.119 parse.y --- parse.y 2001/09/05 06:54:53 1.119 +++ parse.y 2001/09/08 07:41:51 @@ -3587,5 +3587,4 @@ yylex() /* fall through */ case '~': /* $~: match-data */ - local_cnt(c); /* fall through */ case '*': /* $*: argv */ @@ -4122,6 +4121,4 @@ match_gen(node1, node2) NODE *node2; { - local_cnt('~'); - switch (nd_type(node1)) { case NODE_DREGX: @@ -4612,6 +4609,4 @@ cond0(node) case NODE_DREGX_ONCE: warning_unless_e_option("regex literal in condition"); - local_cnt('_'); - local_cnt('~'); return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_"))); @@ -4636,6 +4631,4 @@ cond0(node) warn_unless_e_option("regex literal in condition"); nd_set_type(node, NODE_MATCH); - local_cnt('_'); - local_cnt('~'); } else { @@ -4795,11 +4788,7 @@ local_append(id) { if (lvtbl->tbl == 0) { - lvtbl->tbl = ALLOC_N(ID, 4); + lvtbl->tbl = ALLOC_N(ID, 2); lvtbl->tbl[0] = 0; - lvtbl->tbl[1] = '_'; - lvtbl->tbl[2] = '~'; - lvtbl->cnt = 2; - if (id == '_') return 0; - if (id == '~') return 1; + lvtbl->cnt = 0; } else { @@ -4832,5 +4821,5 @@ local_id(id) if (lvtbl == 0) return Qfalse; - for (i=3, max=lvtbl->cnt+1; i<max; i++) { + for (i=1, max=lvtbl->cnt+1; i<max; i++) { if (lvtbl->tbl[i] == id) return Qtrue; } @@ -5162,58 +5151,3 @@ rb_is_instance_id(id) if (is_instance_id(id)) return Qtrue; return Qfalse; -} - -static void -special_local_set(c, val) - char c; - VALUE val; -{ - int cnt; - - top_local_init(); - cnt = local_cnt(c); - top_local_setup(); - ruby_scope->local_vars[cnt] = val; -} - -VALUE -rb_backref_get() -{ - if (ruby_scope->local_vars) { - return ruby_scope->local_vars[1]; - } - return Qnil; -} - -void -rb_backref_set(val) - VALUE val; -{ - if (ruby_scope->local_vars) { - ruby_scope->local_vars[1] = val; - } - else { - special_local_set('~', val); - } -} - -VALUE -rb_lastline_get() -{ - if (ruby_scope->local_vars) { - return ruby_scope->local_vars[0]; - } - return Qnil; -} - -void -rb_lastline_set(val) - VALUE val; -{ - if (ruby_scope->local_vars) { - ruby_scope->local_vars[0] = val; - } - else { - special_local_set('_', val); - } } Index: re.c =================================================================== RCS file: /cvs/ruby/src/ruby/re.c,v retrieving revision 1.45 diff -u -2 -p -u -r1.45 re.c --- re.c 2001/09/05 06:54:53 1.45 +++ re.c 2001/09/09 15:38:10 @@ -646,10 +646,5 @@ rb_reg_search(re, str, pos, reverse) } - if (rb_thread_scope_shared_p()) { - match = Qnil; - } - else { - match = rb_backref_get(); - } + match = rb_backref_get(); if (NIL_P(match) || FL_TEST(match, MATCH_BUSY)) { match = match_alloc();
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦