Project

General

Profile

Feature #13715 ยป 0001-avoid-garbage-from-Symbol-to_s-in-interpolation.patch

normalperson (Eric Wong), 07/04/2017 10:04 PM

View differences:

benchmark/bm_vm2_dstr_digit.rb
i = 0
x = 0
y = 9
while i<6_000_000 # benchmark loop 2
i += 1
str = "foo#{x}bar#{y}baz"
end
benchmark/bm_vm2_dstr_int.rb
i = 0
while i<6_000_000 # benchmark loop 2
i += 1
str = "foo#{i}bar#{i}baz"
end
benchmark/bm_vm2_dstr_nil.rb
i = 0
x = y = nil
while i<6_000_000 # benchmark loop 2
i += 1
str = "foo#{x}bar#{y}baz"
end
benchmark/bm_vm2_dstr_sym.rb
i = 0
x = y = :z
while i<6_000_000 # benchmark loop 2
i += 1
str = "foo#{x}bar#{y}baz"
end
compile.c
ADD_INSN(ret, line, pop);
}
else {
ADD_INSN(ret, line, tostring);
ADD_INSN2(ret, line, tostring,
new_callinfo(iseq, idTo_s, 0, 0, NULL, FALSE),
NULL/* CALL_CACHE */);
}
break;
}
insns.def
*/
DEFINE_INSN
tostring
()
(CALL_INFO ci, CALL_CACHE cc)
(VALUE val)
(VALUE val)
{
val = rb_obj_as_string(val);
val = vm_tostring(th, val, ci, cc);
}
/**
test/ruby/test_optimization.rb
def t; if false; case 42; when s {}; end; end; end
end;
end
def test_tostring
before = GC.stat(:total_allocated_objects)
3.times { "x #{:total_allocated_objects}" }
assert_equal before + 3, GC.stat(:total_allocated_objects)
s = :total_allocated_objects
assert_equal 'total_allocated_objects!', "#{s}" << '!', 'result mutable'
assert_redefine_method('Symbol', 'to_s', <<-'end')
assert_match %r{\A#<Symbol:0x[0-9a-f]+>\z}, "#{:foo}"
end
end
end
vm_eval.c
return vm_call0_cfunc_with_frame(th, calling, ci, cc, argv);
}
VALUE
rb_vm_call0_body(rb_thread_t *th, struct rb_calling_info *calling,
const struct rb_call_info *ci, struct rb_call_cache *cc,
const VALUE *argv)
{
return vm_call0_body(th, calling, ci, cc, argv);
}
/* `ci' should point temporal value (on stack value) */
static VALUE
vm_call0_body(rb_thread_t* th, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc, const VALUE *argv)
vm_insnhelper.c
}
}
/* vm_eval.c */
VALUE rb_vm_call0_body(rb_thread_t *, struct rb_calling_info *,
const struct rb_call_info *, struct rb_call_cache *,
const VALUE *argv);
static VALUE
vm_tostring(rb_thread_t *th, VALUE recv, CALL_INFO ci, CALL_CACHE cc)
{
struct rb_calling_info calling;
VALUE val;
if (RB_TYPE_P(recv, T_STRING)) {
return recv;
}
if (RB_TYPE_P(recv, T_SYMBOL)) {
vm_search_method(ci, cc, recv);
if (check_cfunc(cc->me, rb_sym_to_s)) {
return rb_sym2str(recv);
}
/* TODO: digits (0-9), maybe true/false/nil... */
}
else {
vm_search_method(ci, cc, recv);
}
calling.block_handler = VM_BLOCK_HANDLER_NONE;
calling.argc = 0;
calling.recv = recv;
val = rb_vm_call0_body(th, &calling, ci, cc, 0);
return RB_TYPE_P(val, T_STRING) ? val : rb_any_to_s(recv);
}
static void
vm_freezestring(VALUE str, VALUE debug)
{
-
    (1-1/1)