From 4d2ce0cbff3cee1119fb664bca5f67332a94dadd Mon Sep 17 00:00:00 2001 From: normal Date: Mon, 7 Dec 2015 23:56:57 +0000 Subject: insns.def (opt_case_dispatch): check Float#=== redefinition The missing check for Float#=== redefinition was noticed while working on enhancing optimized case dispatch for nil/true/false in [ruby-core:71818] https://bugs.ruby-lang.org/issues/11769 So no, I don't normally redefine core classes like this :P * insns.def (opt_case_dispatch): check Float#=== redefinition * test/ruby/test_optimization.rb (test_opt_case_dispatch): new [ruby-core:71920] [Bug #11784] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52928 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 ++++++ insns.def | 1 + test/ruby/test_optimization.rb | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0b2c00d92d..f3cf0bc332 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Tue Dec 8 08:56:16 2015 Eric Wong + + * insns.def (opt_case_dispatch): check Float#=== redefinition + * test/ruby/test_optimization.rb (test_opt_case_dispatch): new + [ruby-core:71920] [Bug #11784] + Tue Dec 8 03:56:05 2015 Koichi Sasada * test/lib/iseq_loader_checker.rb: add iseq dumper/loader checker. diff --git a/insns.def b/insns.def index 36a132b585..c8088919c5 100644 --- a/insns.def +++ b/insns.def @@ -1271,6 +1271,7 @@ opt_case_dispatch if (BASIC_OP_UNREDEFINED_P(BOP_EQQ, SYMBOL_REDEFINED_OP_FLAG | FIXNUM_REDEFINED_OP_FLAG | + FLOAT_REDEFINED_OP_FLAG | BIGNUM_REDEFINED_OP_FLAG | STRING_REDEFINED_OP_FLAG)) { st_data_t val; diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index e2efc9d11c..23c522612f 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -308,4 +308,45 @@ class TestRubyOptimization < Test::Unit::TestCase assert_equal(false, "block".freeze) end; end + + def test_opt_case_dispatch + code = <<-EOF + case foo + when "foo" then :foo + when :sym then :sym + when 6 then :fix + when 0.1 then :float + when 0xffffffffffffffff then :big + else + :nomatch + end + EOF + check = { + 'foo' => :foo, + :sym => :sym, + 6 => :fix, + 0.1 => :float, + 0xffffffffffffffff => :big, + } + iseq = RubyVM::InstructionSequence.compile(code) + assert_match %r{\bopt_case_dispatch\b}, iseq.disasm + check.each do |foo, expect| + assert_equal expect, eval("foo = #{foo.inspect}\n#{code}") + end + assert_equal :nomatch, eval("foo = :blah\n#{code}") + check.each do |foo, _| + klass = foo.class.to_s + assert_separately([], <<-"end;") # do + class #{klass} + undef === + def ===(*args) + false + end + end + foo = #{foo.inspect} + ret = #{code} + assert_equal :nomatch, ret, foo.inspect + end; + end + end end -- cgit v1.2.3