1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

compile.c: fix string Range optimization with FSL

The optimization in [Feature #13355] needs to be detected
differently to work with "frozen_string_literal: true"

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62177 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
normal 2018-02-03 07:25:21 +00:00
parent 55e606b36c
commit bd5406dfa9
2 changed files with 29 additions and 14 deletions

View file

@ -2454,6 +2454,20 @@ same_debug_pos_p(LINK_ELEMENT *iobj1, LINK_ELEMENT *iobj2)
return TRUE;
}
static int
is_frozen_putstring(INSN *insn, VALUE *op)
{
if (IS_INSN_ID(insn, putstring)) {
*op = OPERAND_AT(insn, 0);
return 1;
}
else if (IS_INSN_ID(insn, putobject)) { /* frozen_string_literal */
*op = OPERAND_AT(insn, 0);
return RB_TYPE_P(*op, T_STRING);
}
return 0;
}
static int
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
{
@ -2574,16 +2588,15 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* putobject "beg".."end"
*/
if (IS_INSN_ID(iobj, checkmatch)) {
INSN *range = (INSN *)get_prev_insn(iobj);
INSN *beg, *end;
INSN *range = (INSN *)get_prev_insn(iobj);
INSN *beg, *end;
VALUE str_beg, str_end;
if (range && IS_INSN_ID(range, newrange) &&
(end = (INSN *)get_prev_insn(range)) != 0 &&
IS_INSN_ID(end, putstring) &&
(beg = (INSN *)get_prev_insn(end)) != 0 &&
IS_INSN_ID(beg, putstring)) {
VALUE str_beg = OPERAND_AT(beg, 0);
VALUE str_end = OPERAND_AT(end, 0);
(end = (INSN *)get_prev_insn(range)) != 0 &&
is_frozen_putstring(end, &str_end) &&
(beg = (INSN *)get_prev_insn(end)) != 0 &&
is_frozen_putstring(beg, &str_beg)) {
int excl = FIX2INT(OPERAND_AT(range, 0));
VALUE lit_range = rb_range_new(str_beg, str_end, excl);

View file

@ -557,12 +557,14 @@ class TestRubyOptimization < Test::Unit::TestCase
when "1.8.0"..."1.8.8" then :bar
end
end;
iseq = RubyVM::InstructionSequence.compile(code)
insn = iseq.disasm
assert_match %r{putobject\s+#{Regexp.quote('"1.8.0"..."1.8.8"')}}, insn
assert_match %r{putobject\s+#{Regexp.quote('"2.0.0".."2.3.2"')}}, insn
assert_no_match(/putstring/, insn)
assert_no_match(/newrange/, insn)
[ nil, { frozen_string_literal: true } ].each do |opt|
iseq = RubyVM::InstructionSequence.compile(code, nil, nil, opt)
insn = iseq.disasm
assert_match %r{putobject\s+#{Regexp.quote('"1.8.0"..."1.8.8"')}}, insn
assert_match %r{putobject\s+#{Regexp.quote('"2.0.0".."2.3.2"')}}, insn
assert_no_match(/putstring/, insn)
assert_no_match(/newrange/, insn)
end
end
def test_branch_condition_backquote