diff --git a/ChangeLog b/ChangeLog index 75046c625b..4ab0191ce5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Mon Dec 10 15:11:06 2012 Nobuyoshi Nakada + + * compile.c (iseq_compile_each): count flip-flop state in local iseq + not in each iseqs, so that the keys can be other than hidden + strings. [ruby-core:47253] [Bug #6899] + + * vm_insnhelper.c (lep_svar_get, lep_svar_set, vm_getspecial): store + flip-flop states in an array instead of a hash. + + * iseq.c (set_relation): main iseq also can has local scope. + Mon Dec 10 10:36:12 2012 Narihiro Nakamura * lib/irb/magic-file.rb: set a encoding, which is detected from diff --git a/compile.c b/compile.c index 5d219af65e..09e966d0f2 100644 --- a/compile.c +++ b/compile.c @@ -4977,12 +4977,14 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) LABEL *lend = NEW_LABEL(nd_line(node)); LABEL *lfin = NEW_LABEL(nd_line(node)); LABEL *ltrue = NEW_LABEL(nd_line(node)); - VALUE key = rb_sprintf("flipflag/%s-%p-%d", - RSTRING_PTR(iseq->location.label), (void *)iseq, - iseq->compile_data->flip_cnt++); + struct iseq_compile_data *data = iseq->local_iseq->compile_data; + rb_num_t cnt; + VALUE key; + + if (!data) data = iseq->compile_data; + cnt = data->flip_cnt++ + DEFAULT_SPECIAL_VAR_COUNT; + key = INT2FIX(cnt); - hide_obj(key); - iseq_add_mark_object_compile_time(iseq, key); ADD_INSN2(ret, nd_line(node), getspecial, key, INT2FIX(0)); ADD_INSNL(ret, nd_line(node), branchif, lend); diff --git a/insns.def b/insns.def index 8a0f91f6c1..7ada586d0a 100644 --- a/insns.def +++ b/insns.def @@ -95,7 +95,7 @@ setlocal */ DEFINE_INSN getspecial -(VALUE key, rb_num_t type) +(rb_num_t key, rb_num_t type) () (VALUE val) { @@ -109,7 +109,7 @@ getspecial */ DEFINE_INSN setspecial -(VALUE key) +(rb_num_t key) (VALUE obj) () { diff --git a/iseq.c b/iseq.c index 42eba6eb25..78e33b0d96 100644 --- a/iseq.c +++ b/iseq.c @@ -231,6 +231,10 @@ set_relation(rb_iseq_t *iseq, const VALUE parent) GetISeqPtr(parent, piseq); iseq->parent_iseq = piseq; } + + if (type == ISEQ_TYPE_MAIN) { + iseq->local_iseq = iseq; + } } static VALUE diff --git a/iseq.h b/iseq.h index 47aaa1a7c8..4a7965adf9 100644 --- a/iseq.h +++ b/iseq.h @@ -131,6 +131,8 @@ enum defined_type { VALUE rb_iseq_defined_string(enum defined_type type); +#define DEFAULT_SPECIAL_VAR_COUNT 2 + #if defined __GNUC__ && __GNUC__ >= 4 #pragma GCC visibility pop #endif diff --git a/test/ruby/test_flip.rb b/test/ruby/test_flip.rb new file mode 100644 index 0000000000..8d7cdd03ad --- /dev/null +++ b/test/ruby/test_flip.rb @@ -0,0 +1,13 @@ +require 'test/unit' +require_relative 'envutil' + +class TestFlip < Test::Unit::TestCase + def test_hidden_key + bug6899 = '[ruby-core:47253]' + foo = "foor" + bar = "bar" + assert_nothing_raised(NotImplementedError, bug6899) do + 2000.times {eval %[(foo..bar) ? 1 : 2]} + end + end +end diff --git a/vm_insnhelper.c b/vm_insnhelper.c index f2c8c40e8c..ff59a609e5 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -180,7 +180,7 @@ lep_svar_place(rb_thread_t *th, VALUE *lep) } static VALUE -lep_svar_get(rb_thread_t *th, VALUE *lep, VALUE key) +lep_svar_get(rb_thread_t *th, VALUE *lep, rb_num_t key) { NODE *svar = lep_svar_place(th, lep); @@ -190,20 +190,20 @@ lep_svar_get(rb_thread_t *th, VALUE *lep, VALUE key) case 1: return svar->u2.value; default: { - const VALUE hash = svar->u3.value; + const VALUE ary = svar->u3.value; - if (hash == Qnil) { + if (NIL_P(ary)) { return Qnil; } else { - return rb_hash_lookup(hash, key); + return rb_ary_entry(ary, key - DEFAULT_SPECIAL_VAR_COUNT); } } } } static void -lep_svar_set(rb_thread_t *th, VALUE *lep, VALUE key, VALUE val) +lep_svar_set(rb_thread_t *th, VALUE *lep, rb_num_t key, VALUE val) { NODE *svar = lep_svar_place(th, lep); @@ -215,27 +215,23 @@ lep_svar_set(rb_thread_t *th, VALUE *lep, VALUE key, VALUE val) svar->u2.value = val; return; default: { - VALUE hash = svar->u3.value; + VALUE ary = svar->u3.value; - if (hash == Qnil) { - svar->u3.value = hash = rb_hash_new(); + if (NIL_P(ary)) { + svar->u3.value = ary = rb_ary_new(); } - rb_hash_aset(hash, key, val); + rb_ary_store(ary, key - DEFAULT_SPECIAL_VAR_COUNT, val); } } } static inline VALUE -vm_getspecial(rb_thread_t *th, VALUE *lep, VALUE key, rb_num_t type) +vm_getspecial(rb_thread_t *th, VALUE *lep, rb_num_t key, rb_num_t type) { VALUE val; if (type == 0) { - VALUE k = key; - if (FIXNUM_P(key)) { - k = FIX2INT(key); - } - val = lep_svar_get(th, lep, k); + val = lep_svar_get(th, lep, key); } else { VALUE backref = lep_svar_get(th, lep, 1);