summaryrefslogtreecommitdiff
path: root/compiler/optimizing/ssa_builder.cc
diff options
context:
space:
mode:
author David Brazdil <dbrazdil@google.com> 2015-07-06 11:48:53 +0100
committer David Brazdil <dbrazdil@google.com> 2015-07-15 17:20:30 +0200
commitffee3d33f3ea39aa6031c3d2ff29c4806c8dcc51 (patch)
tree9b990552fbf7e0ba91954758b07e2a51d95da9cd /compiler/optimizing/ssa_builder.cc
parent045da88bd0230ddf48aaf037b3d6c16fbb97ba65 (diff)
ART: Build SSA form when try/catch is present
This patch implements support for try/catch in the SsaBuilder. Values of locals are propagated from throwing sites inside try blocks to their respective catch blocks and phis ("catch phis") are created when necessary. Change-Id: I0736565c2c4ff3f9f0924b6e3a785a50023f875a
Diffstat (limited to 'compiler/optimizing/ssa_builder.cc')
-rw-r--r--compiler/optimizing/ssa_builder.cc41
1 files changed, 28 insertions, 13 deletions
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index c37b1995fa..ff2e6ad821 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -350,7 +350,9 @@ HInstruction* SsaBuilder::ValueOfLocal(HBasicBlock* block, size_t local) {
void SsaBuilder::VisitBasicBlock(HBasicBlock* block) {
current_locals_ = GetLocalsFor(block);
- if (block->IsLoopHeader()) {
+ if (block->IsCatchBlock()) {
+ // Catch phis were already created and inputs collected from throwing sites.
+ } else if (block->IsLoopHeader()) {
// If the block is a loop header, we know we only have visited the pre header
// because we are visiting in reverse post order. We create phis for all initialized
// locals from the pre header. Their inputs will be populated at the end of
@@ -551,19 +553,32 @@ void SsaBuilder::VisitStoreLocal(HStoreLocal* store) {
}
void SsaBuilder::VisitInstruction(HInstruction* instruction) {
- if (!instruction->NeedsEnvironment()) {
- return;
+ if (instruction->NeedsEnvironment()) {
+ HEnvironment* environment = new (GetGraph()->GetArena()) HEnvironment(
+ GetGraph()->GetArena(),
+ current_locals_->Size(),
+ GetGraph()->GetDexFile(),
+ GetGraph()->GetMethodIdx(),
+ instruction->GetDexPc(),
+ GetGraph()->GetInvokeType(),
+ instruction);
+ environment->CopyFrom(*current_locals_);
+ instruction->SetRawEnvironment(environment);
+ }
+
+ // If in a try block, propagate values of locals into catch blocks.
+ if (instruction->GetBlock()->IsInTry() && instruction->CanThrow()) {
+ HTryBoundary* try_block = instruction->GetBlock()->GetTryEntry();
+ for (HExceptionHandlerIterator it(*try_block); !it.Done(); it.Advance()) {
+ GrowableArray<HInstruction*>* handler_locals = GetLocalsFor(it.Current());
+ for (size_t i = 0, e = current_locals_->Size(); i < e; ++i) {
+ HInstruction* local_value = current_locals_->Get(i);
+ if (local_value != nullptr) {
+ handler_locals->Get(i)->AsPhi()->AddInput(local_value);
+ }
+ }
+ }
}
- HEnvironment* environment = new (GetGraph()->GetArena()) HEnvironment(
- GetGraph()->GetArena(),
- current_locals_->Size(),
- GetGraph()->GetDexFile(),
- GetGraph()->GetMethodIdx(),
- instruction->GetDexPc(),
- GetGraph()->GetInvokeType(),
- instruction);
- environment->CopyFrom(*current_locals_);
- instruction->SetRawEnvironment(environment);
}
void SsaBuilder::VisitTemporary(HTemporary* temp) {