mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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:
parent
833e42d120
commit
669a55dfed
5 changed files with 27 additions and 1 deletions
|
@ -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) {
|
ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
|
||||||
VALUE str = rb_fstring(node->nd_recv->nd_lit);
|
VALUE str = rb_fstring(node->nd_recv->nd_lit);
|
||||||
iseq_add_mark_object(iseq, str);
|
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) {
|
if (popped) {
|
||||||
ADD_INSN(ret, line, pop);
|
ADD_INSN(ret, line, pop);
|
||||||
}
|
}
|
||||||
|
|
14
insns.def
14
insns.def
|
@ -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
|
DEFINE_INSN
|
||||||
opt_newarray_max
|
opt_newarray_max
|
||||||
(rb_num_t num)
|
(rb_num_t num)
|
||||||
|
|
|
@ -104,6 +104,11 @@ class TestRubyOptimization < Test::Unit::TestCase
|
||||||
assert_redefine_method('String', 'freeze', 'assert_nil "foo".freeze')
|
assert_redefine_method('String', 'freeze', 'assert_nil "foo".freeze')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_string_uminus
|
||||||
|
assert_same "foo".freeze, -"foo"
|
||||||
|
assert_redefine_method('String', '-@', 'assert_nil(-"foo")')
|
||||||
|
end
|
||||||
|
|
||||||
def test_string_freeze_saves_memory
|
def test_string_freeze_saves_memory
|
||||||
n = 16384
|
n = 16384
|
||||||
data = '.'.freeze
|
data = '.'.freeze
|
||||||
|
|
1
vm.c
1
vm.c
|
@ -1569,6 +1569,7 @@ vm_init_redefined_flag(void)
|
||||||
OP(Succ, SUCC), (C(Integer), C(String), C(Time));
|
OP(Succ, SUCC), (C(Integer), C(String), C(Time));
|
||||||
OP(EqTilde, MATCH), (C(Regexp), C(String));
|
OP(EqTilde, MATCH), (C(Regexp), C(String));
|
||||||
OP(Freeze, FREEZE), (C(String));
|
OP(Freeze, FREEZE), (C(String));
|
||||||
|
OP(UMinus, UMINUS), (C(String));
|
||||||
OP(Max, MAX), (C(Array));
|
OP(Max, MAX), (C(Array));
|
||||||
OP(Min, MIN), (C(Array));
|
OP(Min, MIN), (C(Array));
|
||||||
#undef C
|
#undef C
|
||||||
|
|
|
@ -454,6 +454,7 @@ enum ruby_basic_operators {
|
||||||
BOP_NEQ,
|
BOP_NEQ,
|
||||||
BOP_MATCH,
|
BOP_MATCH,
|
||||||
BOP_FREEZE,
|
BOP_FREEZE,
|
||||||
|
BOP_UMINUS,
|
||||||
BOP_MAX,
|
BOP_MAX,
|
||||||
BOP_MIN,
|
BOP_MIN,
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue