diff options
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r-- | compiler/optimizing/nodes.h | 108 |
1 files changed, 105 insertions, 3 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 0f5b1abbbf..f2e9e22057 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -39,6 +39,7 @@ class HCurrentMethod; class HDoubleConstant; class HEnvironment; class HFloatConstant; +class HGraphBuilder; class HGraphVisitor; class HInstruction; class HIntConstant; @@ -207,6 +208,12 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { // Removes `block` from the graph. void DeleteDeadBlock(HBasicBlock* block); + // Splits the edge between `block` and `successor` while preserving the + // indices in the predecessor/successor lists. If there are multiple edges + // between the blocks, the lowest indices are used. + // Returns the new block which is empty and has the same dex pc as `successor`. + HBasicBlock* SplitEdge(HBasicBlock* block, HBasicBlock* successor); + void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor); void SimplifyLoop(HBasicBlock* header); @@ -566,6 +573,15 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { } bool IsSingleGoto() const; + bool IsSingleTryBoundary() const; + + // Returns true if this block emits nothing but a jump. + bool IsSingleJump() const { + HLoopInformation* loop_info = GetLoopInformation(); + return (IsSingleGoto() || IsSingleTryBoundary()) + // Back edges generate a suspend check. + && (loop_info == nullptr || !loop_info->IsBackEdge(*this)); + } void AddBackEdge(HBasicBlock* back_edge) { if (loop_information_ == nullptr) { @@ -674,7 +690,7 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { successors_.Put(1, temp); } - size_t GetPredecessorIndexOf(HBasicBlock* predecessor) { + size_t GetPredecessorIndexOf(HBasicBlock* predecessor) const { for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) { if (predecessors_.Get(i) == predecessor) { return i; @@ -683,7 +699,7 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { return -1; } - size_t GetSuccessorIndexOf(HBasicBlock* successor) { + size_t GetSuccessorIndexOf(HBasicBlock* successor) const { for (size_t i = 0, e = successors_.Size(); i < e; ++i) { if (successors_.Get(i) == successor) { return i; @@ -692,6 +708,32 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { return -1; } + HBasicBlock* GetSinglePredecessor() const { + DCHECK_EQ(GetPredecessors().Size(), 1u); + return GetPredecessors().Get(0); + } + + HBasicBlock* GetSingleSuccessor() const { + DCHECK_EQ(GetSuccessors().Size(), 1u); + return GetSuccessors().Get(0); + } + + // Returns whether the first occurrence of `predecessor` in the list of + // predecessors is at index `idx`. + bool IsFirstIndexOfPredecessor(HBasicBlock* predecessor, size_t idx) const { + DCHECK_EQ(GetPredecessors().Get(idx), predecessor); + return GetPredecessorIndexOf(predecessor) == idx; + } + + // Returns whether successor at index `idx` is an exception handler. + bool IsExceptionalSuccessor(size_t idx) const; + + // Split the block into two blocks just before `cursor`. Returns the newly + // created, latter block. Note that this method will create a Goto at the end + // of the former block and will create an edge between them. It will not, + // however, update the graph, reverse post order or loop information. + HBasicBlock* SplitBefore(HInstruction* cursor); + // Split the block into two blocks just after `cursor`. Returns the newly // created block. Note that this method just updates raw block information, // like predecessors, successors, dominators, and instruction list. It does not @@ -913,6 +955,7 @@ class HLoopInformationOutwardIterator : public ValueObject { M(SuspendCheck, Instruction) \ M(Temporary, Instruction) \ M(Throw, Instruction) \ + M(TryBoundary, Instruction) \ M(TypeConversion, Instruction) \ M(UShr, BinaryOperation) \ M(Xor, BinaryOperation) \ @@ -1858,7 +1901,7 @@ class HGoto : public HTemplateInstruction<0> { bool IsControlFlow() const OVERRIDE { return true; } HBasicBlock* GetSuccessor() const { - return GetBlock()->GetSuccessors().Get(0); + return GetBlock()->GetSingleSuccessor(); } DECLARE_INSTRUCTION(Goto); @@ -1892,6 +1935,65 @@ class HIf : public HTemplateInstruction<1> { DISALLOW_COPY_AND_ASSIGN(HIf); }; + +// Abstract instruction which marks the beginning and/or end of a try block and +// links it to the respective exception handlers. Behaves the same as a Goto in +// non-exceptional control flow. +// Normal-flow successor is stored at index zero, exception handlers under +// higher indices in no particular order. +class HTryBoundary : public HTemplateInstruction<0> { + public: + HTryBoundary(bool is_entry, bool is_exit) + : HTemplateInstruction(SideEffects::None()), is_entry_(is_entry), is_exit_(is_exit) {} + + bool IsControlFlow() const OVERRIDE { return true; } + + // Returns the block's non-exceptional successor (index zero). + HBasicBlock* GetNormalFlowSuccessor() const { return GetBlock()->GetSuccessors().Get(0); } + + // Returns whether `handler` is among its exception handlers (non-zero index + // successors). + bool HasExceptionHandler(HBasicBlock* handler) const { + DCHECK(handler->IsCatchBlock()); + return GetBlock()->GetSuccessors().Contains(handler, /* start_from */ 1); + } + + // Returns whether successor at index `idx` is an exception handler. + bool IsExceptionalSuccessor(size_t idx) const { + DCHECK_LT(idx, GetBlock()->GetSuccessors().Size()); + bool is_handler = (idx != 0); + DCHECK(!is_handler || GetBlock()->GetSuccessors().Get(idx)->IsCatchBlock()); + return is_handler; + } + + // If not present already, adds `handler` to its block's list of exception + // handlers. + void AddExceptionHandler(HBasicBlock* handler) { + if (!HasExceptionHandler(handler)) { + GetBlock()->AddSuccessor(handler); + } + } + + bool IsTryEntry() const { return is_entry_; } + bool IsTryExit() const { return is_exit_; } + + DECLARE_INSTRUCTION(TryBoundary); + + private: + // Only for debugging purposes. + bool is_entry_; + bool is_exit_; + + // Only set by HGraphBuilder. + void SetIsTryEntry() { is_entry_ = true; } + void SetIsTryExit() { is_exit_ = true; } + + friend HGraphBuilder; + + DISALLOW_COPY_AND_ASSIGN(HTryBoundary); +}; + + // Deoptimize to interpreter, upon checking a condition. class HDeoptimize : public HTemplateInstruction<1> { public: |