Feature #13715 ยป 0001-avoid-garbage-from-Symbol-to_s-in-interpolation.patch
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)
|
||
{
|
||
-
|