diff options
Diffstat (limited to 'compiler/optimizing/nodes.cc')
| -rw-r--r-- | compiler/optimizing/nodes.cc | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index efaf48cc9f..d7795f9dff 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -564,6 +564,13 @@ bool HBasicBlock::Dominates(HBasicBlock* other) const { return false; } +void HBasicBlock::AddExceptionalPredecessor(HInstruction* exceptional_predecessor) { + DCHECK(exceptional_predecessor->CanThrow()); + DCHECK(exceptional_predecessor->GetBlock()->IsInTry()); + DCHECK(exceptional_predecessor->GetBlock()->GetTryEntry()->HasExceptionHandler(*this)); + exceptional_predecessors_.Add(exceptional_predecessor); +} + static void UpdateInputsUsers(HInstruction* instruction) { for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) { instruction->InputAt(i)->AddUseAt(instruction, i); @@ -1221,10 +1228,12 @@ bool HTryBoundary::HasSameExceptionHandlersAs(const HTryBoundary& other) const { return false; } - // Exception handler lists cannot contain duplicates, which makes it - // sufficient to test inclusion only in one direction. - for (HExceptionHandlerIterator it(other); !it.Done(); it.Advance()) { - if (!HasExceptionHandler(*it.Current())) { + // Exception handlers need to be stored in the same order. + for (HExceptionHandlerIterator it1(*this), it2(other); + !it1.Done(); + it1.Advance(), it2.Advance()) { + DCHECK(!it2.Done()); + if (it1.Current() != it2.Current()) { return false; } } @@ -1481,7 +1490,7 @@ void HGraph::DeleteDeadBlock(HBasicBlock* block) { blocks_.Put(block->GetBlockId(), nullptr); } -void HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { +HInstruction* HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { DCHECK(HasExitBlock()) << "Unimplemented scenario"; // Update the environments in this graph to have the invoke's environment // as parent. @@ -1506,6 +1515,7 @@ void HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { outer_graph->SetHasBoundsChecks(true); } + HInstruction* return_value = nullptr; if (GetBlocks().Size() == 3) { // Simple case of an entry block, a body block, and an exit block. // Put the body block's instruction into `invoke`'s block. @@ -1520,7 +1530,8 @@ void HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { // Replace the invoke with the return value of the inlined graph. if (last->IsReturn()) { - invoke->ReplaceWith(last->InputAt(0)); + return_value = last->InputAt(0); + invoke->ReplaceWith(return_value); } else { DCHECK(last->IsReturnVoid()); } @@ -1542,7 +1553,6 @@ void HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { // Update all predecessors of the exit block (now the `to` block) // to not `HReturn` but `HGoto` instead. - HInstruction* return_value = nullptr; bool returns_void = to->GetPredecessors().Get(0)->GetLastInstruction()->IsReturnVoid(); if (to->GetPredecessors().Size() == 1) { HBasicBlock* predecessor = to->GetPredecessors().Get(0); @@ -1676,6 +1686,8 @@ void HGraph::InlineInto(HGraph* outer_graph, HInvoke* invoke) { // Finally remove the invoke from the caller. invoke->GetBlock()->RemoveInstruction(invoke); + + return return_value; } /* |