/* * 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; }
/* 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; }
/* 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; } } }