summaryrefslogtreecommitdiff
path: root/mjit.c
diff options
context:
space:
mode:
authork0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-14 12:40:44 +0000
committerk0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-04-14 12:40:44 +0000
commite45c9a40a2ee2ca241565f5953af116cd2b5ab29 (patch)
tree7e568375050ffb4d39a1549ca8ec147273520ae1 /mjit.c
parent12225347198344590af4a4a55ac1f90591a21dac (diff)
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
Diffstat (limited to 'mjit.c')
-rw-r--r--mjit.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/mjit.c b/mjit.c
index 9d849b1411..bd5dd46b19 100644
--- a/mjit.c
+++ b/mjit.c
@@ -33,11 +33,16 @@ mjit_copy_job_handler(void *data)
// Make sure that this job is never executed when:
// 1. job is being modified
// 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) {
CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
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;
if (job->cc_entries) {
@@ -113,6 +118,9 @@ mjit_free_iseq(const rb_iseq_t *iseq)
if (!mjit_enabled)
return;
CRITICAL_SECTION_START(4, "mjit_free_iseq");
+ if (mjit_copy_job.iseq == iseq) {
+ mjit_copy_job.iseq = NULL;
+ }
if (iseq->body->jit_unit) {
// 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.