* eval.c, intern.h (rb_svar): return reference to special variable
from local variable index. [new] * eval.c (rb_eval): use rb_svar() for NODE_FLIP{2,3}. * parse.y (rb_(backref|lastline)_(get|set)): access via rb_svar(). * eval.c (proc_invoke): push dynamic variables. * eval.c (rb_thread_yield): push special variables as dynamic variables($_, $~ and FLIP states). * intern.h, parse.y (rb_is_local_id): return true if the ID is local symbol. [new] * parse.y (internal_id): make new ID for internal use. [new] * parse.y (cond0): allocate internal ID for NODE_FLIP{2,3}. * eval.c (rb_f_local_variables): use rb_is_local_id() to select visible local variables. * eval.c (rb_thread_start_0): SCOPE_SHARED is removed. * eval.c, intern.h (rb_thread_scope_shared_p): removed. special variables are no longer shared by threads. * re.c (rb_reg_search): MATCHDATA is no longer shared by threads. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1752 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
6767cd760a
commit
9d61bdff14
101
eval.c
101
eval.c
@ -721,6 +721,24 @@ dvar_asgn_curr(id, value)
|
|||||||
dvar_asgn_internal(id, value, 1);
|
dvar_asgn_internal(id, value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE *
|
||||||
|
rb_svar(cnt)
|
||||||
|
int cnt;
|
||||||
|
{
|
||||||
|
struct RVarmap *vars = ruby_dyna_vars;
|
||||||
|
ID id;
|
||||||
|
|
||||||
|
if (!ruby_scope->local_tbl) return NULL;
|
||||||
|
if (cnt >= ruby_scope->local_tbl[0]) return NULL;
|
||||||
|
id = ruby_scope->local_tbl[cnt+1];
|
||||||
|
while (vars) {
|
||||||
|
if (vars->id == id) return &vars->val;
|
||||||
|
vars = vars->next;
|
||||||
|
}
|
||||||
|
if (ruby_scope->local_vars == 0) return NULL;
|
||||||
|
return &ruby_scope->local_vars[cnt];
|
||||||
|
}
|
||||||
|
|
||||||
struct iter {
|
struct iter {
|
||||||
int iter;
|
int iter;
|
||||||
struct iter *prev;
|
struct iter *prev;
|
||||||
@ -2536,40 +2554,41 @@ rb_eval(self, n)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_FLIP2: /* like AWK */
|
case NODE_FLIP2: /* like AWK */
|
||||||
if (ruby_scope->local_vars == 0) {
|
{
|
||||||
rb_bug("unexpected local variable");
|
VALUE *flip = rb_svar(node->nd_cnt);
|
||||||
}
|
if (!flip) rb_bug("unexpected local variable");
|
||||||
if (!RTEST(ruby_scope->local_vars[node->nd_cnt])) {
|
if (!RTEST(*flip)) {
|
||||||
if (RTEST(rb_eval(self, node->nd_beg))) {
|
if (RTEST(rb_eval(self, node->nd_beg))) {
|
||||||
ruby_scope->local_vars[node->nd_cnt] =
|
*flip = RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
|
||||||
RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
|
result = Qtrue;
|
||||||
result = Qtrue;
|
}
|
||||||
|
else {
|
||||||
|
result = Qfalse;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = Qfalse;
|
if (RTEST(rb_eval(self, node->nd_end))) {
|
||||||
|
*flip = Qfalse;
|
||||||
|
}
|
||||||
|
result = Qtrue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (RTEST(rb_eval(self, node->nd_end))) {
|
|
||||||
ruby_scope->local_vars[node->nd_cnt] = Qfalse;
|
|
||||||
}
|
|
||||||
result = Qtrue;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NODE_FLIP3: /* like SED */
|
case NODE_FLIP3: /* like SED */
|
||||||
if (ruby_scope->local_vars == 0) {
|
{
|
||||||
rb_bug("unexpected local variable");
|
VALUE *flip = rb_svar(node->nd_cnt);
|
||||||
}
|
if (!flip) rb_bug("unexpected local variable");
|
||||||
if (!RTEST(ruby_scope->local_vars[node->nd_cnt])) {
|
if (!RTEST(*flip)) {
|
||||||
result = RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse;
|
result = RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse;
|
||||||
ruby_scope->local_vars[node->nd_cnt] = result;
|
*flip = result;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (RTEST(rb_eval(self, node->nd_end))) {
|
if (RTEST(rb_eval(self, node->nd_end))) {
|
||||||
ruby_scope->local_vars[node->nd_cnt] = Qfalse;
|
*flip = Qfalse;
|
||||||
|
}
|
||||||
|
result = Qtrue;
|
||||||
}
|
}
|
||||||
result = Qtrue;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -5852,7 +5871,7 @@ rb_f_local_variables()
|
|||||||
if (tbl) {
|
if (tbl) {
|
||||||
n = *tbl++;
|
n = *tbl++;
|
||||||
for (i=2; i<n; i++) { /* skip first 2 ($_ and $~) */
|
for (i=2; i<n; i++) { /* skip first 2 ($_ and $~) */
|
||||||
if (tbl[i] == 0) continue; /* skip flip states */
|
if (!rb_is_local_id(tbl[i])) continue; /* skip flip states */
|
||||||
rb_ary_push(ary, rb_str_new2(rb_id2name(tbl[i])));
|
rb_ary_push(ary, rb_str_new2(rb_id2name(tbl[i])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6414,6 +6433,7 @@ proc_invoke(proc, args, pcall)
|
|||||||
volatile int orphan;
|
volatile int orphan;
|
||||||
volatile int safe = ruby_safe_level;
|
volatile int safe = ruby_safe_level;
|
||||||
volatile VALUE old_wrapper = ruby_wrapper;
|
volatile VALUE old_wrapper = ruby_wrapper;
|
||||||
|
struct RVarmap * volatile old_dvars = ruby_dyna_vars;
|
||||||
|
|
||||||
if (rb_block_given_p() && ruby_frame->last_func) {
|
if (rb_block_given_p() && ruby_frame->last_func) {
|
||||||
rb_warning("block for %s#%s is useless",
|
rb_warning("block for %s#%s is useless",
|
||||||
@ -6425,6 +6445,7 @@ proc_invoke(proc, args, pcall)
|
|||||||
orphan = blk_orphan(data);
|
orphan = blk_orphan(data);
|
||||||
|
|
||||||
ruby_wrapper = data->wrapper;
|
ruby_wrapper = data->wrapper;
|
||||||
|
ruby_dyna_vars = data->dyna_vars;
|
||||||
/* PUSH BLOCK from data */
|
/* PUSH BLOCK from data */
|
||||||
old_block = ruby_block;
|
old_block = ruby_block;
|
||||||
_block = *data;
|
_block = *data;
|
||||||
@ -6450,6 +6471,7 @@ proc_invoke(proc, args, pcall)
|
|||||||
}
|
}
|
||||||
ruby_block = old_block;
|
ruby_block = old_block;
|
||||||
ruby_wrapper = old_wrapper;
|
ruby_wrapper = old_wrapper;
|
||||||
|
ruby_dyna_vars = old_dvars;
|
||||||
ruby_safe_level = safe;
|
ruby_safe_level = safe;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@ -8254,8 +8276,6 @@ catch_timer(sig)
|
|||||||
int rb_thread_tick = THREAD_TICK;
|
int rb_thread_tick = THREAD_TICK;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SCOPE_SHARED FL_USER1
|
|
||||||
|
|
||||||
#if defined(HAVE_SETITIMER)
|
#if defined(HAVE_SETITIMER)
|
||||||
static int thread_init = 0;
|
static int thread_init = 0;
|
||||||
|
|
||||||
@ -8321,7 +8341,6 @@ rb_thread_start_0(fn, arg, th_arg)
|
|||||||
saved_block = ruby_block = dummy.prev;
|
saved_block = ruby_block = dummy.prev;
|
||||||
}
|
}
|
||||||
scope_dup(ruby_scope);
|
scope_dup(ruby_scope);
|
||||||
FL_SET(ruby_scope, SCOPE_SHARED);
|
|
||||||
|
|
||||||
if (!th->next) {
|
if (!th->next) {
|
||||||
/* merge in thread list */
|
/* merge in thread list */
|
||||||
@ -8397,18 +8416,28 @@ rb_thread_create(fn, arg)
|
|||||||
return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
|
return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
rb_thread_scope_shared_p()
|
|
||||||
{
|
|
||||||
return FL_TEST(ruby_scope, SCOPE_SHARED);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_thread_yield(arg, th)
|
rb_thread_yield(arg, th)
|
||||||
VALUE arg;
|
VALUE arg;
|
||||||
rb_thread_t th;
|
rb_thread_t th;
|
||||||
{
|
{
|
||||||
|
const ID *tbl;
|
||||||
|
|
||||||
scope_dup(ruby_block->scope);
|
scope_dup(ruby_block->scope);
|
||||||
|
|
||||||
|
tbl = ruby_scope->local_tbl;
|
||||||
|
if (tbl) {
|
||||||
|
int n = *tbl++;
|
||||||
|
for (tbl += 2, n -= 2; n > 0; --n) { /* skip first 2 ($_ and $~) */
|
||||||
|
ID id = *tbl++;
|
||||||
|
if (id != 0 && !rb_is_local_id(id)) /* push flip states */
|
||||||
|
rb_dvar_push(id, Qfalse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rb_dvar_push('_', Qnil);
|
||||||
|
rb_dvar_push('~', Qnil);
|
||||||
|
ruby_block->dyna_vars = ruby_dyna_vars;
|
||||||
|
|
||||||
return rb_yield_0(mvalue_to_svalue(arg), 0, 0, Qtrue);
|
return rb_yield_0(mvalue_to_svalue(arg), 0, 0, Qtrue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
intern.h
3
intern.h
@ -133,6 +133,7 @@ VALUE rb_dvar_curr _((ID));
|
|||||||
VALUE rb_dvar_ref _((ID));
|
VALUE rb_dvar_ref _((ID));
|
||||||
void rb_dvar_asgn _((ID, VALUE));
|
void rb_dvar_asgn _((ID, VALUE));
|
||||||
void rb_dvar_push _((ID, VALUE));
|
void rb_dvar_push _((ID, VALUE));
|
||||||
|
VALUE *rb_svar _((int));
|
||||||
VALUE rb_eval_cmd _((VALUE, VALUE));
|
VALUE rb_eval_cmd _((VALUE, VALUE));
|
||||||
int rb_respond_to _((VALUE, ID));
|
int rb_respond_to _((VALUE, ID));
|
||||||
void rb_interrupt _((void));
|
void rb_interrupt _((void));
|
||||||
@ -170,7 +171,6 @@ VALUE rb_thread_stop _((void));
|
|||||||
VALUE rb_thread_wakeup _((VALUE));
|
VALUE rb_thread_wakeup _((VALUE));
|
||||||
VALUE rb_thread_run _((VALUE));
|
VALUE rb_thread_run _((VALUE));
|
||||||
VALUE rb_thread_create _((VALUE (*)(ANYARGS), void*));
|
VALUE rb_thread_create _((VALUE (*)(ANYARGS), void*));
|
||||||
int rb_thread_scope_shared_p _((void));
|
|
||||||
void rb_thread_interrupt _((void));
|
void rb_thread_interrupt _((void));
|
||||||
void rb_thread_trap_eval _((VALUE, int));
|
void rb_thread_trap_eval _((VALUE, int));
|
||||||
void rb_thread_signal_raise _((char*));
|
void rb_thread_signal_raise _((char*));
|
||||||
@ -269,6 +269,7 @@ void rb_parser_while_loop _((int, int));
|
|||||||
int rb_is_const_id _((ID));
|
int rb_is_const_id _((ID));
|
||||||
int rb_is_instance_id _((ID));
|
int rb_is_instance_id _((ID));
|
||||||
int rb_is_class_id _((ID));
|
int rb_is_class_id _((ID));
|
||||||
|
int rb_is_local_id _((ID));
|
||||||
VALUE rb_backref_get _((void));
|
VALUE rb_backref_get _((void));
|
||||||
void rb_backref_set _((VALUE));
|
void rb_backref_set _((VALUE));
|
||||||
VALUE rb_lastline_get _((void));
|
VALUE rb_lastline_get _((void));
|
||||||
|
43
parse.y
43
parse.y
@ -30,6 +30,7 @@
|
|||||||
#define ID_CONST 0x05
|
#define ID_CONST 0x05
|
||||||
#define ID_CLASS 0x06
|
#define ID_CLASS 0x06
|
||||||
#define ID_JUNK 0x07
|
#define ID_JUNK 0x07
|
||||||
|
#define ID_INTERNAL ID_JUNK
|
||||||
|
|
||||||
#define is_notop_id(id) ((id)>LAST_TOKEN)
|
#define is_notop_id(id) ((id)>LAST_TOKEN)
|
||||||
#define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
|
#define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
|
||||||
@ -138,6 +139,7 @@ static int local_append();
|
|||||||
static int local_cnt();
|
static int local_cnt();
|
||||||
static int local_id();
|
static int local_id();
|
||||||
static ID *local_tbl();
|
static ID *local_tbl();
|
||||||
|
static ID internal_id();
|
||||||
|
|
||||||
static struct RVarmap *dyna_push();
|
static struct RVarmap *dyna_push();
|
||||||
static void dyna_pop();
|
static void dyna_pop();
|
||||||
@ -4626,7 +4628,7 @@ cond0(node)
|
|||||||
node->nd_end = range_op(node->nd_end);
|
node->nd_end = range_op(node->nd_end);
|
||||||
if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
|
if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
|
||||||
else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
|
else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
|
||||||
node->nd_cnt = local_append(0);
|
node->nd_cnt = local_append(internal_id());
|
||||||
warning_unless_e_option("range literal in condition");
|
warning_unless_e_option("range literal in condition");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -5003,11 +5005,18 @@ Init_sym()
|
|||||||
rb_global_variable((VALUE*)&lex_lastline);
|
rb_global_variable((VALUE*)&lex_lastline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ID last_id = LAST_TOKEN;
|
||||||
|
|
||||||
|
static ID
|
||||||
|
internal_id()
|
||||||
|
{
|
||||||
|
return ID_INTERNAL | (++last_id << ID_SCOPE_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
ID
|
ID
|
||||||
rb_intern(name)
|
rb_intern(name)
|
||||||
const char *name;
|
const char *name;
|
||||||
{
|
{
|
||||||
static ID last_id = LAST_TOKEN;
|
|
||||||
const char *m = name;
|
const char *m = name;
|
||||||
ID id;
|
ID id;
|
||||||
int last;
|
int last;
|
||||||
@ -5162,6 +5171,14 @@ rb_is_instance_id(id)
|
|||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_is_local_id(id)
|
||||||
|
ID id;
|
||||||
|
{
|
||||||
|
if (is_local_id(id)) return Qtrue;
|
||||||
|
return Qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
special_local_set(c, val)
|
special_local_set(c, val)
|
||||||
char c;
|
char c;
|
||||||
@ -5175,11 +5192,14 @@ special_local_set(c, val)
|
|||||||
ruby_scope->local_vars[cnt] = val;
|
ruby_scope->local_vars[cnt] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE *rb_svar _((int cnt));
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_backref_get()
|
rb_backref_get()
|
||||||
{
|
{
|
||||||
if (ruby_scope->local_vars) {
|
VALUE *var = rb_svar(1);
|
||||||
return ruby_scope->local_vars[1];
|
if (var) {
|
||||||
|
return *var;
|
||||||
}
|
}
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
@ -5188,8 +5208,9 @@ void
|
|||||||
rb_backref_set(val)
|
rb_backref_set(val)
|
||||||
VALUE val;
|
VALUE val;
|
||||||
{
|
{
|
||||||
if (ruby_scope->local_vars) {
|
VALUE *var = rb_svar(1);
|
||||||
ruby_scope->local_vars[1] = val;
|
if (var) {
|
||||||
|
*var = val;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
special_local_set('~', val);
|
special_local_set('~', val);
|
||||||
@ -5199,8 +5220,9 @@ rb_backref_set(val)
|
|||||||
VALUE
|
VALUE
|
||||||
rb_lastline_get()
|
rb_lastline_get()
|
||||||
{
|
{
|
||||||
if (ruby_scope->local_vars) {
|
VALUE *var = rb_svar(0);
|
||||||
return ruby_scope->local_vars[0];
|
if (var) {
|
||||||
|
return *var;
|
||||||
}
|
}
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
@ -5209,8 +5231,9 @@ void
|
|||||||
rb_lastline_set(val)
|
rb_lastline_set(val)
|
||||||
VALUE val;
|
VALUE val;
|
||||||
{
|
{
|
||||||
if (ruby_scope->local_vars) {
|
VALUE *var = rb_svar(0);
|
||||||
ruby_scope->local_vars[0] = val;
|
if (var) {
|
||||||
|
*var = val;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
special_local_set('_', val);
|
special_local_set('_', val);
|
||||||
|
7
re.c
7
re.c
@ -645,12 +645,7 @@ rb_reg_search(re, str, pos, reverse)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rb_thread_scope_shared_p()) {
|
match = rb_backref_get();
|
||||||
match = Qnil;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
match = rb_backref_get();
|
|
||||||
}
|
|
||||||
if (NIL_P(match) || FL_TEST(match, MATCH_BUSY)) {
|
if (NIL_P(match) || FL_TEST(match, MATCH_BUSY)) {
|
||||||
match = match_alloc();
|
match = match_alloc();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user