* [PATCH] compile.c: optimize literal String range in case/when dispatch
@ 2017-03-23 8:20 Eric Wong
0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2017-03-23 8:20 UTC (permalink / raw)
To: spew
This is similar in spirit to opt_case_dispatch as the literal
Range here is guaranteed to be immutable when used for
checkmatch.
Normal range literals with non-frozen strings are actually
mutable, as Range#begin and Range#end exposes the strings to
modification. So those Range objects cannot be frozen without
breaking compatibility.
* compile.c (iseq_peephole_optimize): persistent Range creation
when String literals are used as beginning and end of range
when used for case/when dispatch.
---
compile.c | 31 +++++++++++++++++++++++++++++++
test/ruby/test_optimization.rb | 15 +++++++++++++++
2 files changed, 46 insertions(+)
diff --git a/compile.c b/compile.c
index e3d66b6809..496e4d8857 100644
--- a/compile.c
+++ b/compile.c
@@ -2144,6 +2144,37 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
+ /*
+ * putstring "beg"
+ * putstring "end"
+ * newrange excl
+ *
+ * ==>
+ *
+ * putobject "beg".."end"
+ */
+ if (IS_INSN_ID(iobj, checkmatch)) {
+ INSN *range = (INSN *)get_prev_insn(iobj);
+ INSN *beg, *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 sbeg = OPERAND_AT(beg, 0);
+ VALUE send = OPERAND_AT(end, 0);
+ int excl = FIX2INT(OPERAND_AT(range, 0));
+ VALUE lit_range = rb_range_new(sbeg, send, excl);
+
+ iseq_add_mark_object_compile_time(iseq, lit_range);
+ REMOVE_ELEM(&beg->link);
+ REMOVE_ELEM(&end->link);
+ range->insn_id = BIN(putobject);
+ OPERAND_AT(range, 0) = lit_range;
+ }
+ }
+
if (IS_INSN_ID(iobj, leave)) {
remove_unreachable_chunk(iseq, iobj->link.next);
}
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index 502d12389e..aa3c82fdfd 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -490,4 +490,19 @@ def test_nil_safe_conditional_assign
bug11816 = '[ruby-core:74993] [Bug #11816]'
assert_ruby_status([], 'nil&.foo &&= false', bug11816)
end
+
+ def test_peephole_string_literal_range
+ code = <<-EOF
+ case ver
+ when "2.0.0".."2.3.2" then :foo
+ when "1.8.0"..."1.8.8" then :bar
+ end
+ EOF
+ 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
+ end
end
--
EW
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2017-03-23 8:20 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-23 8:20 [PATCH] compile.c: optimize literal String range in case/when dispatch Eric Wong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).