/* Unwinds after a handler. */ static void unwind_after_handler(MVMThreadContext *tc, void *sr_data) { MVMFrame *frame; MVMException *exception; MVMuint32 goto_offset; /* Get active handler; sanity check (though it's possible other cases * should be supported). */ MVMActiveHandler *ah = (MVMActiveHandler *)sr_data; if (tc->active_handlers != ah) MVM_panic(1, "Trying to unwind from wrong handler"); /* Grab info we'll need to unwind. */ frame = ah->frame; exception = (MVMException *)ah->ex_obj; goto_offset = ah->handler->goto_offset; /* Clean up. */ tc->active_handlers = ah->next_handler; MVM_frame_dec_ref(tc, ah->frame); free(ah); /* Do the unwinding as needed. */ if (exception && exception->body.return_after_unwind) { MVM_frame_unwind_to(tc, frame->caller, NULL, 0, tc->last_handler_result); } else { MVM_frame_unwind_to(tc, frame, NULL, goto_offset, NULL); } }
static void run_handler(MVMThreadContext *tc, LocatedHandler lh, MVMObject *ex_obj, MVMuint32 category) { switch (lh.handler->action) { case MVM_EX_ACTION_GOTO: if (lh.jit_handler) { void **labels = lh.frame->spesh_cand->jitcode->labels; MVMuint8 *pc = lh.frame->spesh_cand->jitcode->bytecode; lh.frame->jit_entry_label = labels[lh.jit_handler->goto_label]; MVM_frame_unwind_to(tc, lh.frame, pc, 0, NULL); } else { MVM_frame_unwind_to(tc, lh.frame, NULL, lh.handler->goto_offset, NULL); } break; case MVM_EX_ACTION_INVOKE: { /* Create active handler record. */ MVMActiveHandler *ah = MVM_malloc(sizeof(MVMActiveHandler)); MVMFrame *cur_frame = tc->cur_frame; MVMObject *handler_code; /* Ensure we have an exception object. */ if (ex_obj == NULL) { ex_obj = MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTException); ((MVMException *)ex_obj)->body.category = category; } /* Find frame to invoke. */ handler_code = MVM_frame_find_invokee(tc, lh.frame->work[lh.handler->block_reg].o, NULL); /* Install active handler record. */ ah->frame = MVM_frame_inc_ref(tc, lh.frame); ah->handler = lh.handler; ah->jit_handler = lh.jit_handler; ah->ex_obj = ex_obj; ah->next_handler = tc->active_handlers; tc->active_handlers = ah; /* Set up special return to unwinding after running the * handler. */ cur_frame->return_value = (MVMRegister *)&tc->last_handler_result; cur_frame->return_type = MVM_RETURN_OBJ; cur_frame->special_return = unwind_after_handler; cur_frame->special_unwind = cleanup_active_handler; cur_frame->special_return_data = ah; /* Invoke the handler frame and return to runloop. */ STABLE(handler_code)->invoke(tc, handler_code, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_NULL_ARGS), cur_frame->args); break; } default: MVM_panic(1, "Unimplemented handler action"); } }
static void continue_unwind(MVMThreadContext *tc, void *sr_data) { MVMUnwindData *ud = (MVMUnwindData *)sr_data; MVMFrame *frame = ud->frame; MVMuint8 *abs_addr = ud->abs_addr; MVMuint32 rel_addr = ud->rel_addr; free(sr_data); MVM_frame_unwind_to(tc, frame, abs_addr, rel_addr, NULL); }
static void run_handler(MVMThreadContext *tc, LocatedHandler lh, MVMObject *ex_obj, MVMuint32 category, MVMObject *payload) { switch (lh.handler->action) { case MVM_EX_ACTION_GOTO_WITH_PAYLOAD: if (payload) tc->last_payload = payload; else if (ex_obj && ((MVMException *)ex_obj)->body.payload) tc->last_payload = ((MVMException *)ex_obj)->body.payload; else tc->last_payload = tc->instance->VMNull; /* Deliberate fallthrough to unwind below. */ case MVM_EX_ACTION_GOTO: if (lh.jit_handler) { void **labels = lh.frame->spesh_cand->jitcode->labels; MVMuint8 *pc = lh.frame->spesh_cand->jitcode->bytecode; lh.frame->jit_entry_label = labels[lh.jit_handler->goto_label]; MVM_frame_unwind_to(tc, lh.frame, pc, 0, NULL); } else { MVM_frame_unwind_to(tc, lh.frame, NULL, lh.handler->goto_offset, NULL); } break; case MVM_EX_ACTION_INVOKE: { /* Create active handler record. */ MVMActiveHandler *ah = MVM_malloc(sizeof(MVMActiveHandler)); MVMFrame *cur_frame = tc->cur_frame; MVMObject *handler_code; /* Ensure we have an exception object. */ if (ex_obj == NULL) { MVMROOT(tc, cur_frame, { MVMROOT(tc, lh.frame, { MVMROOT(tc, payload, { ex_obj = MVM_repr_alloc_init(tc, tc->instance->boot_types.BOOTException); }); }); });
static void run_handler(MVMThreadContext *tc, LocatedHandler lh, MVMObject *ex_obj) { switch (lh.handler->action) { case MVM_EX_ACTION_GOTO: MVM_frame_unwind_to(tc, lh.frame, NULL, lh.handler->goto_offset, NULL); break; case MVM_EX_ACTION_INVOKE: { /* Create active handler record. */ MVMActiveHandler *ah = malloc(sizeof(MVMActiveHandler)); /* Find frame to invoke. */ MVMObject *handler_code = MVM_frame_find_invokee(tc, lh.frame->work[lh.handler->block_reg].o, NULL); /* Ensure we have an exception object. */ /* TODO: Can make one up. */ if (ex_obj == NULL) MVM_panic(1, "Exception object creation NYI"); /* Install active handler record. */ ah->frame = MVM_frame_inc_ref(tc, lh.frame); ah->handler = lh.handler; ah->ex_obj = ex_obj; ah->next_handler = tc->active_handlers; tc->active_handlers = ah; /* Set up special return to unwinding after running the * handler. */ tc->cur_frame->return_value = (MVMRegister *)&tc->last_handler_result; tc->cur_frame->return_type = MVM_RETURN_OBJ; tc->cur_frame->special_return = unwind_after_handler; tc->cur_frame->special_unwind = cleanup_active_handler; tc->cur_frame->special_return_data = ah; /* Invoke the handler frame and return to runloop. */ STABLE(handler_code)->invoke(tc, handler_code, &no_arg_callsite, tc->cur_frame->args); break; } default: MVM_panic(1, "Unimplemented handler action"); } }