summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compile.c29
-rw-r--r--test/ruby/test_optimization.rb14
2 files changed, 29 insertions, 14 deletions
diff --git a/compile.c b/compile.c
index 315e2dc92e..c7d6a41f99 100644
--- a/compile.c
+++ b/compile.c
@@ -2455,6 +2455,20 @@ same_debug_pos_p(LINK_ELEMENT *iobj1, LINK_ELEMENT *iobj2)
}
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)
{
INSN *const iobj = (INSN *)list;
@@ -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);
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index e8b4f92d92..ac3440a665 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -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