Esempio n. 1
0
/*
 * Look for Jcc instructions in the main trace that
 * branch to "normal exits".  We can optimize these into the
 * SideExitJcc* instructions that can be patched in place.
 */
void optimizeSideExitJccs(IRUnit& unit) {
    auto trace = unit.main();
    FTRACE(5, "SideExitJcc:vvvvvvvvvvvvvvvvvvvvv\n");
    SCOPE_EXIT { FTRACE(5, "SideExitJcc:^^^^^^^^^^^^^^^^^^^^^\n"); };

    forEachInst(trace->blocks(), [&] (IRInstruction* inst) {
        if (!jccCanBeDirectExit(inst->op())) return;
        auto const exitBlock = inst->taken();
        if (!isNormalExit(exitBlock)) return;

        auto it = exitBlock->backIter();
        auto& reqBindJmp = *(it--);
        auto& syncABI = *it;
        assert(syncABI.op() == SyncABIRegs);

        FTRACE(5, "converting jcc ({}) to side exit\n",
               inst->id());

        auto const newOpcode = jmpToSideExitJmp(inst->op());
        SideExitJccData data;
        data.taken = reqBindJmp.extra<ReqBindJmp>()->offset;

        auto const block = inst->block();
        block->insert(block->iteratorTo(inst),
                      unit.cloneInstruction(&syncABI));

        unit.replace(
            inst,
            newOpcode,
            data,
            std::make_pair(inst->numSrcs(), inst->srcs().begin())
        );
    });
}
Esempio n. 2
0
/*
 * Look for CheckStk/CheckLoc instructions in the main trace that
 * branch to "normal exits".  We can optimize these into the
 * SideExitGuard* instructions that can be patched in place.
 */
void optimizeSideExitChecks(IRUnit& unit) {
    auto trace = unit.main();
    FTRACE(5, "SideExit:vvvvvvvvvvvvvvvvvvvvv\n");
    SCOPE_EXIT { FTRACE(5, "SideExit:^^^^^^^^^^^^^^^^^^^^^\n"); };

    forEachInst(trace->blocks(), [&] (IRInstruction* inst) {
        if (inst->op() != CheckStk && inst->op() != CheckLoc) return;
        auto const exitBlock = inst->taken();
        if (!isNormalExit(exitBlock)) return;

        auto const syncABI = &*boost::prior(exitBlock->backIter());
        assert(syncABI->op() == SyncABIRegs);

        FTRACE(5, "converting jump ({}) to side exit\n",
               inst->id());

        auto const isStack = inst->op() == CheckStk;
        auto const fp      = syncABI->src(0);
        auto const sp      = syncABI->src(1);

        SideExitGuardData data;
        data.checkedSlot = isStack
                           ? inst->extra<CheckStk>()->offset
                           : inst->extra<CheckLoc>()->locId;
        data.taken = exitBlock->back()->extra<ReqBindJmp>()->offset;

        auto const block = inst->block();
        block->insert(block->iteratorTo(inst),
                      unit.cloneInstruction(syncABI));

        unit.replace(
            inst,
            isStack ? SideExitGuardStk : SideExitGuardLoc,
            inst->typeParam(),
            data,
            isStack ? sp : fp
        );
    });
}
Esempio n. 3
0
// Return true if branch is a conditional branch to a normal exit.
bool isSideExitJcc(IRInstruction* branch, Block* exit) {
  return jccCanBeDirectExit(branch->op()) && isNormalExit(exit);
}