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: |