1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

merge revision(s) efcdf68e6443ab70fbff1703b9dabbfc5090df31,5e26619660f20272a53c7f839dde36cce034bb35: [Backport #17539]

Guard callinfo

	Callinfo was being written in to an array and the GC would not see the
	reference on the stack.  `new_insn_send` creates a new callinfo object,
	then it calls `new_insn_core`.  `new_insn_core` allocates a new INSN
	linked list item, which can end up calling `xmalloc` which will trigger
	a GC:

	  70cd351c7c/compile.c (L968-L969)

	Since the callinfo object isn't on the stack, the GC won't see it, and
	it can get collected.  This patch just refactors `new_insn_send` to keep
	the object on the stack

	Co-authored-by: John Hawthorn <john@hawthorn.email>
	---
	 compile.c            |  7 +++++--
	 test/ruby/test_gc.rb | 10 ++++++++++
	 2 files changed, 15 insertions(+), 2 deletions(-)

	Fix WB for callinfo

	The WB for callinfo needs to be executed *after* the reference is
	written.  Otherwise we get a WB miss.
	---
	 compile.c | 1 +
	 1 file changed, 1 insertion(+)
This commit is contained in:
NARUSE, Yui 2021-02-01 21:42:11 +09:00
parent d1fb0a3953
commit 74f90b46a9
3 changed files with 17 additions and 3 deletions

View file

@ -1302,12 +1302,16 @@ static INSN *
new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_callinfo_kwarg *keywords)
{
VALUE *operands = compile_data_calloc2(iseq, sizeof(VALUE), 2);
operands[0] = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL);
VALUE ci = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL);
operands[0] = ci;
operands[1] = (VALUE)blockiseq;
if (blockiseq) {
RB_OBJ_WRITTEN(iseq, Qundef, blockiseq);
}
return new_insn_core(iseq, line_no, BIN(send), 2, operands);
INSN *insn = new_insn_core(iseq, line_no, BIN(send), 2, operands);
RB_OBJ_WRITTEN(iseq, Qundef, ci);
RB_GC_GUARD(ci);
return insn;
}
static rb_iseq_t *

View file

@ -175,6 +175,16 @@ class TestGc < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {GC.latest_gc_info(:"\u{30eb 30d3 30fc}")}
end
def test_stress_compile_send
assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "")
GC.stress = true
begin
eval("A::B.c(1, 1, d: 234)")
rescue
end
EOS
end
def test_singleton_method
assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "[ruby-dev:42832]")
GC.stress = true

View file

@ -12,7 +12,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 0
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
#define RUBY_PATCHLEVEL 20
#define RUBY_PATCHLEVEL 21
#define RUBY_RELEASE_YEAR 2021
#define RUBY_RELEASE_MONTH 2