Example #1
0
/*
 * Iterate through all successor blocks and propagate up the live-in sets.
 * The calculated result is used for phi-node pruning - where we only need to
 * insert a phi node if the variable is live-in to the block.
 */
static bool computeBlockLiveIns(CompilationUnit *cUnit, BasicBlock *bb) {
    BitVector *tempDalvikRegisterV = cUnit->tempDalvikRegisterV;

    if (bb->dataFlowInfo == NULL) return false;
    dvmCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
    if (bb->taken && bb->taken->dataFlowInfo)
        computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
                          bb->dataFlowInfo->defV);
    if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
        computeSuccLiveIn(tempDalvikRegisterV,
                          bb->fallThrough->dataFlowInfo->liveInV,
                          bb->dataFlowInfo->defV);
    if (bb->successorBlockList.blockListType != kNotUsed) {
        GrowableListIterator iterator;
        dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
                                    &iterator);
        while (true) {
            SuccessorBlockInfo *successorBlockInfo =
                    (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
            if (successorBlockInfo == NULL) break;
            BasicBlock *succBB = successorBlockInfo->block;
            if (succBB->dataFlowInfo) {
                computeSuccLiveIn(tempDalvikRegisterV,
                                  succBB->dataFlowInfo->liveInV,
                                  bb->dataFlowInfo->defV);
            }
        }
    }
    if (dvmCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
        dvmCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
        return true;
    }
    return false;
}
Example #2
0
/* Worker function to compute the dominance frontier */
static bool computeDominanceFrontier(CompilationUnit *cUnit, BasicBlock *bb) {
    GrowableList *blockList = &cUnit->blockList;

    /* Calculate DF_local */
    if (bb->taken) {
        checkForDominanceFrontier(bb, bb->taken);
    }
    if (bb->fallThrough) {
        checkForDominanceFrontier(bb, bb->fallThrough);
    }
    if (bb->successorBlockList.blockListType != kNotUsed) {
        GrowableListIterator iterator;
        dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
                                    &iterator);
        while (true) {
            SuccessorBlockInfo *successorBlockInfo =
                    (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
            if (successorBlockInfo == NULL) break;
            BasicBlock *succBB = successorBlockInfo->block;
            checkForDominanceFrontier(bb, succBB);
        }
    }

    /* Calculate DF_up */
    BitVectorIterator bvIterator;
    dvmBitVectorIteratorInit(bb->iDominated, &bvIterator);
    while (true) {
        int dominatedIdx = dvmBitVectorIteratorNext(&bvIterator);
        if (dominatedIdx == -1) break;
        BasicBlock *dominatedBB = (BasicBlock *)
                dvmGrowableListGetElement(blockList, dominatedIdx);
        BitVectorIterator dfIterator;
        dvmBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
        while (true) {
            int dfUpIdx = dvmBitVectorIteratorNext(&dfIterator);
            if (dfUpIdx == -1) break;
            BasicBlock *dfUpBlock = (BasicBlock *)
                    dvmGrowableListGetElement(blockList, dfUpIdx);
            checkForDominanceFrontier(bb, dfUpBlock);
        }
    }

    return true;
}
Example #3
0
/* Enter the node to the dfsOrder list then visit its successors */
static void recordDFSPreOrder(CompilationUnit *cUnit, BasicBlock *block) {

    if (block->visited || block->hidden) return;
    block->visited = true;

    /* Enqueue the block id */
    dvmInsertGrowableList(&cUnit->dfsOrder, block->id);

    if (block->fallThrough) recordDFSPreOrder(cUnit, block->fallThrough);
    if (block->taken) recordDFSPreOrder(cUnit, block->taken);
    if (block->successorBlockList.blockListType != kNotUsed) {
        GrowableListIterator iterator;
        dvmGrowableListIteratorInit(&block->successorBlockList.blocks,
                                    &iterator);
        while (true) {
            SuccessorBlockInfo *successorBlockInfo =
                    (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
            if (successorBlockInfo == NULL) break;
            BasicBlock *succBB = successorBlockInfo->block;
            recordDFSPreOrder(cUnit, succBB);
        }
    }
    return;
}
void dvmCompilerInlineMIR(CompilationUnit *cUnit, JitTranslationInfo *info)
{
    bool isRange = false;
    GrowableListIterator iterator;

    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
    /*
     * Analyze the basic block containing an invoke to see if it can be inlined
     */
    while (true) {
        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
        if (bb == NULL) break;
        if (bb->blockType != kDalvikByteCode)
            continue;
        MIR *lastMIRInsn = bb->lastMIRInsn;
        Opcode opcode = lastMIRInsn->dalvikInsn.opcode;
        int flags = (int)dexGetFlagsFromOpcode(opcode);

        /* No invoke - continue */
        if ((flags & kInstrInvoke) == 0)
            continue;

        /* Disable inlining when doing method tracing */
        if (gDvmJit.methodTraceSupport)
            continue;

        /*
         * If the invoke itself is selected for single stepping, don't bother
         * to inline it.
         */
        if (SINGLE_STEP_OP(opcode))
            continue;

        const Method *calleeMethod;

        switch (opcode) {
            case OP_INVOKE_SUPER:
            case OP_INVOKE_DIRECT:
            case OP_INVOKE_STATIC:
            case OP_INVOKE_SUPER_QUICK:
                calleeMethod = lastMIRInsn->meta.callsiteInfo->method;
                break;
            case OP_INVOKE_SUPER_RANGE:
            case OP_INVOKE_DIRECT_RANGE:
            case OP_INVOKE_STATIC_RANGE:
            case OP_INVOKE_SUPER_QUICK_RANGE:
                isRange = true;
                calleeMethod = lastMIRInsn->meta.callsiteInfo->method;
                break;
            default:
                calleeMethod = NULL;
                break;
        }

        if (calleeMethod) {
            bool inlined = tryInlineSingletonCallsite(cUnit, calleeMethod,
                                                      lastMIRInsn, bb, isRange);
            if (!inlined &&
                !(gDvmJit.disableOpt & (1 << kMethodJit)) &&
                !dvmIsNativeMethod(calleeMethod)) {
                CompilerMethodStats *methodStats =
                    dvmCompilerAnalyzeMethodBody(calleeMethod, true);
                if ((methodStats->attributes & METHOD_IS_LEAF) &&
                    !(methodStats->attributes & METHOD_CANNOT_COMPILE)) {
                    /* Callee has been previously compiled */
                    if (dvmJitGetMethodAddr(calleeMethod->insns)) {
                        lastMIRInsn->OptimizationFlags |= MIR_INVOKE_METHOD_JIT;
                    } else {
                        /* Compile the callee first */
                        dvmCompileMethod(calleeMethod, info);
                        if (dvmJitGetMethodAddr(calleeMethod->insns)) {
                            lastMIRInsn->OptimizationFlags |=
                                MIR_INVOKE_METHOD_JIT;
                        } else {
                            methodStats->attributes |= METHOD_CANNOT_COMPILE;
                        }
                    }
                }
            }
            return;
        }

        switch (opcode) {
            case OP_INVOKE_VIRTUAL:
            case OP_INVOKE_VIRTUAL_QUICK:
            case OP_INVOKE_INTERFACE:
                isRange = false;
                calleeMethod = lastMIRInsn->meta.callsiteInfo->method;
                break;
            case OP_INVOKE_VIRTUAL_RANGE:
            case OP_INVOKE_VIRTUAL_QUICK_RANGE:
            case OP_INVOKE_INTERFACE_RANGE:
                isRange = true;
                calleeMethod = lastMIRInsn->meta.callsiteInfo->method;
                break;
            default:
                break;
        }

        if (calleeMethod) {
            bool inlined = tryInlineVirtualCallsite(cUnit, calleeMethod,
                                                    lastMIRInsn, bb, isRange);
            if (!inlined &&
                !(gDvmJit.disableOpt & (1 << kMethodJit)) &&
                !dvmIsNativeMethod(calleeMethod)) {
                CompilerMethodStats *methodStats =
                    dvmCompilerAnalyzeMethodBody(calleeMethod, true);
                if ((methodStats->attributes & METHOD_IS_LEAF) &&
                    !(methodStats->attributes & METHOD_CANNOT_COMPILE)) {
                    /* Callee has been previously compiled */
                    if (dvmJitGetMethodAddr(calleeMethod->insns)) {
                        lastMIRInsn->OptimizationFlags |= MIR_INVOKE_METHOD_JIT;
                    } else {
                        /* Compile the callee first */
                        dvmCompileMethod(calleeMethod, info);
                        if (dvmJitGetMethodAddr(calleeMethod->insns)) {
                            lastMIRInsn->OptimizationFlags |=
                                MIR_INVOKE_METHOD_JIT;
                        } else {
                            methodStats->attributes |= METHOD_CANNOT_COMPILE;
                        }
                    }
                }
            }
            return;
        }
    }
}