コード例 #1
0
ファイル: exceptions.c プロジェクト: stmuk/MoarVM
/* Looks through the handlers of a particular scope, and sees if one will
 * match what we're looking for. Returns 1 to it if so; if not,
 * returns 0. */
static MVMint32 search_frame_handlers(MVMThreadContext *tc, MVMFrame *f,
                                      MVMuint8 mode, MVMuint32 cat,
                                      MVMObject *payload, LocatedHandler *lh) {
    MVMuint32  i;
    if (f->spesh_cand && f->spesh_cand->jitcode && f->jit_entry_label) {
        MVMJitHandler    *jhs = f->spesh_cand->jitcode->handlers;
        MVMFrameHandler  *fhs = f->effective_handlers;
        MVMint32 num_handlers = f->spesh_cand->jitcode->num_handlers;
        void         **labels = f->spesh_cand->jitcode->labels;
        void       *cur_label = f->jit_entry_label;
        for (i = 0; i < num_handlers; i++) {
            if (mode == MVM_EX_THROW_LEX && fhs[i].inlined_and_not_lexical)
                continue;
            if (!handler_can_handle(f, &fhs[i], cat, payload))
                continue;
            if (cur_label >= labels[jhs[i].start_label] &&
                cur_label <= labels[jhs[i].end_label] &&
                !in_handler_stack(tc, &fhs[i], f)) {
                lh->handler     = &fhs[i];
                lh->jit_handler = &jhs[i];
                return 1;
            }
        }
    } else {
        MVMint32 num_handlers = f->spesh_cand
            ? f->spesh_cand->num_handlers
            : f->static_info->body.num_handlers;
        MVMint32 pc;
        if (f == tc->cur_frame)
            pc = (MVMuint32)(*tc->interp_cur_op - *tc->interp_bytecode_start);
        else
            pc = (MVMuint32)(f->return_address - f->effective_bytecode);
        for (i = 0; i < num_handlers; i++) {
            MVMFrameHandler  *fh = &f->effective_handlers[i];
            if (mode == MVM_EX_THROW_LEX && fh->inlined_and_not_lexical)
                continue;
            if (!handler_can_handle(f, fh, cat, payload))
                continue;
            if (pc >= fh->start_offset && pc <= fh->end_offset && !in_handler_stack(tc, fh, f)) {
                lh->handler = fh;
                return 1;
            }
        }
    }
    return 0;
}
コード例 #2
0
ファイル: exceptions.c プロジェクト: MasterDuke17/MoarVM
/* Looks through the handlers of a particular frame, including inlines in
 * dynamic scope, and sees if one will match what we're looking for. Returns
 * 1 to it if so, and 0 if not; in the case 1 is returned the *lh will be
 * populated with details of the located handler. Since upon inlining, the
 * dynamic scope becomes lexical so far as the optimized bytecode is
 * concerned, then this just needs a scan of the table without any further
 * checks being needed. */
static MVMint32 search_frame_handlers_dyn(MVMThreadContext *tc, MVMFrame *f,
                                          MVMuint32 cat, MVMObject *payload,
                                          LocatedHandler *lh) {
    MVMuint32  i;
    if (f->spesh_cand && f->spesh_cand->jitcode && f->jit_entry_label) {
        MVMJitCode *jitcode = f->spesh_cand->jitcode;
        void *current_position = MVM_jit_code_get_current_position(tc, jitcode, f);
        MVMJitHandler    *jhs = f->spesh_cand->jitcode->handlers;
        MVMFrameHandler  *fhs = MVM_frame_effective_handlers(f);
        for (i = MVM_jit_code_get_active_handlers(tc, jitcode, current_position, 0);
             i < jitcode->num_handlers;
             i = MVM_jit_code_get_active_handlers(tc, jitcode, current_position, i+1)) {
            if (handler_can_handle(f, &fhs[i], cat, payload) &&
                !in_handler_stack(tc, &fhs[i], f)) {
                lh->handler     = &fhs[i];
                lh->jit_handler = &jhs[i];
                return 1;
            }
        }
    } else {
        MVMint32 num_handlers = f->spesh_cand
            ? f->spesh_cand->num_handlers
            : f->static_info->body.num_handlers;
        MVMint32 pc;
        if (f == tc->cur_frame)
            pc = (MVMuint32)(*tc->interp_cur_op - *tc->interp_bytecode_start);
        else
            pc = (MVMuint32)(f->return_address - MVM_frame_effective_bytecode(f));
        for (i = 0; i < num_handlers; i++) {
            MVMFrameHandler  *fh = &(MVM_frame_effective_handlers(f)[i]);
            if (!handler_can_handle(f, fh, cat, payload))
                continue;
            if (pc >= fh->start_offset && pc <= fh->end_offset && !in_handler_stack(tc, fh, f)) {
                lh->handler = fh;
                return 1;
            }
        }
    }
    return 0;
}
コード例 #3
0
ファイル: exceptions.c プロジェクト: tokuhirom/MoarVM
/* Looks through the handlers of a particular scope, and sees if one will
 * match what we're looking for. Returns a pointer to it if so; if not,
 * returns NULL. */
static MVMFrameHandler * search_frame_handlers(MVMThreadContext *tc, MVMFrame *f, MVMuint32 cat) {
    MVMStaticFrame *sf = f->static_info;
    MVMuint32 pc, i;
    if (f == tc->cur_frame)
        pc = (MVMuint32)(*tc->interp_cur_op - *tc->interp_bytecode_start);
    else
        pc = (MVMuint32)(f->return_address - sf->bytecode);
    for (i = 0; i < sf->num_handlers; i++) {
        if (sf->handlers[i].category_mask & cat)
            if (pc >= sf->handlers[i].start_offset && pc < sf->handlers[i].end_offset)
                if (!in_handler_stack(tc, &sf->handlers[i]))
                    return &sf->handlers[i];
    }
    return NULL;
}
コード例 #4
0
ファイル: exceptions.c プロジェクト: danaj/MoarVM
/* Looks through the handlers of a particular scope, and sees if one will
 * match what we're looking for. Returns a pointer to it if so; if not,
 * returns NULL. */
static MVMFrameHandler * search_frame_handlers(MVMThreadContext *tc, MVMFrame *f, MVMuint32 cat, MVMObject *payload) {
    MVMuint32 pc, i;
    if (f == tc->cur_frame)
        pc = (MVMuint32)(*tc->interp_cur_op - *tc->interp_bytecode_start);
    else
        pc = (MVMuint32)(f->return_address - f->effective_bytecode);
    for (i = 0; i < f->static_info->body.num_handlers; i++) {
        MVMFrameHandler              eh = f->effective_handlers[i];
        MVMuint32         category_mask = eh.category_mask;
        MVMuint64       block_has_label = category_mask & MVM_EX_CAT_LABELED;
        MVMuint64           block_label = block_has_label ? (MVMuint64)(f->work[eh.label_reg].o) : 0;
        MVMuint64          thrown_label = payload ? (MVMuint64)payload : 0;
        MVMuint64 identical_label_found = thrown_label == block_label;

        if ( ((cat & category_mask) == cat && (!(cat & MVM_EX_CAT_LABELED) || identical_label_found))
          || ((category_mask & MVM_EX_CAT_CONTROL) && cat != MVM_EX_CAT_CATCH) ) {
            if (pc >= f->effective_handlers[i].start_offset && pc <= f->effective_handlers[i].end_offset)
                if (!in_handler_stack(tc, &f->effective_handlers[i], f))
                    return &f->effective_handlers[i];
        }
    }
    return NULL;
}
コード例 #5
0
ファイル: exceptions.c プロジェクト: MasterDuke17/MoarVM
/* Looks for lexically applicable handlers in the current frame, accounting
 * for any inlines. The skip_first_inlinee flag indicates that we should skip
 * looking until we have encountered an inline boundary indicator saying that
 * we have crossed from an inlinee to its inliner's handlers; this is used to
 * handle the THROW_LEX_CALLER mode. If we never encounter an inline boundary
 * when skip_first_inlinee is true then we'll always return 0.
 *
 * If skip_first_inlinee is false or we already saw an inline boundary, then
 * we start looking for a matching handler. If one is found before seeing
 * another inline boundary, then it is applicable; the data pointed to by lh
 * will be updated with the frame handler details and 1 will be returned.
 *
 * Upon reaching an (or, in the case of skip_first_inlinee, a second) inline
 * boundary indicator, there are two cases that apply. We take the inline
 * that we are leaving, and look up the code ref using the code_ref_reg in
 * the inline. We know that we can never inline a frame that was closed over
 * (due to capturelex or takeclosure being marked :noinline). Thus, either:
 * 1. The outer of the inlinee is actually the current frame f. In this case,
 *    we skip all inlined handlers and just consider those of f itself.
 * 2. The next frame we should search in is the ->outer of the inlinee, and
 *    thus all the rest of the handlers in this frame should be ignored. In
 *    this case, the MVMFrame **next_outer will be populated with a pointer
 *    to that frame.
 *
 * The skip_all_inlinees flag is set once we are below the frame on the stack
 * to where the search started. Again, this is because a frame that did a
 * lexical capture may not be inlined, so we only need to consider the topmost
 * frame's handlers, not anything it might have inlined into it.
 */
static MVMint32 search_frame_handlers_lex(MVMThreadContext *tc, MVMFrame *f,
                                          MVMuint32 cat, MVMObject *payload,
                                          LocatedHandler *lh,
                                          MVMuint32 *skip_first_inlinee,
                                          MVMuint32 skip_all_inlinees,
                                          MVMFrame **next_outer) {
    MVMuint32 i;
    MVMuint32 skipping = *skip_first_inlinee;
    MVMFrameHandler *fhs = MVM_frame_effective_handlers(f);
    if (f->spesh_cand && f->spesh_cand->jitcode && f->jit_entry_label) {
        MVMJitCode *jitcode = f->spesh_cand->jitcode;
        void *current_position = MVM_jit_code_get_current_position(tc, jitcode, f);
        MVMJitHandler    *jhs = jitcode->handlers;
        for (i = MVM_jit_code_get_active_handlers(tc, jitcode, current_position, 0);
             i < jitcode->num_handlers;
             i = MVM_jit_code_get_active_handlers(tc, jitcode, current_position, i+1)) {
            MVMFrameHandler *fh = &(fhs[i]);
            if (skip_all_inlinees && fh->inlinee >= 0)
                continue;
            if (fh->category_mask == MVM_EX_INLINE_BOUNDARY) {
                if (skipping) {
                    skipping = 0;
                    *skip_first_inlinee = 0;
                }
                else {
                    MVMuint16 cr_reg = f->spesh_cand->inlines[fh->inlinee].code_ref_reg;
                    MVMFrame *inline_outer = ((MVMCode *)f->work[cr_reg].o)->body.outer;
                    if (inline_outer == f) {
                        skip_all_inlinees = 1;
                    }
                    else {
                        *next_outer = inline_outer;
                        return 0;
                    }
                }
            }
            if (skipping || !handler_can_handle(f, fh, cat, payload))
                continue;
            if (!in_handler_stack(tc, fh, f)) {
                if (skipping && f->static_info->body.is_thunk)
                    return 0;
                lh->handler     = fh;
                lh->jit_handler = &jhs[i];
                return 1;
            }
        }
    }
    else {
        MVMint32 num_handlers = f->spesh_cand
            ? f->spesh_cand->num_handlers
            : f->static_info->body.num_handlers;
        MVMint32 pc;
        if (f == tc->cur_frame)
            pc = (MVMuint32)(*tc->interp_cur_op - *tc->interp_bytecode_start);
        else
            pc = (MVMuint32)(f->return_address - MVM_frame_effective_bytecode(f));
        for (i = 0; i < num_handlers; i++) {
            MVMFrameHandler *fh = &(fhs[i]);
            if (skip_all_inlinees && fh->inlinee >= 0)
                continue;
            if (fh->category_mask == MVM_EX_INLINE_BOUNDARY) {
                if (pc >= fh->start_offset && pc <= fh->end_offset) {
                    if (skipping) {
                        skipping = 0;
                        *skip_first_inlinee = 0;
                    }
                    else {
                        MVMuint16 cr_reg = f->spesh_cand->inlines[fh->inlinee].code_ref_reg;
                        MVMFrame *inline_outer = ((MVMCode *)f->work[cr_reg].o)->body.outer;
                        if (inline_outer == f) {
                            skip_all_inlinees = 1;
                        }
                        else {
                            *next_outer = inline_outer;
                            return 0;
                        }
                    }
                }
                continue;
            }
            if (skipping || !handler_can_handle(f, fh, cat, payload))
                continue;
            if (pc >= fh->start_offset &&
                    pc <= fh->end_offset &&
                    !in_handler_stack(tc, fh, f)) {
                if (skipping && f->static_info->body.is_thunk)
                    return 0;
                lh->handler = fh;
                return 1;
            }
        }
    }
    return 0;
}