summaryrefslogtreecommitdiff
path: root/compiler/optimizing/nodes.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/nodes.h')
-rw-r--r--compiler/optimizing/nodes.h108
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: