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
1
i = 0
2
x = 0
3
y = 9
4
while i<6_000_000 # benchmark loop 2
5
  i += 1
6
  str = "foo#{x}bar#{y}baz"
7
end
benchmark/bm_vm2_dstr_int.rb
1
i = 0
2
while i<6_000_000 # benchmark loop 2
3
  i += 1
4
  str = "foo#{i}bar#{i}baz"
5
end
benchmark/bm_vm2_dstr_nil.rb
1
i = 0
2
x = y = nil
3
while i<6_000_000 # benchmark loop 2
4
  i += 1
5
  str = "foo#{x}bar#{y}baz"
6
end
benchmark/bm_vm2_dstr_sym.rb
1
i = 0
2
x = y = :z
3
while i<6_000_000 # benchmark loop 2
4
  i += 1
5
  str = "foo#{x}bar#{y}baz"
6
end
compile.c
5946 5946
	    ADD_INSN(ret, line, pop);
5947 5947
	}
5948 5948
	else {
5949
	    ADD_INSN(ret, line, tostring);
5949
	    ADD_INSN2(ret, line, tostring,
5950
		      new_callinfo(iseq, idTo_s, 0, 0, NULL, FALSE),
5951
		      NULL/* CALL_CACHE */);
5950 5952
	}
5951 5953
	break;
5952 5954
      }
insns.def
357 357
 */
358 358
DEFINE_INSN
359 359
tostring
360
()
360
(CALL_INFO ci, CALL_CACHE cc)
361 361
(VALUE val)
362 362
(VALUE val)
363 363
{
364
    val = rb_obj_as_string(val);
364
    val = vm_tostring(th, val, ci, cc);
365 365
}
366 366

  
367 367
/**
test/ruby/test_optimization.rb
575 575
      def t; if false; case 42; when s {}; end; end; end
576 576
    end;
577 577
  end
578

  
579
  def test_tostring
580
    before = GC.stat(:total_allocated_objects)
581
    3.times { "x #{:total_allocated_objects}" }
582
    assert_equal before + 3, GC.stat(:total_allocated_objects)
583
    s = :total_allocated_objects
584
    assert_equal 'total_allocated_objects!', "#{s}" << '!', 'result mutable'
585
    assert_redefine_method('Symbol', 'to_s', <<-'end')
586
      assert_match %r{\A#<Symbol:0x[0-9a-f]+>\z}, "#{:foo}"
587
    end
588
  end
578 589
end
vm_eval.c
101 101
    return vm_call0_cfunc_with_frame(th, calling, ci, cc, argv);
102 102
}
103 103

  
104
VALUE
105
rb_vm_call0_body(rb_thread_t *th, struct rb_calling_info *calling,
106
		const struct rb_call_info *ci, struct rb_call_cache *cc,
107
		const VALUE *argv)
108
{
109
    return vm_call0_body(th, calling, ci, cc, argv);
110
}
111

  
104 112
/* `ci' should point temporal value (on stack value) */
105 113
static VALUE
106 114
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
2920 2920
    }
2921 2921
}
2922 2922

  
2923
/* vm_eval.c */
2924
VALUE rb_vm_call0_body(rb_thread_t *, struct rb_calling_info *,
2925
			const struct rb_call_info *, struct rb_call_cache *,
2926
			const VALUE *argv);
2927

  
2928
static VALUE
2929
vm_tostring(rb_thread_t *th, VALUE recv, CALL_INFO ci, CALL_CACHE cc)
2930
{
2931
    struct rb_calling_info calling;
2932
    VALUE val;
2933

  
2934
    if (RB_TYPE_P(recv, T_STRING)) {
2935
	return recv;
2936
    }
2937
    if (RB_TYPE_P(recv, T_SYMBOL)) {
2938
	vm_search_method(ci, cc, recv);
2939
	if (check_cfunc(cc->me, rb_sym_to_s)) {
2940
	    return rb_sym2str(recv);
2941
	}
2942
    /* TODO: digits (0-9), maybe true/false/nil... */
2943
    }
2944
    else {
2945
	vm_search_method(ci, cc, recv);
2946
    }
2947
    calling.block_handler = VM_BLOCK_HANDLER_NONE;
2948
    calling.argc = 0;
2949
    calling.recv = recv;
2950
    val = rb_vm_call0_body(th, &calling, ci, cc, 0);
2951

  
2952
    return RB_TYPE_P(val, T_STRING) ? val : rb_any_to_s(recv);
2953
}
2954

  
2923 2955
static void
2924 2956
vm_freezestring(VALUE str, VALUE debug)
2925 2957
{
2926
-