static void deopt_frame(MVMThreadContext *tc, MVMFrame *f, MVMint32 deopt_offset, MVMint32 deopt_target) { /* Found it; are we in an inline? */ MVMSpeshInline *inlines = f->spesh_cand->inlines; if (inlines) { /* Yes, going to have to re-create the frames; uninline * moves the interpreter, so we can just tweak the last * frame. */ uninline(tc, f, f->spesh_cand, deopt_offset, deopt_target, NULL); f->effective_bytecode = f->static_info->body.bytecode; f->effective_handlers = f->static_info->body.handlers; f->effective_spesh_slots = NULL; f->spesh_cand = NULL; /*fprintf(stderr, "Completed deopt_one in '%s' (cuid '%s'), idx = %i, with uninlining\n", MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name), MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid), i / 2);*/ } else { /* No inlining; simple case. Switch back to the original code. */ f->effective_bytecode = f->static_info->body.bytecode; f->effective_handlers = f->static_info->body.handlers; *(tc->interp_cur_op) = f->effective_bytecode + deopt_target; *(tc->interp_bytecode_start) = f->effective_bytecode; f->effective_spesh_slots = NULL; f->spesh_cand = NULL; /*fprintf(stderr, "Completed deopt_one in '%s' (cuid '%s'), idx = %i\n", MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name), MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid), i / 2);*/ } }
static void Ungetch(int c) { if (Inlining<0) ungetc(c,yyin); else uninline(); if (1) { printf("\n<bs{%d}bs>\n", c); } }
/* De-optimizes all specialized frames on the call stack. Used when a change * is made the could invalidate all kinds of assumptions all over the place * (such as a mix-in). */ void MVM_spesh_deopt_all(MVMThreadContext *tc) { /* Walk frames looking for any callers in specialized bytecode. */ MVMFrame *l = tc->cur_frame; MVMFrame *f = tc->cur_frame->caller; if (tc->instance->profiling) MVM_profiler_log_deopt_all(tc); while (f) { if (f->effective_bytecode != f->static_info->body.bytecode && f->spesh_log_idx < 0) { /* Found one. Is it JITted code? */ if (f->spesh_cand->jitcode && f->jit_entry_label) { MVMint32 num_deopts = f->spesh_cand->jitcode->num_deopts; MVMJitDeopt *deopts = f->spesh_cand->jitcode->deopts; void **labels = f->spesh_cand->jitcode->labels; MVMint32 i; for (i = 0; i < num_deopts; i++) { if (labels[deopts[i].label] == f->jit_entry_label) { /* fprintf(stderr, "Found deopt label for JIT (%d) (label %d idx %d)\n", i, deopts[i].label, deopts[i].idx); */ /* Resolve offset and target. */ MVMint32 deopt_idx = deopts[i].idx; MVMint32 deopt_offset = f->spesh_cand->deopts[2 * deopt_idx + 1]; MVMint32 deopt_target = f->spesh_cand->deopts[2 * deopt_idx]; /* Switch frame itself back to the original code. */ f->effective_bytecode = f->static_info->body.bytecode; f->effective_handlers = f->static_info->body.handlers; /* Re-create any frames needed if we're in an inline; if not, * just update return address. */ if (f->spesh_cand->inlines) uninline(tc, f, f->spesh_cand, deopt_offset, deopt_target, l); else f->return_address = f->effective_bytecode + deopt_target; /* No spesh cand/slots needed now. */ f->effective_spesh_slots = NULL; f->spesh_cand = NULL; f->jit_entry_label = NULL; break; } } /* if (i == num_deopts) fprintf(stderr, "JIT: can't find deopt all idx"); */ } else { /* Not JITted; see if we can find the return address in the deopt table. */ MVMint32 ret_offset = f->return_address - f->effective_bytecode; MVMint32 i; for (i = 0; i < f->spesh_cand->num_deopts * 2; i += 2) { if (f->spesh_cand->deopts[i + 1] == ret_offset) { /* Switch frame itself back to the original code. */ f->effective_bytecode = f->static_info->body.bytecode; f->effective_handlers = f->static_info->body.handlers; /* Re-create any frames needed if we're in an inline; if not, * just update return address. */ if (f->spesh_cand->inlines) uninline(tc, f, f->spesh_cand, ret_offset, f->spesh_cand->deopts[i], l); else f->return_address = f->effective_bytecode + f->spesh_cand->deopts[i]; /* No spesh cand/slots needed now. */ f->effective_spesh_slots = NULL; f->spesh_cand = NULL; break; } } } } l = f; f = f->caller; } }