diff options
Diffstat (limited to 'src/compiler')
| -rw-r--r-- | src/compiler/Compiler.h | 1 | ||||
| -rw-r--r-- | src/compiler/CompilerIR.h | 14 | ||||
| -rw-r--r-- | src/compiler/Dataflow.cc | 192 | ||||
| -rw-r--r-- | src/compiler/Frontend.cc | 121 | ||||
| -rw-r--r-- | src/compiler/Ralloc.cc | 26 | ||||
| -rw-r--r-- | src/compiler/Utility.cc | 11 | ||||
| -rw-r--r-- | src/compiler/codegen/MethodBitcode.cc | 121 | ||||
| -rw-r--r-- | src/compiler/codegen/MethodCodegenDriver.cc | 33 |
8 files changed, 312 insertions, 207 deletions
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h index 00ab796a81..214f603080 100644 --- a/src/compiler/Compiler.h +++ b/src/compiler/Compiler.h @@ -129,6 +129,7 @@ enum debugControlVector { kDebugCountOpcodes, #if defined(ART_USE_QUICK_COMPILER) kDebugDumpBitcodeFile, + kDebugVerifyBitcode, #endif }; diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h index 453ccdf556..69689f94ac 100644 --- a/src/compiler/CompilerIR.h +++ b/src/compiler/CompilerIR.h @@ -196,9 +196,10 @@ enum ExtendedMIROpcode { kMirOpFusedCmpgDouble, kMirOpFusedCmpLong, kMirOpNop, - kMirOpNullNRangeUpCheck, - kMirOpNullNRangeDownCheck, - kMirOpLowerBound, + kMirOpNullCheck, + kMirOpRangeCheck, + kMirOpDivZeroCheck, + kMirOpCheck, kMirOpLast, }; @@ -245,12 +246,10 @@ struct MIR { int optimizationFlags; int seqNum; union { - // Used by the inlined insn from the callee to find the mother method - const Method* calleeMethod; - // Used by the inlined invoke to find the class and method pointers - CallsiteInfo* callsiteInfo; // Used to quickly locate all Phi opcodes MIR* phiNext; + // Establish link between two halves of throwing instructions + MIR* throwInsn; } meta; }; @@ -278,7 +277,6 @@ struct BasicBlock { uint16_t nestingDepth; const Method* containingMethod; // For blocks from the callee BBType blockType; - bool needFallThroughBranch; // For blocks ended due to length limit bool isFallThroughFromInvoke; // True means the block needs alignment MIR* firstMIRInsn; MIR* lastMIRInsn; diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc index fc1d262454..0925793501 100644 --- a/src/compiler/Dataflow.cc +++ b/src/compiler/Dataflow.cc @@ -822,13 +822,16 @@ const int oatDataFlowAttributes[kMirOpLast] = { // 107 MIR_NOP DF_NOP, - // 108 MIR_NULL_RANGE_UP_CHECK + // 108 MIR_NULL_CHECK 0, - // 109 MIR_NULL_RANGE_DOWN_CHECK + // 109 MIR_RANGE_CHECK 0, - // 110 MIR_LOWER_BOUND + // 110 MIR_DIV_ZERO_CHECK + 0, + + // 111 MIR_CHECK 0, }; @@ -855,27 +858,29 @@ int getSSAUseCount(CompilationUnit* cUnit, int sReg) char* oatGetDalvikDisassembly(CompilationUnit* cUnit, const DecodedInstruction& insn, const char* note) { - char buffer[256]; - Instruction::Code opcode = insn.opcode; + std::string str; + int opcode = insn.opcode; int dfAttributes = oatDataFlowAttributes[opcode]; int flags; char* ret; - buffer[0] = 0; - if ((int)opcode >= (int)kMirOpFirst) { - if ((int)opcode == (int)kMirOpPhi) { - strcpy(buffer, "PHI"); + if (opcode >= kMirOpFirst) { + if (opcode == kMirOpPhi) { + str.append("PHI"); + } else if (opcode == kMirOpCheck) { + str.append("Check"); } else { - sprintf(buffer, "Opcode %#x", opcode); + str.append(StringPrintf("Opcode %#x", opcode)); } flags = 0; } else { - strcpy(buffer, Instruction::Name(opcode)); - flags = Instruction::Flags(opcode); + str.append(Instruction::Name(insn.opcode)); + flags = Instruction::Flags(insn.opcode); } - if (note) - strcat(buffer, note); + if (note) { + str.append(note); + } /* For branches, decode the instructions to print out the branch targets */ if (flags & Instruction::kBranch) { @@ -883,11 +888,11 @@ char* oatGetDalvikDisassembly(CompilationUnit* cUnit, int offset = 0; switch (dalvikFormat) { case Instruction::k21t: - snprintf(buffer + strlen(buffer), 256, " v%d,", insn.vA); + str.append(StringPrintf(" v%d,", insn.vA)); offset = (int) insn.vB; break; case Instruction::k22t: - snprintf(buffer + strlen(buffer), 256, " v%d, v%d,", insn.vA, insn.vB); + str.append(StringPrintf(" v%d, v%d,", insn.vA, insn.vB)); offset = (int) insn.vC; break; case Instruction::k10t: @@ -899,45 +904,43 @@ char* oatGetDalvikDisassembly(CompilationUnit* cUnit, LOG(FATAL) << "Unexpected branch format " << (int)dalvikFormat << " / opcode " << (int)opcode; } - snprintf(buffer + strlen(buffer), 256, " (%c%x)", - offset > 0 ? '+' : '-', - offset > 0 ? offset : -offset); + str.append(StringPrintf(" (%c%x)", + offset > 0 ? '+' : '-', + offset > 0 ? offset : -offset)); } else if (dfAttributes & DF_FORMAT_35C) { unsigned int i; for (i = 0; i < insn.vA; i++) { - if (i != 0) strcat(buffer, ","); - snprintf(buffer + strlen(buffer), 256, " v%d", insn.arg[i]); + if (i != 0) str.append(","); + str.append(StringPrintf(" v%d", insn.arg[i])); } } else if (dfAttributes & DF_FORMAT_3RC) { - snprintf(buffer + strlen(buffer), 256, - " v%d..v%d", insn.vC, insn.vC + insn.vA - 1); + str.append(StringPrintf(" v%d..v%d", insn.vC, insn.vC + insn.vA - 1)); } else { if (dfAttributes & DF_A_IS_REG) { - snprintf(buffer + strlen(buffer), 256, " v%d", insn.vA); + str.append(StringPrintf(" v%d", insn.vA)); } if (dfAttributes & DF_B_IS_REG) { - snprintf(buffer + strlen(buffer), 256, ", v%d", insn.vB); + str.append(StringPrintf(", v%d", insn.vB)); } else if ((int)opcode < (int)kMirOpFirst) { - snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn.vB); + str.append(StringPrintf(", (#%d)", insn.vB)); } if (dfAttributes & DF_C_IS_REG) { - snprintf(buffer + strlen(buffer), 256, ", v%d", insn.vC); + str.append(StringPrintf(", v%d", insn.vC)); } else if ((int)opcode < (int)kMirOpFirst) { - snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn.vC); + str.append(StringPrintf(", (#%d)", insn.vC)); } } - int length = strlen(buffer) + 1; + int length = str.length() + 1; ret = (char*)oatNew(cUnit, length, false, kAllocDFInfo); - memcpy(ret, buffer, length); + strncpy(ret, str.c_str(), length); return ret; } -char* getSSAName(const CompilationUnit* cUnit, int ssaReg, char* name) +std::string getSSAName(const CompilationUnit* cUnit, int ssaReg) { - sprintf(name, "v%d_%d", SRegToVReg(cUnit, ssaReg), - SRegToSubscript(cUnit, ssaReg)); - return name; + return StringPrintf("v%d_%d", SRegToVReg(cUnit, ssaReg), + SRegToSubscript(cUnit, ssaReg)); } /* @@ -945,32 +948,38 @@ char* getSSAName(const CompilationUnit* cUnit, int ssaReg, char* name) */ char* oatFullDisassembler(CompilationUnit* cUnit, const MIR* mir) { - char buffer[256]; - char operand0[32], operand1[32]; + std::string str; const DecodedInstruction* insn = &mir->dalvikInsn; - Instruction::Code opcode = insn->opcode; + int opcode = insn->opcode; int dfAttributes = oatDataFlowAttributes[opcode]; char* ret; int length; - buffer[0] = 0; - if (static_cast<int>(opcode) >= static_cast<int>(kMirOpFirst)) { - if (static_cast<int>(opcode) == static_cast<int>(kMirOpPhi)) { - snprintf(buffer, 256, "PHI %s = (%s", - getSSAName(cUnit, mir->ssaRep->defs[0], operand0), - getSSAName(cUnit, mir->ssaRep->uses[0], operand1)); + if (opcode >= kMirOpFirst) { + if (opcode == kMirOpPhi) { + int* incoming = (int*)mir->dalvikInsn.vB; + str.append(StringPrintf("PHI %s = (%s", + getSSAName(cUnit, mir->ssaRep->defs[0]).c_str(), + getSSAName(cUnit, mir->ssaRep->uses[0]).c_str())); + str.append(StringPrintf(":%d",incoming[0])); int i; for (i = 1; i < mir->ssaRep->numUses; i++) { - snprintf(buffer + strlen(buffer), 256, ", %s", - getSSAName(cUnit, mir->ssaRep->uses[i], operand0)); + str.append(StringPrintf(", %s:%d", + getSSAName(cUnit, mir->ssaRep->uses[i]).c_str(), + incoming[i])); } - snprintf(buffer + strlen(buffer), 256, ")"); + str.append(")"); + } else if (opcode == kMirOpCheck) { + str.append("Check "); + str.append(Instruction::Name(mir->meta.throwInsn->dalvikInsn.opcode)); + } else if (opcode == kMirOpNop) { + str.append("MirNop"); } else { - sprintf(buffer, "Opcode %#x", opcode); + str.append(StringPrintf("Opcode %#x", opcode)); } goto done; } else { - strcpy(buffer, Instruction::Name(opcode)); + str.append(Instruction::Name(insn->opcode)); } /* For branches, decode the instructions to print out the branch targets */ @@ -979,14 +988,14 @@ char* oatFullDisassembler(CompilationUnit* cUnit, const MIR* mir) int delta = 0; switch (dalvikFormat) { case Instruction::k21t: - snprintf(buffer + strlen(buffer), 256, " %s, ", - getSSAName(cUnit, mir->ssaRep->uses[0], operand0)); + str.append(StringPrintf(" %s, ", + getSSAName(cUnit, mir->ssaRep->uses[0]).c_str())); delta = (int) insn->vB; break; case Instruction::k22t: - snprintf(buffer + strlen(buffer), 256, " %s, %s, ", - getSSAName(cUnit, mir->ssaRep->uses[0], operand0), - getSSAName(cUnit, mir->ssaRep->uses[1], operand1)); + str.append(StringPrintf(" %s, %s, ", + getSSAName(cUnit, mir->ssaRep->uses[0]).c_str(), + getSSAName(cUnit, mir->ssaRep->uses[1]).c_str())); delta = (int) insn->vC; break; case Instruction::k10t: @@ -997,54 +1006,53 @@ char* oatFullDisassembler(CompilationUnit* cUnit, const MIR* mir) default: LOG(FATAL) << "Unexpected branch format: " << (int)dalvikFormat; } - snprintf(buffer + strlen(buffer), 256, " %04x", - mir->offset + delta); + str.append(StringPrintf(" %04x", mir->offset + delta)); } else if (dfAttributes & (DF_FORMAT_35C | DF_FORMAT_3RC)) { unsigned int i; for (i = 0; i < insn->vA; i++) { - if (i != 0) strcat(buffer, ","); - snprintf(buffer + strlen(buffer), 256, " %s", - getSSAName(cUnit, mir->ssaRep->uses[i], operand0)); + if (i != 0) str.append(","); + str.append(" "); + str.append(getSSAName(cUnit, mir->ssaRep->uses[i])); } } else { int udIdx; if (mir->ssaRep->numDefs) { for (udIdx = 0; udIdx < mir->ssaRep->numDefs; udIdx++) { - snprintf(buffer + strlen(buffer), 256, " %s", - getSSAName(cUnit, mir->ssaRep->defs[udIdx], operand0)); + str.append(" "); + str.append(getSSAName(cUnit, mir->ssaRep->defs[udIdx])); } - strcat(buffer, ","); + str.append(","); } if (mir->ssaRep->numUses) { /* No leading ',' for the first use */ - snprintf(buffer + strlen(buffer), 256, " %s", - getSSAName(cUnit, mir->ssaRep->uses[0], operand0)); + str.append(" "); + str.append(getSSAName(cUnit, mir->ssaRep->uses[0])); for (udIdx = 1; udIdx < mir->ssaRep->numUses; udIdx++) { - snprintf(buffer + strlen(buffer), 256, ", %s", - getSSAName(cUnit, mir->ssaRep->uses[udIdx], operand0)); + str.append(", "); + str.append(getSSAName(cUnit, mir->ssaRep->uses[udIdx])); } } if (static_cast<int>(opcode) < static_cast<int>(kMirOpFirst)) { - Instruction::Format dalvikFormat = Instruction::FormatOf(opcode); + Instruction::Format dalvikFormat = Instruction::FormatOf(insn->opcode); switch (dalvikFormat) { case Instruction::k11n: // op vA, #+B case Instruction::k21s: // op vAA, #+BBBB case Instruction::k21h: // op vAA, #+BBBB00000[00000000] case Instruction::k31i: // op vAA, #+BBBBBBBB case Instruction::k51l: // op vAA, #+BBBBBBBBBBBBBBBB - snprintf(buffer + strlen(buffer), 256, " #%#x", insn->vB); + str.append(StringPrintf(" #%#x", insn->vB)); break; case Instruction::k21c: // op vAA, thing@BBBB case Instruction::k31c: // op vAA, thing@BBBBBBBB - snprintf(buffer + strlen(buffer), 256, " @%#x", insn->vB); + str.append(StringPrintf(" @%#x", insn->vB)); break; case Instruction::k22b: // op vAA, vBB, #+CC case Instruction::k22s: // op vA, vB, #+CCCC - snprintf(buffer + strlen(buffer), 256, " #%#x", insn->vC); + str.append(StringPrintf(" #%#x", insn->vC)); break; case Instruction::k22c: // op vA, vB, thing@CCCC - snprintf(buffer + strlen(buffer), 256, " @%#x", insn->vC); + str.append(StringPrintf(" @%#x", insn->vC)); break; /* No need for special printing */ default: @@ -1054,44 +1062,38 @@ char* oatFullDisassembler(CompilationUnit* cUnit, const MIR* mir) } done: - length = strlen(buffer) + 1; + length = str.length() + 1; ret = (char*) oatNew(cUnit, length, false, kAllocDFInfo); - memcpy(ret, buffer, length); + strncpy(ret, str.c_str(), length); return ret; } char* oatGetSSAString(CompilationUnit* cUnit, SSARepresentation* ssaRep) { - char buffer[256]; + std::string str; char* ret; int i; - buffer[0] = 0; for (i = 0; i < ssaRep->numDefs; i++) { int ssaReg = ssaRep->defs[i]; - sprintf(buffer + strlen(buffer), "s%d(v%d_%d) ", ssaReg, - SRegToVReg(cUnit, ssaReg), SRegToSubscript(cUnit, ssaReg)); + str.append(StringPrintf("s%d(v%d_%d) ", ssaReg, + SRegToVReg(cUnit, ssaReg), + SRegToSubscript(cUnit, ssaReg))); } if (ssaRep->numDefs) { - strcat(buffer, "<- "); + str.append("<- "); } for (i = 0; i < ssaRep->numUses; i++) { - int len = strlen(buffer); int ssaReg = ssaRep->uses[i]; - - if (snprintf(buffer + len, 250 - len, "s%d(v%d_%d) ", ssaReg, - SRegToVReg(cUnit, ssaReg), - SRegToSubscript(cUnit, ssaReg))) { - strcat(buffer, "..."); - break; - } + str.append(StringPrintf("s%d(v%d_%d) ", ssaReg, SRegToVReg(cUnit, ssaReg), + SRegToSubscript(cUnit, ssaReg))); } - int length = strlen(buffer) + 1; + int length = str.length() + 1; ret = (char*)oatNew(cUnit, length, false, kAllocDFInfo); - memcpy(ret, buffer, length); + strncpy(ret, str.c_str(), length); return ret; } @@ -1183,8 +1185,10 @@ int addNewSReg(CompilationUnit* cUnit, int vReg) int ssaReg = cUnit->numSSARegs++; oatInsertGrowableList(cUnit, cUnit->ssaBaseVRegs, vReg); oatInsertGrowableList(cUnit, cUnit->ssaSubscripts, subscript); - char* name = (char*)oatNew(cUnit, SSA_NAME_MAX, true, kAllocDFInfo); - oatInsertGrowableList(cUnit, cUnit->ssaStrings, (intptr_t)getSSAName(cUnit, ssaReg, name)); + std::string ssaName = getSSAName(cUnit, ssaReg); + char* name = (char*)oatNew(cUnit, ssaName.length() + 1, false, kAllocDFInfo); + strncpy(name, ssaName.c_str(), ssaName.length() + 1); + oatInsertGrowableList(cUnit, cUnit->ssaStrings, (intptr_t)name); DCHECK_EQ(cUnit->ssaBaseVRegs->numUsed, cUnit->ssaSubscripts->numUsed); return ssaReg; } @@ -1492,8 +1496,10 @@ void oatInitializeSSAConversion(CompilationUnit* cUnit) for (i = 0; i < numDalvikReg; i++) { oatInsertGrowableList(cUnit, cUnit->ssaBaseVRegs, i); oatInsertGrowableList(cUnit, cUnit->ssaSubscripts, 0); - char* name = (char*)oatNew(cUnit, SSA_NAME_MAX, true, kAllocDFInfo); - oatInsertGrowableList(cUnit, cUnit->ssaStrings, (intptr_t)getSSAName(cUnit, i, name)); + std::string ssaName = getSSAName(cUnit, i); + char* name = (char*)oatNew(cUnit, ssaName.length() + 1, true, kAllocDFInfo); + strncpy(name, ssaName.c_str(), ssaName.length() + 1); + oatInsertGrowableList(cUnit, cUnit->ssaStrings, (intptr_t)name); } /* @@ -1687,14 +1693,14 @@ MIR* oatFindMoveResult(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir) BasicBlock* tbb = bb; mir = advanceMIR(cUnit, &tbb, mir, NULL, false); while (mir != NULL) { + int opcode = mir->dalvikInsn.opcode; if ((mir->dalvikInsn.opcode == Instruction::MOVE_RESULT) || (mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) || (mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_WIDE)) { break; } // Keep going if pseudo op, otherwise terminate - if (mir->dalvikInsn.opcode < - static_cast<Instruction::Code>(kNumPackedOpcodes)) { + if (opcode < kNumPackedOpcodes) { mir = NULL; } else { mir = advanceMIR(cUnit, &tbb, mir, NULL, false); diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc index 6cdfebc014..b893cca5f6 100644 --- a/src/compiler/Frontend.cc +++ b/src/compiler/Frontend.cc @@ -54,6 +54,7 @@ static uint32_t kCompilerDebugFlags = 0 | // Enable debug/testing modes //(1 << kDebugCountOpcodes) | #if defined(ART_USE_QUICK_COMPILER) //(1 << kDebugDumpBitcodeFile) | + //(1 << kDebugVerifyBitcode) | #endif 0; @@ -154,10 +155,8 @@ BasicBlock *splitBlock(CompilationUnit* cUnit, unsigned int codeOffset, } /* Handle the fallthrough path */ - bottomBlock->needFallThroughBranch = origBlock->needFallThroughBranch; bottomBlock->fallThrough = origBlock->fallThrough; origBlock->fallThrough = bottomBlock; - origBlock->needFallThroughBranch = true; oatInsertGrowableList(cUnit, bottomBlock->predecessors, (intptr_t)origBlock); if (bottomBlock->fallThrough) { @@ -289,12 +288,12 @@ void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix) blockIdx); if (bb == NULL) break; if (bb->blockType == kEntryBlock) { - fprintf(file, " entry [shape=Mdiamond];\n"); + fprintf(file, " entry_%d [shape=Mdiamond];\n", bb->id); } else if (bb->blockType == kExitBlock) { - fprintf(file, " exit [shape=Mdiamond];\n"); + fprintf(file, " exit_%d [shape=Mdiamond];\n", bb->id); } else if (bb->blockType == kDalvikByteCode) { - fprintf(file, " block%04x [shape=record,label = \"{ \\\n", - bb->startOffset); + fprintf(file, " block%04x_%d [shape=record,label = \"{ \\\n", + bb->startOffset, bb->id); const MIR *mir; fprintf(file, " {block id %d\\l}%s\\\n", bb->id, bb->firstMIRInsn ? " | " : " "); @@ -327,8 +326,8 @@ void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix) } if (bb->successorBlockList.blockListType != kNotUsed) { - fprintf(file, " succ%04x [shape=%s,label = \"{ \\\n", - bb->startOffset, + fprintf(file, " succ%04x_%d [shape=%s,label = \"{ \\\n", + bb->startOffset, bb->id, (bb->successorBlockList.blockListType == kCatch) ? "Mrecord" : "record"); GrowableListIterator iterator; @@ -356,8 +355,8 @@ void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix) fprintf(file, " }\"];\n\n"); oatGetBlockName(bb, blockName1); - fprintf(file, " %s:s -> succ%04x:n [style=dashed]\n", - blockName1, bb->startOffset); + fprintf(file, " %s:s -> succ%04x_%d:n [style=dashed]\n", + blockName1, bb->startOffset, bb->id); if (bb->successorBlockList.blockListType == kPackedSwitch || bb->successorBlockList.blockListType == kSparseSwitch) { @@ -374,8 +373,8 @@ void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix) BasicBlock *destBlock = successorBlockInfo->block; oatGetBlockName(destBlock, blockName2); - fprintf(file, " succ%04x:f%d:e -> %s:n\n", bb->startOffset, - succId++, blockName2); + fprintf(file, " succ%04x_%d:f%d:e -> %s:n\n", bb->startOffset, + bb->id, succId++, blockName2); } } } @@ -644,18 +643,20 @@ void processCanSwitch(CompilationUnit* cUnit, BasicBlock* curBlock, } /* Process instructions with the kThrow flag */ -void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, MIR* insn, - int curOffset, int width, int flags, - ArenaBitVector* tryBlockAddr, const u2* codePtr, - const u2* codeEnd) +BasicBlock* processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, + MIR* insn, int curOffset, int width, int flags, + ArenaBitVector* tryBlockAddr, const u2* codePtr, + const u2* codeEnd) { const DexFile::CodeItem* code_item = cUnit->code_item; + bool inTryBlock = oatIsBitSet(tryBlockAddr, curOffset); /* In try block */ - if (oatIsBitSet(tryBlockAddr, curOffset)) { + if (inTryBlock) { CatchHandlerIterator iterator(*code_item, curOffset); if (curBlock->successorBlockList.blockListType != kNotUsed) { + LOG(INFO) << PrettyMethod(cUnit->method_idx, *cUnit->dex_file); LOG(FATAL) << "Successor block list already in use: " << (int)curBlock->successorBlockList.blockListType; } @@ -688,37 +689,46 @@ void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, MIR* insn, oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock); } - /* - * Force the current block to terminate. - * - * Data may be present before codeEnd, so we need to parse it to know - * whether it is code or data. - */ - if (codePtr < codeEnd) { - /* Create a fallthrough block for real instructions (incl. NOP) */ - if (contentIsInsn(codePtr)) { - BasicBlock *fallthroughBlock = findBlock(cUnit, - curOffset + width, - /* split */ - false, - /* create */ - true, - /* immedPredBlockP */ - NULL); - /* - * THROW is an unconditional branch. NOTE: - * THROW_VERIFICATION_ERROR is also an unconditional - * branch, but we shouldn't treat it as such until we have - * a dead code elimination pass (which won't be important - * until inlining w/ constant propagation is implemented. - */ - if (insn->dalvikInsn.opcode != Instruction::THROW) { - curBlock->fallThrough = fallthroughBlock; - oatInsertGrowableList(cUnit, fallthroughBlock->predecessors, - (intptr_t)curBlock); - } + if (insn->dalvikInsn.opcode == Instruction::THROW){ + if ((codePtr < codeEnd) && contentIsInsn(codePtr)) { + // Force creation of new block following THROW via side-effect + findBlock(cUnit, curOffset + width, /* split */ false, + /* create */ true, /* immedPredBlockP */ NULL); + } + if (!inTryBlock) { + // Don't split a THROW that can't rethrow - we're done. + return curBlock; } } + + /* + * Split the potentially-throwing instruction into two parts. + * The first half will be a pseudo-op that captures the exception + * edges and terminates the basic block. It always falls through. + * Then, create a new basic block that begins with the throwing instruction + * (minus exceptions). Note: this new basic block must NOT be entered into + * the blockMap. If the potentially-throwing instruction is the target of a + * future branch, we need to find the check psuedo half. The new + * basic block containing the work portion of the instruction should + * only be entered via fallthrough from the block containing the + * pseudo exception edge MIR. Note also that this new block is + * not automatically terminated after the work portion, and may + * contain following instructions. + */ + BasicBlock *newBlock = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++); + oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t)newBlock); + newBlock->startOffset = insn->offset; + curBlock->fallThrough = newBlock; + oatInsertGrowableList(cUnit, newBlock->predecessors, (intptr_t)curBlock); + MIR* newInsn = (MIR*)oatNew(cUnit, sizeof(MIR), true, kAllocMIR); + *newInsn = *insn; + insn->dalvikInsn.opcode = + static_cast<Instruction::Code>(kMirOpCheck); + // Associate the two halves + insn->meta.throwInsn = newInsn; + newInsn->meta.throwInsn = insn; + oatAppendMIR(newBlock, newInsn); + return newBlock; } void oatInit(CompilationUnit* cUnit, const Compiler& compiler) { @@ -762,15 +772,11 @@ CompiledMethod* oatCompileMethod(Compiler& compiler, cUnit->numRegs = code_item->registers_size_ - cUnit->numIns; cUnit->numOuts = code_item->outs_size_; #if defined(ART_USE_QUICK_COMPILER) - // TODO: fix bug and remove this workaround - std::string methodName = PrettyMethod(method_idx, dex_file); - if ((methodName.find("gdata2.AndroidGDataClient.createAndExecuteMethod") - != std::string::npos) || (methodName.find("hG.a") != std::string::npos) - || (methodName.find("hT.a(hV, java.lang.String, java.lang.String, java") - != std::string::npos) || (methodName.find("AndroidHttpTransport.exchange") - != std::string::npos)) { - LOG(INFO) << "Skipping bitcode generation for " << methodName; - } else { + DCHECK((cUnit->instructionSet == kThumb2) || + (cUnit->instructionSet == kX86) || + (cUnit->instructionSet == kMips)); + if (cUnit->instructionSet == kThumb2) { + // TODO: remove this once x86 is tested cUnit->genBitcode = true; } #endif @@ -790,6 +796,7 @@ CompiledMethod* oatCompileMethod(Compiler& compiler, } #if defined(ART_USE_QUICK_COMPILER) if (cUnit->genBitcode) { + //cUnit->enableDebug |= (1 << kDebugVerifyBitcode); //cUnit->printMe = true; //cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile); // Disable non-safe optimizations for now @@ -957,8 +964,8 @@ CompiledMethod* oatCompileMethod(Compiler& compiler, } } } else if (flags & Instruction::kThrow) { - processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags, - tryBlockAddr, codePtr, codeEnd); + curBlock = processCanThrow(cUnit.get(), curBlock, insn, curOffset, + width, flags, tryBlockAddr, codePtr, codeEnd); } else if (flags & Instruction::kSwitch) { processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags); } diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc index 500b1b2d1b..f4e735a5b5 100644 --- a/src/compiler/Ralloc.cc +++ b/src/compiler/Ralloc.cc @@ -89,20 +89,6 @@ bool remapNames(CompilationUnit* cUnit, BasicBlock* bb) return false; } -// Try to find the next move result which might have an FP target -SSARepresentation* findFPMoveResult(MIR* mir) -{ - SSARepresentation* res = NULL; - for (; mir; mir = mir->next) { - if ((mir->dalvikInsn.opcode == Instruction::MOVE_RESULT) || - (mir->dalvikInsn.opcode == Instruction::MOVE_RESULT_WIDE)) { - res = mir->ssaRep; - break; - } - } - return res; -} - /* * Infer types and sizes. We don't need to track change on sizes, * as it doesn't propagate. We're guaranteed at least one pass through @@ -236,14 +222,12 @@ bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb) const char* shorty = oatGetShortyFromTargetIdx(cUnit, target_idx); // Handle result type if floating point if ((shorty[0] == 'F') || (shorty[0] == 'D')) { - // Find move-result that consumes this result - SSARepresentation* tgtRep = findFPMoveResult(mir->next); - // Might be in next basic block - if (!tgtRep) { - tgtRep = findFPMoveResult(bb->fallThrough->firstMIRInsn); - } + MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir); // Result might not be used at all, so no move-result - if (tgtRep) { + if (moveResultMIR && (moveResultMIR->dalvikInsn.opcode != + Instruction::MOVE_RESULT_OBJECT)) { + SSARepresentation* tgtRep = moveResultMIR->ssaRep; + DCHECK(tgtRep != NULL); tgtRep->fpDef[0] = true; changed |= setFp(cUnit, tgtRep->defs[0], true); if (shorty[0] == 'D') { diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc index 571208fe45..c865718536 100644 --- a/src/compiler/Utility.cc +++ b/src/compiler/Utility.cc @@ -687,19 +687,20 @@ void oatGetBlockName(BasicBlock* bb, char* name) { switch (bb->blockType) { case kEntryBlock: - snprintf(name, BLOCK_NAME_LEN, "entry"); + snprintf(name, BLOCK_NAME_LEN, "entry_%d", bb->id); break; case kExitBlock: - snprintf(name, BLOCK_NAME_LEN, "exit"); + snprintf(name, BLOCK_NAME_LEN, "exit_%d", bb->id); break; case kDalvikByteCode: - snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset); + snprintf(name, BLOCK_NAME_LEN, "block%04x_%d", bb->startOffset, bb->id); break; case kExceptionHandling: - snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset); + snprintf(name, BLOCK_NAME_LEN, "exception%04x_%d", bb->startOffset, + bb->id); break; default: - snprintf(name, BLOCK_NAME_LEN, "??"); + snprintf(name, BLOCK_NAME_LEN, "??_%d", bb->id); break; } } diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc index a8da1cde44..e7e4e5a190 100644 --- a/src/compiler/codegen/MethodBitcode.cc +++ b/src/compiler/codegen/MethodBitcode.cc @@ -51,7 +51,7 @@ void defineValue(CompilationUnit* cUnit, llvm::Value* val, int sReg) llvm::Value* placeholder = getLLVMValue(cUnit, sReg); if (placeholder == NULL) { // This can happen on instruction rewrite on verification failure - LOG(WARNING) << "Null placeholder - invalid CFG"; + LOG(WARNING) << "Null placeholder"; return; } placeholder->replaceAllUsesWith(val); @@ -307,7 +307,6 @@ void convertThrow(CompilationUnit* cUnit, RegLocation rlSrc) llvm::Function* func = cUnit->intrinsic_helper->GetIntrinsicFunction( greenland::IntrinsicHelper::Throw); cUnit->irb->CreateCall(func, src); - cUnit->irb->CreateUnreachable(); } void convertMonitorEnterExit(CompilationUnit* cUnit, int optFlags, @@ -812,6 +811,15 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, bool objectDefinition = false; + if (cUnit->printMe) { + if ((int)opcode < kMirOpFirst) { + LOG(INFO) << ".. " << Instruction::Name(opcode) << " 0x" + << std::hex << (int)opcode; + } else { + LOG(INFO) << ".. opcode 0x" << std::hex << (int)opcode; + } + } + /* Prep Src and Dest locations */ int nextSreg = 0; int nextLoc = 0; @@ -1292,10 +1300,24 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, case Instruction::THROW: convertThrow(cUnit, rlSrc[0]); + /* + * If this throw is standalone, terminate. + * If it might rethrow, force termination + * of the following block. + */ + if (bb->fallThrough == NULL) { + cUnit->irb->CreateUnreachable(); + } else { + bb->fallThrough->fallThrough = NULL; + bb->fallThrough->taken = NULL; + } break; case Instruction::THROW_VERIFICATION_ERROR: convertThrowVerificationError(cUnit, vA, vB); + UNIMPLEMENTED(WARNING) << "Need dead code elimination pass" + << " - disabling bitcode verification"; + cUnit->enableDebug &= ~(1 << kDebugVerifyBitcode); break; case Instruction::MOVE_RESULT_WIDE: @@ -1306,7 +1328,8 @@ bool convertMIRNode(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, * Instruction rewriting on verification failure can eliminate * the invoke that feeds this move0result. It won't ever be reached, * so we can ignore it. - * TODO: verify that previous instruction if THROW_VERIFICATION_ERROR + * TODO: verify that previous instruction is THROW_VERIFICATION_ERROR, + * or better, add dead-code elimination. */ UNIMPLEMENTED(WARNING) << "Need to verify previous inst was rewritten"; #else @@ -1649,6 +1672,13 @@ void convertExtendedMIR(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir, UNIMPLEMENTED(WARNING) << "unimp kMirOpPhi"; break; } + case kMirOpNop: + if ((mir == bb->lastMIRInsn) && (bb->taken == NULL) && + (bb->fallThrough == NULL)) { + cUnit->irb->CreateUnreachable(); + } + break; + #if defined(TARGET_ARM) case kMirOpFusedCmplFloat: UNIMPLEMENTED(WARNING) << "unimp kMirOpFusedCmpFloat"; @@ -1720,6 +1750,16 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb) cUnit->irb->SetInsertPoint(llvmBB); setDexOffset(cUnit, bb->startOffset); + if (cUnit->printMe) { + LOG(INFO) << "................................"; + LOG(INFO) << "Block id " << bb->id; + if (llvmBB != NULL) { + LOG(INFO) << "label " << llvmBB->getName().str().c_str(); + } else { + LOG(INFO) << "llvmBB is NULL"; + } + } + if (bb->blockType == kEntryBlock) { setMethodInfo(cUnit); bool *canBeRef = (bool*) oatNew(cUnit, sizeof(bool) * @@ -1759,8 +1799,6 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb) /* * Because we're deferring null checking, delete the associated empty * exception block. - * TODO: add new block type for exception blocks that we generate - * greenland code for. */ llvmBB->eraseFromParent(); return false; @@ -1770,8 +1808,9 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb) setDexOffset(cUnit, mir->offset); - Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode; - Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode); + int opcode = mir->dalvikInsn.opcode; + Instruction::Format dalvikFormat = + Instruction::FormatOf(mir->dalvikInsn.opcode); /* If we're compiling for the debugger, generate an update callout */ if (cUnit->genDebugger) { @@ -1779,7 +1818,43 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb) //genDebuggerUpdate(cUnit, mir->offset); } - if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) { + if (opcode == kMirOpCheck) { + // Combine check and work halves of throwing instruction. + MIR* workHalf = mir->meta.throwInsn; + mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode; + opcode = mir->dalvikInsn.opcode; + SSARepresentation* ssaRep = workHalf->ssaRep; + workHalf->ssaRep = mir->ssaRep; + mir->ssaRep = ssaRep; + workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); + if (bb->successorBlockList.blockListType == kCatch) { + llvm::Function* intr = cUnit->intrinsic_helper->GetIntrinsicFunction( + greenland::IntrinsicHelper::CatchTargets); + llvm::Value* switchKey = + cUnit->irb->CreateCall(intr, cUnit->irb->getInt32(mir->offset)); + GrowableListIterator iter; + oatGrowableListIteratorInit(&bb->successorBlockList.blocks, &iter); + // New basic block to use for work half + llvm::BasicBlock* workBB = + llvm::BasicBlock::Create(*cUnit->context, "", cUnit->func); + llvm::SwitchInst* sw = + cUnit->irb->CreateSwitch(switchKey, workBB, + bb->successorBlockList.blocks.numUsed); + while (true) { + SuccessorBlockInfo *successorBlockInfo = + (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iter); + if (successorBlockInfo == NULL) break; + llvm::BasicBlock *target = + getLLVMBlock(cUnit, successorBlockInfo->block->id); + int typeIndex = successorBlockInfo->key; + sw->addCase(cUnit->irb->getInt32(typeIndex), target); + } + llvmBB = workBB; + cUnit->irb->SetInsertPoint(llvmBB); + } + } + + if (opcode >= kMirOpFirst) { convertExtendedMIR(cUnit, bb, mir, llvmBB); continue; } @@ -1787,8 +1862,9 @@ bool methodBlockBitcodeConversion(CompilationUnit* cUnit, BasicBlock* bb) bool notHandled = convertMIRNode(cUnit, mir, bb, llvmBB, NULL /* labelList */); if (notHandled) { + Instruction::Code dalvikOpcode = static_cast<Instruction::Code>(opcode); LOG(WARNING) << StringPrintf("%#06x: Op %#x (%s) / Fmt %d not handled", - mir->offset, dalvikOpcode, + mir->offset, opcode, Instruction::Name(dalvikOpcode), dalvikFormat); } @@ -1986,7 +2062,14 @@ void oatMethodMIR2Bitcode(CompilationUnit* cUnit) cUnit->irb->SetInsertPoint(cUnit->entryBB); cUnit->irb->CreateBr(cUnit->entryTargetBB); - //llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction); + if (cUnit->enableDebug & (1 << kDebugVerifyBitcode)) { + if (llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction)) { + LOG(INFO) << "Bitcode verification FAILED for " + << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) + << " of size " << cUnit->insnsSize; + cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile); + } + } if (cUnit->enableDebug & (1 << kDebugDumpBitcodeFile)) { // Write bitcode to file @@ -3134,6 +3217,24 @@ bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb) cvtShiftOp(cUnit, Instruction::USHR_INT, callInst); break; + case greenland::IntrinsicHelper::CatchTargets: { + llvm::SwitchInst* swInst = + llvm::dyn_cast<llvm::SwitchInst>(nextIt); + DCHECK(swInst != NULL); + /* + * Discard the edges and the following conditional branch. + * Do a direct branch to the default target (which is the + * "work" portion of the pair. + * TODO: awful code layout - rework + */ + llvm::BasicBlock* targetBB = swInst->getDefaultDest(); + DCHECK(targetBB != NULL); + opUnconditionalBranch(cUnit, + cUnit->blockToLabelMap.Get(targetBB)); + ++it; + } + break; + default: LOG(FATAL) << "Unexpected intrinsic " << (int)id << ", " << cUnit->intrinsic_helper->GetName(id); diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc index e2a5f979d5..53377264b7 100644 --- a/src/compiler/codegen/MethodCodegenDriver.cc +++ b/src/compiler/codegen/MethodCodegenDriver.cc @@ -814,9 +814,10 @@ const char* extendedMIROpNames[kMirOpLast - kMirOpFirst] = { "kMirFusedCmpgDouble", "kMirFusedCmpLong", "kMirNop", - "kMirOpNullNRangeUpCheck", - "kMirOpNullNRangeDownCheck", - "kMirOpLowerBound", + "kMirOpNullCheck", + "kMirOpRangeCheck", + "kMirOpDivZeroCheck", + "kMirOpCheck", }; /* Extended MIR instructions like PHI */ @@ -905,7 +906,6 @@ bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) } for (mir = bb->firstMIRInsn; mir; mir = mir->next) { - oatResetRegPool(cUnit); if (cUnit->disableOpt & (1 << kTrackLiveTemps)) { oatClobberAllRegs(cUnit); @@ -921,10 +921,7 @@ bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) #endif cUnit->currentDalvikOffset = mir->offset; - - Instruction::Code dalvikOpcode = mir->dalvikInsn.opcode; - Instruction::Format dalvikFormat = Instruction::FormatOf(dalvikOpcode); - + int opcode = mir->dalvikInsn.opcode; LIR* boundaryLIR; /* Mark the beginning of a Dalvik instruction for line tracking */ @@ -951,17 +948,27 @@ bool methodBlockCodeGen(CompilationUnit* cUnit, BasicBlock* bb) newLIR1(cUnit, kPseudoSSARep, (int) ssaString); } - if ((int)mir->dalvikInsn.opcode >= (int)kMirOpFirst) { + if (opcode == kMirOpCheck) { + // Combine check and work halves of throwing instruction. + MIR* workHalf = mir->meta.throwInsn; + mir->dalvikInsn.opcode = workHalf->dalvikInsn.opcode; + opcode = workHalf->dalvikInsn.opcode; + SSARepresentation* ssaRep = workHalf->ssaRep; + workHalf->ssaRep = mir->ssaRep; + mir->ssaRep = ssaRep; + workHalf->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); + } + + if (opcode >= kMirOpFirst) { handleExtendedMethodMIR(cUnit, bb, mir); continue; } bool notHandled = compileDalvikInstruction(cUnit, mir, bb, labelList); if (notHandled) { - LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s) / Fmt %d not handled", - mir->offset, dalvikOpcode, - Instruction::Name(dalvikOpcode), dalvikFormat); - + LOG(FATAL) << StringPrintf("%#06x: Opcode %#x (%s)", + mir->offset, opcode, + Instruction::Name(mir->dalvikInsn.opcode)); } } |