summaryrefslogtreecommitdiff
path: root/mjit_compile.c
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2020-03-12 22:51:33 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2020-03-12 22:51:34 -0700
commit0cd7be99e9a15f649970559e43e3edb704568670 (patch)
tree848fb360585d0f78ad6f26fdb89a4b61b920beb0 /mjit_compile.c
parent43e18c68f4d53767db7aae232ca46c2b400148cd (diff)
Avoid referring to an old value of realloc
OpenBSD RubyCI has failed with SEGV since 4bcd5981e80d3e1852c8723741a0069779464128. https://rubyci.org/logs/rubyci.s3.amazonaws.com/openbsd-current/ruby-master/log/20200312T223005Z.fail.html.gz This was because `status->cc_entries` could be stale after `realloc` call for inlined iseqs.
Diffstat (limited to 'mjit_compile.c')
-rw-r--r--mjit_compile.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/mjit_compile.c b/mjit_compile.c
index a75e3fe738..cfaa672a2d 100644
--- a/mjit_compile.c
+++ b/mjit_compile.c
@@ -51,8 +51,8 @@ struct compile_status {
bool local_stack_p;
// Safely-accessible ivar cache entries copied from main thread.
union iseq_inline_storage_entry *is_entries;
- // Safely-accessible call cache entries captured to compiled_iseq to be marked on GC
- const struct rb_callcache **cc_entries;
+ // Index of call cache entries captured to compiled_iseq to be marked on GC
+ int cc_entries_index;
// A pointer to root (i.e. not inlined) iseq being compiled.
const struct rb_iseq_constant_body *compiled_iseq;
// Mutated optimization levels
@@ -82,6 +82,18 @@ call_data_index(CALL_DATA cd, const struct rb_iseq_constant_body *body)
return cd - body->call_data;
}
+const struct rb_callcache ** mjit_iseq_cc_entries(const struct rb_iseq_constant_body *const body);
+
+// Using this function to refer to cc_entries allocated by `mjit_capture_cc_entries`
+// instead of storing cc_entries in status directly so that we always refer to a new address
+// returned by `realloc` inside it.
+static const struct rb_callcache **
+captured_cc_entries(const struct compile_status *status)
+{
+ VM_ASSERT(status->cc_entries_index != -1);
+ return mjit_iseq_cc_entries(status->compiled_iseq) + status->cc_entries_index;
+}
+
// Returns true if call cache is still not obsoleted and vm_cc_cme(cc)->def->type is available.
static bool
has_valid_method_type(CALL_CACHE cc)
@@ -277,7 +289,7 @@ compile_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body, struct
fprintf(f, " return Qundef;\n");
}
-extern const struct rb_callcache **
+extern int
mjit_capture_cc_entries(const struct rb_iseq_constant_body *compiled_iseq, const struct rb_iseq_constant_body *captured_iseq);
extern bool mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq,
@@ -375,8 +387,8 @@ inlinable_iseq_p(const struct rb_iseq_constant_body *body)
alloca(sizeof(const struct rb_iseq_constant_body *) * body->iseq_size) : NULL, \
.is_entries = (body->is_size > 0) ? \
alloca(sizeof(union iseq_inline_storage_entry) * body->is_size) : NULL, \
- .cc_entries = (body->ci_size > 0) ? \
- mjit_capture_cc_entries(status.compiled_iseq, body) : NULL, \
+ .cc_entries_index = (body->ci_size > 0) ? \
+ mjit_capture_cc_entries(status.compiled_iseq, body) : -1, \
.compiled_iseq = status.compiled_iseq, \
.compile_info = compile_root_p ? \
rb_mjit_iseq_compile_info(body) : alloca(sizeof(struct rb_mjit_compile_info)) \
@@ -403,7 +415,7 @@ precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status
if (insn == BIN(opt_send_without_block)) { // `compile_inlined_cancel_handler` supports only `opt_send_without_block`
CALL_DATA cd = (CALL_DATA)body->iseq_encoded[pos + 1];
const struct rb_callinfo *ci = cd->ci;
- const struct rb_callcache *cc = status->cc_entries[call_data_index(cd, body)]; // use copy to avoid race condition
+ const struct rb_callcache *cc = captured_cc_entries(status)[call_data_index(cd, body)]; // use copy to avoid race condition
const rb_iseq_t *child_iseq;
if (has_valid_method_type(cc) &&
@@ -429,7 +441,7 @@ precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status
.param_size = child_iseq->body->param.size,
.local_size = child_iseq->body->local_table_size
};
- if ((child_iseq->body->ci_size > 0 && child_status.cc_entries == NULL)
+ if ((child_iseq->body->ci_size > 0 && child_status.cc_entries_index == -1)
|| (child_status.is_entries != NULL && !mjit_copy_cache_from_main_thread(child_iseq, child_status.is_entries))) {
return false;
}
@@ -462,7 +474,7 @@ mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname)
struct compile_status status = { .compiled_iseq = iseq->body };
INIT_COMPILE_STATUS(status, iseq->body, true);
- if ((iseq->body->ci_size > 0 && status.cc_entries == NULL)
+ if ((iseq->body->ci_size > 0 && status.cc_entries_index == -1)
|| (status.is_entries != NULL && !mjit_copy_cache_from_main_thread(iseq, status.is_entries))) {
return false;
}