mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Do not execute MJIT copy job when ISeq is GC-ed
I assumed that ISeq is never GC-ed by `in_jit` + `mjit_mark` on copy job ISeq, but unfortunately I found SEGV on `mjit_copy_job_handler` in which iseq->body was somehow Qnil. And it seems to be fixed by disabling the job when `mjit_free_iseq` is called for the ISeq. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67551 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1222534719
commit
e45c9a40a2
2 changed files with 13 additions and 3 deletions
10
mjit.c
10
mjit.c
|
@ -33,11 +33,16 @@ mjit_copy_job_handler(void *data)
|
||||||
// Make sure that this job is never executed when:
|
// Make sure that this job is never executed when:
|
||||||
// 1. job is being modified
|
// 1. job is being modified
|
||||||
// 2. alloca memory inside job is expired
|
// 2. alloca memory inside job is expired
|
||||||
// Note that job->iseq is guarded from GC by `mjit_mark`.
|
// 3. ISeq is GC-ed
|
||||||
if (job->finish_p) {
|
if (job->finish_p) {
|
||||||
CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
|
CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (job->iseq == NULL) { // ISeq GC notified in mjit_mark_iseq
|
||||||
|
job->finish_p = true;
|
||||||
|
CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const struct rb_iseq_constant_body *body = job->iseq->body;
|
const struct rb_iseq_constant_body *body = job->iseq->body;
|
||||||
if (job->cc_entries) {
|
if (job->cc_entries) {
|
||||||
|
@ -113,6 +118,9 @@ mjit_free_iseq(const rb_iseq_t *iseq)
|
||||||
if (!mjit_enabled)
|
if (!mjit_enabled)
|
||||||
return;
|
return;
|
||||||
CRITICAL_SECTION_START(4, "mjit_free_iseq");
|
CRITICAL_SECTION_START(4, "mjit_free_iseq");
|
||||||
|
if (mjit_copy_job.iseq == iseq) {
|
||||||
|
mjit_copy_job.iseq = NULL;
|
||||||
|
}
|
||||||
if (iseq->body->jit_unit) {
|
if (iseq->body->jit_unit) {
|
||||||
// jit_unit is not freed here because it may be referred by multiple
|
// jit_unit is not freed here because it may be referred by multiple
|
||||||
// lists of units. `get_from_list` and `mjit_finish` do the job.
|
// lists of units. `get_from_list` and `mjit_finish` do the job.
|
||||||
|
|
|
@ -1195,15 +1195,17 @@ mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq, struct rb_call_cache *cc
|
||||||
}
|
}
|
||||||
|
|
||||||
CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread");
|
CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread");
|
||||||
bool result = job->finish_p;
|
bool success_p = job->finish_p;
|
||||||
// Disable dispatching this job in mjit_copy_job_handler while memory allocated by alloca
|
// Disable dispatching this job in mjit_copy_job_handler while memory allocated by alloca
|
||||||
// could be expired after finishing this function.
|
// could be expired after finishing this function.
|
||||||
job->finish_p = true;
|
job->finish_p = true;
|
||||||
|
|
||||||
in_jit = true; // Prohibit GC during JIT compilation
|
in_jit = true; // Prohibit GC during JIT compilation
|
||||||
|
if (job->iseq == NULL) // ISeq GC is notified in mjit_mark_iseq
|
||||||
|
success_p = false;
|
||||||
job->iseq = NULL; // Allow future GC of this ISeq from here
|
job->iseq = NULL; // Allow future GC of this ISeq from here
|
||||||
CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread");
|
CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread");
|
||||||
return result;
|
return success_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The function implementing a worker. It is executed in a separate
|
// The function implementing a worker. It is executed in a separate
|
||||||
|
|
Loading…
Add table
Reference in a new issue