From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS43350 46.166.144.0/21 X-Spam-Status: No, score=-1.8 required=3.0 tests=BAYES_00,RCVD_IN_MSPIKE_BL, RCVD_IN_MSPIKE_ZBI,RCVD_IN_XBL,RDNS_NONE,SPF_FAIL,SPF_HELO_FAIL, TO_EQ_FM_DOM_SPF_FAIL shortcircuit=no autolearn=no autolearn_force=no version=3.4.0 Received: from 80x24.org (unknown [46.166.148.177]) by dcvr.yhbt.net (Postfix) with ESMTP id F169F20958 for ; Mon, 27 Mar 2017 06:07:17 +0000 (UTC) From: Eric Wong To: spew@80x24.org Subject: [PATCH] fix redefinition of for -"literal string" (UMinus) Date: Mon, 27 Mar 2017 06:07:13 +0000 Message-Id: <20170327060713.12190-1-e@80x24.org> List-Id: [ruby-core:80368] --- compile.c | 7 ++++++- insns.def | 14 ++++++++++++++ test/ruby/test_optimization.rb | 5 +++++ vm.c | 1 + vm_core.h | 1 + 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/compile.c b/compile.c index e3d66b6809..317475b525 100644 --- a/compile.c +++ b/compile.c @@ -5211,7 +5211,12 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { VALUE str = rb_fstring(node->nd_recv->nd_lit); iseq_add_mark_object(iseq, str); - ADD_INSN1(ret, line, opt_str_freeze, str); + if (node->nd_mid == idUMinus) { + ADD_INSN1(ret, line, opt_str_uminus, str); + } + else { + ADD_INSN1(ret, line, opt_str_freeze, str); + } if (popped) { ADD_INSN(ret, line, pop); } diff --git a/insns.def b/insns.def index 9bae14b5a9..a4f2526bef 100644 --- a/insns.def +++ b/insns.def @@ -982,6 +982,20 @@ opt_str_freeze } DEFINE_INSN +opt_str_uminus +(VALUE str) +() +(VALUE val) +{ + if (BASIC_OP_UNREDEFINED_P(BOP_UMINUS, STRING_REDEFINED_OP_FLAG)) { + val = str; + } + else { + val = rb_funcall(rb_str_resurrect(str), idUMinus, 0); + } +} + +DEFINE_INSN opt_newarray_max (rb_num_t num) (...) diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 502d12389e..7c8990fde8 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -104,6 +104,11 @@ def test_string_freeze assert_redefine_method('String', 'freeze', 'assert_nil "foo".freeze') end + def test_string_uminus + assert_same "foo".freeze, -"foo" + assert_redefine_method('String', '-@', 'assert_nil(-"foo")') + end + def test_string_freeze_saves_memory n = 16384 data = '.'.freeze diff --git a/vm.c b/vm.c index 1eefee18a6..9ece1b8c3d 100644 --- a/vm.c +++ b/vm.c @@ -1569,6 +1569,7 @@ vm_init_redefined_flag(void) OP(Succ, SUCC), (C(Integer), C(String), C(Time)); OP(EqTilde, MATCH), (C(Regexp), C(String)); OP(Freeze, FREEZE), (C(String)); + OP(UMinus, UMINUS), (C(String)); OP(Max, MAX), (C(Array)); OP(Min, MIN), (C(Array)); #undef C diff --git a/vm_core.h b/vm_core.h index 5b930a8aa7..437c4d9c2d 100644 --- a/vm_core.h +++ b/vm_core.h @@ -454,6 +454,7 @@ enum ruby_basic_operators { BOP_NEQ, BOP_MATCH, BOP_FREEZE, + BOP_UMINUS, BOP_MAX, BOP_MIN, -- EW