fix redefinition optimization for -"literal string" (UMinus)

Unfortunately this enlarges insns.def by yet another
instruction.  However, it is much prettier than opt_str_freeze
in use, and maybe we can avoid having so many instructions in
the future.

[ruby-core:80368]

* insns.def (DEFINE_INSN): new instruction: opt_str_uminus (maybe temporary)
* compile.c (iseq_compile_each0): split instructions
* test/ruby/test_optimization.rb (test_string_uminus): new test
* vm.c (vm_init_redefined_flag): set redefinintion flag for uminus
* vm_core.h (enum ruby_basic_operators): add BOP_UMINUS

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58144 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
normal 2017-03-27 06:12:37 +00:00
Родитель 833e42d120
Коммит 669a55dfed
5 изменённых файлов: 27 добавлений и 1 удалений

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -981,6 +981,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)

Просмотреть файл

@ -104,6 +104,11 @@ class TestRubyOptimization < Test::Unit::TestCase
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

1
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

Просмотреть файл

@ -454,6 +454,7 @@ enum ruby_basic_operators {
BOP_NEQ,
BOP_MATCH,
BOP_FREEZE,
BOP_UMINUS,
BOP_MAX,
BOP_MIN,