diff options
-rw-r--r-- | compiler/dex/mir_graph.cc | 161 | ||||
-rw-r--r-- | compiler/dex/mir_graph.h | 29 | ||||
-rw-r--r-- | compiler/dex/quick/dex_file_method_inliner.cc | 3 | ||||
-rw-r--r-- | compiler/dex/ssa_transformation.cc | 3 |
4 files changed, 183 insertions, 13 deletions
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index 08d1bca..4ba6677 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -196,7 +196,7 @@ BasicBlock* MIRGraph::SplitBlock(DexOffset code_offset, } orig_block->last_mir_insn = prev; - prev->next = NULL; + prev->next = nullptr; /* * Update the immediate predecessor block pointer so that outgoing edges @@ -220,6 +220,7 @@ BasicBlock* MIRGraph::SplitBlock(DexOffset code_offset, while (p != bottom_block->last_mir_insn) { p = p->next; DCHECK(p != nullptr); + p->bb = bottom_block->id; int opcode = p->dalvikInsn.opcode; /* * Some messiness here to ensure that we only enter real opcodes and only the @@ -543,7 +544,7 @@ BasicBlock* MIRGraph::ProcessCanThrow(BasicBlock* cur_block, MIR* insn, DexOffse new_block->start_offset = insn->offset; cur_block->fall_through = new_block->id; new_block->predecessors->Insert(cur_block->id); - MIR* new_insn = static_cast<MIR*>(arena_->Alloc(sizeof(MIR), kArenaAllocMIR)); + MIR* new_insn = NewMIR(); *new_insn = *insn; insn->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpCheck); @@ -629,7 +630,7 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ /* Parse all instructions and put them into containing basic blocks */ while (code_ptr < code_end) { - MIR *insn = static_cast<MIR *>(arena_->Alloc(sizeof(MIR), kArenaAllocMIR)); + MIR *insn = NewMIR(); insn->offset = current_offset_; insn->m_unit_index = current_method_; int width = ParseInsn(code_ptr, &insn->dalvikInsn); @@ -923,7 +924,7 @@ void MIRGraph::DumpCFG(const char* dir_prefix, bool all_blocks, const char *suff fclose(file); } -/* Insert an MIR instruction to the end of a basic block */ +/* Insert an MIR instruction to the end of a basic block. */ void BasicBlock::AppendMIR(MIR* mir) { if (first_mir_insn == nullptr) { DCHECK(last_mir_insn == nullptr); @@ -934,9 +935,11 @@ void BasicBlock::AppendMIR(MIR* mir) { mir->next = nullptr; last_mir_insn = mir; } + + mir->bb = id; } -/* Insert an MIR instruction to the head of a basic block */ +/* Insert an MIR instruction to the head of a basic block. */ void BasicBlock::PrependMIR(MIR* mir) { if (first_mir_insn == nullptr) { DCHECK(last_mir_insn == nullptr); @@ -946,17 +949,53 @@ void BasicBlock::PrependMIR(MIR* mir) { mir->next = first_mir_insn; first_mir_insn = mir; } + + mir->bb = id; } -/* Insert a MIR instruction after the specified MIR */ +/* Insert a MIR instruction after the specified MIR. */ void BasicBlock::InsertMIRAfter(MIR* current_mir, MIR* new_mir) { new_mir->next = current_mir->next; current_mir->next = new_mir; if (last_mir_insn == current_mir) { - /* Is the last MIR in the block */ + /* Is the last MIR in the block? */ last_mir_insn = new_mir; } + + new_mir->bb = id; +} + +MIR* BasicBlock::FindPreviousMIR(MIR* mir) { + MIR* current = first_mir_insn; + + while (current != nullptr) { + MIR* next = current->next; + + if (next == mir) { + return current; + } + + current = next; + } + + return nullptr; +} + +void BasicBlock::InsertMIRBefore(MIR* current_mir, MIR* new_mir) { + if (first_mir_insn == current_mir) { + /* Is the first MIR in the block? */ + first_mir_insn = new_mir; + new_mir->bb = id; + } + + MIR* prev = FindPreviousMIR(current_mir); + + if (prev != nullptr) { + prev->next = new_mir; + new_mir->next = current_mir; + new_mir->bb = id; + } } MIR* BasicBlock::GetNextUnconditionalMir(MIRGraph* mir_graph, MIR* current) { @@ -1239,6 +1278,12 @@ CallInfo* MIRGraph::NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, return info; } +// Allocate a new MIR. +MIR* MIRGraph::NewMIR() { + MIR* mir = new (arena_) MIR(); + return mir; +} + // Allocate a new basic block. BasicBlock* MIRGraph::NewMemBB(BBType block_type, int block_id) { BasicBlock* bb = static_cast<BasicBlock*>(arena_->Alloc(sizeof(BasicBlock), @@ -1343,4 +1388,106 @@ BasicBlock* ChildBlockIterator::Next() { return nullptr; } +bool BasicBlock::RemoveMIR(MIR* mir) { + if (mir == nullptr) { + return false; + } + + // Find the MIR, and the one before it if they exist. + MIR* current = nullptr; + MIR* prev = nullptr; + + // Find the mir we are looking for. + for (current = first_mir_insn; current != nullptr; prev = current, current = current->next) { + if (current == mir) { + break; + } + } + + // Did we find it? + if (current != nullptr) { + MIR* next = current->next; + + // Just update the links of prev and next and current is almost gone. + if (prev != nullptr) { + prev->next = next; + } + + // Exceptions are if first or last mirs are invoke. + if (first_mir_insn == current) { + first_mir_insn = next; + } + + if (last_mir_insn == current) { + last_mir_insn = prev; + } + + // Found it and removed it. + return true; + } + + // We did not find it. + return false; +} + +MIR* MIR::Copy(MIRGraph* mir_graph) { + MIR* res = mir_graph->NewMIR(); + *res = *this; + + // Remove links + res->next = nullptr; + res->bb = NullBasicBlockId; + res->ssa_rep = nullptr; + + return res; +} + +MIR* MIR::Copy(CompilationUnit* c_unit) { + return Copy(c_unit->mir_graph.get()); +} + +uint32_t SSARepresentation::GetStartUseIndex(Instruction::Code opcode) { + // Default result. + int res = 0; + + // We are basically setting the iputs to their igets counterparts. + switch (opcode) { + case Instruction::IPUT: + case Instruction::IPUT_OBJECT: + case Instruction::IPUT_BOOLEAN: + case Instruction::IPUT_BYTE: + case Instruction::IPUT_CHAR: + case Instruction::IPUT_SHORT: + case Instruction::IPUT_QUICK: + case Instruction::IPUT_OBJECT_QUICK: + case Instruction::APUT: + case Instruction::APUT_OBJECT: + case Instruction::APUT_BOOLEAN: + case Instruction::APUT_BYTE: + case Instruction::APUT_CHAR: + case Instruction::APUT_SHORT: + case Instruction::SPUT: + case Instruction::SPUT_OBJECT: + case Instruction::SPUT_BOOLEAN: + case Instruction::SPUT_BYTE: + case Instruction::SPUT_CHAR: + case Instruction::SPUT_SHORT: + // Skip the VR containing what to store. + res = 1; + break; + case Instruction::IPUT_WIDE: + case Instruction::IPUT_WIDE_QUICK: + case Instruction::APUT_WIDE: + case Instruction::SPUT_WIDE: + // Skip the two VRs containing what to store. + res = 2; + break; + default: + // Do nothing in the general case. + break; + } + + return res; +} + } // namespace art diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index ded1c99..0bb8265 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -242,6 +242,8 @@ struct SSARepresentation { bool* fp_use; int32_t* defs; bool* fp_def; + + static uint32_t GetStartUseIndex(Instruction::Code opcode); }; /* @@ -261,13 +263,15 @@ struct MIR { uint32_t vC; uint32_t arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */ Instruction::Code opcode; + + explicit DecodedInstruction():vA(0), vB(0), vB_wide(0), vC(0), opcode(Instruction::NOP) { + } } dalvikInsn; - // TODO: Add id of parent basic block. - // BasicBlockId parent_bb; // ID of parent basic block. NarrowDexOffset offset; // Offset of the instruction in code units. uint16_t optimization_flags; int16_t m_unit_index; // From which method was this MIR included + BasicBlockId bb; MIR* next; SSARepresentation* ssa_rep; union { @@ -286,6 +290,23 @@ struct MIR { // INVOKE data index, points to MIRGraph::method_lowering_infos_. uint32_t method_lowering_info; } meta; + + explicit MIR():offset(0), optimization_flags(0), m_unit_index(0), bb(NullBasicBlockId), + next(nullptr), ssa_rep(nullptr) { + memset(&meta, 0, sizeof(meta)); + } + + uint32_t GetStartUseIndex() const { + return SSARepresentation::GetStartUseIndex(dalvikInsn.opcode); + } + + MIR* Copy(CompilationUnit *c_unit); + MIR* Copy(MIRGraph* mir_Graph); + + static void* operator new(size_t size, ArenaAllocator* arena) { + return arena->Alloc(sizeof(MIR), kArenaAllocMIR); + } + static void operator delete(void* p) {} // Nop. }; struct SuccessorBlockInfo; @@ -320,6 +341,8 @@ struct BasicBlock { void AppendMIR(MIR* mir); void PrependMIR(MIR* mir); void InsertMIRAfter(MIR* current_mir, MIR* new_mir); + void InsertMIRBefore(MIR* current_mir, MIR* new_mir); + MIR* FindPreviousMIR(MIR* mir); /** * @brief Used to obtain the next MIR that follows unconditionally. @@ -330,6 +353,7 @@ struct BasicBlock { * @return Returns the following MIR if one can be found. */ MIR* GetNextUnconditionalMir(MIRGraph* mir_graph, MIR* current); + bool RemoveMIR(MIR* mir); }; /* @@ -837,6 +861,7 @@ class MIRGraph { void DumpMIRGraph(); CallInfo* NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, bool is_range); BasicBlock* NewMemBB(BBType block_type, int block_id); + MIR* NewMIR(); MIR* AdvanceMIR(BasicBlock** p_bb, MIR* mir); BasicBlock* NextDominatedBlock(BasicBlock* bb); bool LayoutBlocks(BasicBlock* bb); diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc index 9f98e55..526c981 100644 --- a/compiler/dex/quick/dex_file_method_inliner.cc +++ b/compiler/dex/quick/dex_file_method_inliner.cc @@ -35,8 +35,7 @@ namespace art { namespace { // anonymous namespace MIR* AllocReplacementMIR(MIRGraph* mir_graph, MIR* invoke, MIR* move_return) { - ArenaAllocator* arena = mir_graph->GetArena(); - MIR* insn = static_cast<MIR*>(arena->Alloc(sizeof(MIR), kArenaAllocMIR)); + MIR* insn = mir_graph->NewMIR(); insn->offset = invoke->offset; insn->optimization_flags = MIR_CALLEE; return insn; diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc index 5aa093a..865311b 100644 --- a/compiler/dex/ssa_transformation.cc +++ b/compiler/dex/ssa_transformation.cc @@ -557,8 +557,7 @@ void MIRGraph::InsertPhiNodes() { if (!phi_bb->data_flow_info->live_in_v->IsBitSet(dalvik_reg)) { continue; } - MIR *phi = - static_cast<MIR*>(arena_->Alloc(sizeof(MIR), kArenaAllocDFInfo)); + MIR *phi = NewMIR(); phi->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpPhi); phi->dalvikInsn.vA = dalvik_reg; phi->offset = phi_bb->start_offset; |