Skip to content

Commit

Permalink
Merge pull request #1568 from MoarVM/fix_segfault_finding_dynamics_af…
Browse files Browse the repository at this point in the history
…ter_deopt

Fix segfault finding dynamics after deopt
  • Loading branch information
jnthn committed Oct 18, 2021
2 parents 098e9b1 + 80f8edf commit ba7df1b
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/6model/reprs/MVMContext.c
Expand Up @@ -286,7 +286,7 @@ static void snapshot_frame_callees(MVMThreadContext *tc, MVMFrame *f) {
if (extra->caller_deopt_idx)
return;
/* Store with + 1 to avoid semi-predicate problem. */
extra->caller_deopt_idx = MVM_spesh_deopt_find_inactive_frame_deopt_idx(tc, f->caller) + 1;
extra->caller_deopt_idx = 1 + MVM_spesh_deopt_find_inactive_frame_deopt_idx(tc, f->caller, cand);
}
}
f = f->caller;
Expand Down
2 changes: 1 addition & 1 deletion src/disp/resume.c
Expand Up @@ -145,7 +145,7 @@ static MVMuint32 find_internal(MVMThreadContext *tc, MVMDispResumptionData *data
* it is the one in the most nested inline, if there are
* any inlines. */
MVMint32 deopt_idx = MVM_spesh_deopt_find_inactive_frame_deopt_idx(tc,
frame);
frame, cand);
if (deopt_idx == -1)
MVM_oops(tc, "Failed to find deopt index when processing resume");
MVMuint32 i;
Expand Down
25 changes: 14 additions & 11 deletions src/spesh/deopt.c
Expand Up @@ -340,10 +340,12 @@ void MVM_spesh_deopt_all(MVMThreadContext *tc) {
/* Takes a frame that we're lazily deoptimizing and finds the currently
* active deopt index at the point of the call it was making. Returns -1 if
* none can be resolved. */
MVMint32 MVM_spesh_deopt_find_inactive_frame_deopt_idx(MVMThreadContext *tc, MVMFrame *f) {
MVMint32 MVM_spesh_deopt_find_inactive_frame_deopt_idx(MVMThreadContext *tc,
MVMFrame *f, MVMSpeshCandidate *spesh_cand)
{
/* Is it JITted code? */
if (f->spesh_cand->body.jitcode) {
MVMJitCode *jitcode = f->spesh_cand->body.jitcode;
if (spesh_cand->body.jitcode) {
MVMJitCode *jitcode = spesh_cand->body.jitcode;
MVMuint32 idx = MVM_jit_code_get_active_deopt_idx(tc, jitcode, f);
if (idx < jitcode->num_deopts) {
MVMint32 deopt_idx = jitcode->deopts[idx].idx;
Expand All @@ -355,11 +357,11 @@ MVMint32 MVM_spesh_deopt_find_inactive_frame_deopt_idx(MVMThreadContext *tc, MVM
}
else {
/* Not JITted; see if we can find the return address in the deopt table. */
MVMuint32 ret_offset = (f == tc->cur_frame ? *(tc->interp_cur_op) : f->return_address) - f->spesh_cand->body.bytecode;
MVMint32 n = f->spesh_cand->body.num_deopts * 2;
MVMuint32 ret_offset = (f == tc->cur_frame ? *(tc->interp_cur_op) : f->return_address) - spesh_cand->body.bytecode;
MVMint32 n = spesh_cand->body.num_deopts * 2;
MVMint32 i;
for (i = 0; i < n; i += 2) {
if (MVM_spesh_deopt_bytecode_pos(f->spesh_cand->body.deopts[i + 1]) == ret_offset) {
if (MVM_spesh_deopt_bytecode_pos(spesh_cand->body.deopts[i + 1]) == ret_offset) {
MVMint32 deopt_idx = i / 2;
#if MVM_LOG_DEOPTS
fprintf(stderr, " Found deopt index for interpeter (idx %d)\n", deopt_idx);
Expand All @@ -383,17 +385,18 @@ void MVM_spesh_deopt_during_unwind(MVMThreadContext *tc) {
* stack top one. */
MVMCallStackRecord *record = tc->stack_top;
MVMFrame *frame = MVM_callstack_record_to_frame(record);
MVMSpeshCandidate *spesh_cand = frame->spesh_cand;
#if MVM_LOG_DEOPTS
fprintf(stderr, "Lazy deopt on unwind of frame '%s' (cuid '%s')\n",
MVM_string_utf8_encode_C_string(tc, frame->static_info->body.name),
MVM_string_utf8_encode_C_string(tc, frame->static_info->body.cuuid));
#endif

/* Find the deopt index, and assuming it's found, deopt. */
MVMint32 deopt_idx = MVM_spesh_deopt_find_inactive_frame_deopt_idx(tc, frame);
MVMint32 deopt_idx = MVM_spesh_deopt_find_inactive_frame_deopt_idx(tc, frame, spesh_cand);
if (deopt_idx >= 0) {
MVMuint32 deopt_target = frame->spesh_cand->body.deopts[deopt_idx * 2];
MVMuint32 deopt_offset = MVM_spesh_deopt_bytecode_pos(frame->spesh_cand->body.deopts[deopt_idx * 2 + 1]);
MVMuint32 deopt_target = spesh_cand->body.deopts[deopt_idx * 2];
MVMuint32 deopt_offset = MVM_spesh_deopt_bytecode_pos(spesh_cand->body.deopts[deopt_idx * 2 + 1]);

MVMFrame *top_frame;
MVMROOT(tc, frame, {
Expand All @@ -402,8 +405,8 @@ void MVM_spesh_deopt_during_unwind(MVMThreadContext *tc) {
/* Potentially need to uninline. This leaves the top frame being the
* one we're returning into. Otherwise, the top frame is the current
* one. */
if (frame->spesh_cand->body.inlines) {
uninline(tc, frame, frame->spesh_cand, deopt_offset, 1, 0);
if (spesh_cand->body.inlines) {
uninline(tc, frame, spesh_cand, deopt_offset, 1, 0);
top_frame = MVM_callstack_current_frame(tc);
}
else {
Expand Down
3 changes: 2 additions & 1 deletion src/spesh/deopt.h
@@ -1,6 +1,7 @@
void MVM_spesh_deopt_all(MVMThreadContext *tc);
void MVM_spesh_deopt_one(MVMThreadContext *tc, MVMuint32 deopt_idx);
MVMint32 MVM_spesh_deopt_find_inactive_frame_deopt_idx(MVMThreadContext *tc, MVMFrame *f);
MVMint32 MVM_spesh_deopt_find_inactive_frame_deopt_idx(MVMThreadContext *tc,
MVMFrame *frame, MVMSpeshCandidate *spesh_cand);
void MVM_spesh_deopt_during_unwind(MVMThreadContext *tc);
MVM_STATIC_INLINE MVMuint32 MVM_spesh_deopt_bytecode_pos(MVMuint32 deopt) {
return deopt >> 1;
Expand Down
14 changes: 9 additions & 5 deletions src/spesh/frame_walker.c
Expand Up @@ -72,12 +72,15 @@ static void go_to_next_inline(MVMThreadContext *tc, MVMSpeshFrameWalker *fw) {
* If so, go to the innermost inline. */
static void go_to_first_inline(MVMThreadContext *tc, MVMSpeshFrameWalker *fw, MVMFrame *prev) {
MVMFrame *f = fw->cur_caller_frame;
/* Get a local copy of spesh_cand so we don't stumble over another thread
* clearing the pointer after we checked it */
MVMSpeshCandidate *spesh_cand = f->spesh_cand;
if (spesh_cand && spesh_cand->body.inlines) {
MVMJitCode *jitcode = spesh_cand->body.jitcode;
if (jitcode && f->jit_entry_label) {
void *current_position = prev && prev->extra && prev->extra->caller_jit_position
? prev->extra->caller_jit_position
MVMFrameExtra *extra; /* Get a local copy as well for the same reason */
void *current_position = prev && (extra = prev->extra) && extra->caller_jit_position
? extra->caller_jit_position
: MVM_jit_code_get_current_position(tc, jitcode, f);
MVMuint32 idx = MVM_jit_code_get_active_inlines(tc, jitcode, current_position, 0);
if (idx < jitcode->num_inlines) {
Expand All @@ -94,9 +97,10 @@ static void go_to_first_inline(MVMThreadContext *tc, MVMSpeshFrameWalker *fw, MV
return;
}
else {
MVMint32 deopt_idx = prev && prev->extra && prev->extra->caller_deopt_idx > 0
? prev->extra->caller_deopt_idx - 1
: MVM_spesh_deopt_find_inactive_frame_deopt_idx(tc, f);
MVMFrameExtra *extra; /* Get a local copy as well for the same reason */
MVMint32 deopt_idx = prev && (extra = prev->extra) && extra->caller_deopt_idx > 0
? extra->caller_deopt_idx - 1
: MVM_spesh_deopt_find_inactive_frame_deopt_idx(tc, f, spesh_cand);
if (deopt_idx >= 0) {
fw->deopt_offset = MVM_spesh_deopt_bytecode_pos(spesh_cand->body.deopts[2 * deopt_idx + 1]);
fw->inline_idx = -1;
Expand Down

0 comments on commit ba7df1b

Please sign in to comment.