diff options
Diffstat (limited to 'src/compiler/Frontend.cc')
| -rw-r--r-- | src/compiler/Frontend.cc | 121 | 
1 files changed, 64 insertions, 57 deletions
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc index b68233b4c0..6b45f0d2cd 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) { @@ -763,15 +773,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 @@ -791,6 +797,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 @@ -962,8 +969,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);      }  |