Index: runtime/vm/kernel_to_il.cc |
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc |
index 61a4e71f0d36f8aaf7e08312746f2e73041ca437..46750fd49d521e920e53a031e1e019d9ab3a19a5 100644 |
--- a/runtime/vm/kernel_to_il.cc |
+++ b/runtime/vm/kernel_to_il.cc |
@@ -840,7 +840,8 @@ class TryFinallyBlock { |
// Finalizers are executed outside of the try block hence |
// try depth of finalizers are one less than current try |
// depth. |
- try_depth_(builder->try_depth_ - 1) { |
+ try_depth_(builder->try_depth_ - 1), |
+ try_index_(builder_->CurrentTryIndex()) { |
builder_->try_finally_block_ = this; |
} |
~TryFinallyBlock() { builder_->try_finally_block_ = outer_; } |
@@ -848,6 +849,7 @@ class TryFinallyBlock { |
Statement* finalizer() const { return finalizer_; } |
intptr_t context_depth() const { return context_depth_; } |
intptr_t try_depth() const { return try_depth_; } |
+ intptr_t try_index() const { return try_index_; } |
TryFinallyBlock* outer() const { return outer_; } |
private: |
@@ -856,6 +858,7 @@ class TryFinallyBlock { |
Statement* const finalizer_; |
const intptr_t context_depth_; |
const intptr_t try_depth_; |
+ const intptr_t try_index_; |
}; |
@@ -871,7 +874,8 @@ class TryCatchBlock { |
} |
~TryCatchBlock() { builder_->try_catch_block_ = outer_; } |
- intptr_t TryIndex() { return try_index_; } |
+ intptr_t try_index() { return try_index_; } |
+ TryCatchBlock* outer() const { return outer_; } |
private: |
FlowGraphBuilder* builder_; |
@@ -1853,6 +1857,7 @@ Fragment FlowGraphBuilder::TranslateFinallyFinalizers( |
TryFinallyBlock* outer_finally, |
intptr_t target_context_depth) { |
TryFinallyBlock* const saved_block = try_finally_block_; |
+ TryCatchBlock* const saved_try_catch_block = try_catch_block_; |
const intptr_t saved_depth = context_depth_; |
const intptr_t saved_try_depth = try_depth_; |
@@ -1868,6 +1873,20 @@ Fragment FlowGraphBuilder::TranslateFinallyFinalizers( |
// block. |
instructions += AdjustContextTo(try_finally_block_->context_depth()); |
+ // The to-be-translated finalizer has to have the correct try-index (namely |
+ // the one outside the try-finally block). |
+ bool changed_try_index = false; |
+ intptr_t target_try_index = try_finally_block_->try_index(); |
+ while (CurrentTryIndex() != target_try_index) { |
+ try_catch_block_ = try_catch_block_->outer(); |
+ changed_try_index = true; |
+ } |
+ if (changed_try_index) { |
+ JoinEntryInstr* entry = BuildJoinEntry(); |
+ instructions += Goto(entry); |
+ instructions = Fragment(instructions.entry, entry); |
+ } |
+ |
Statement* finalizer = try_finally_block_->finalizer(); |
try_finally_block_ = try_finally_block_->outer(); |
@@ -1881,13 +1900,14 @@ Fragment FlowGraphBuilder::TranslateFinallyFinalizers( |
} |
if (instructions.is_open() && target_context_depth != -1) { |
- // A target context depth of -1 indicates that we the code after this |
+ // A target context depth of -1 indicates that the code after this |
// will not care about the context chain so we can leave it any way we |
// want after the last finalizer. That is used when returning. |
instructions += AdjustContextTo(target_context_depth); |
} |
try_finally_block_ = saved_block; |
+ try_catch_block_ = saved_try_catch_block; |
context_depth_ = saved_depth; |
try_depth_ = saved_try_depth; |
@@ -2668,7 +2688,7 @@ intptr_t FlowGraphBuilder::CurrentTryIndex() { |
if (try_catch_block_ == NULL) { |
return CatchClauseNode::kInvalidTryIndex; |
} else { |
- return try_catch_block_->TryIndex(); |
+ return try_catch_block_->try_index(); |
} |
} |
@@ -5432,8 +5452,8 @@ void FlowGraphBuilder::VisitTryFinally(TryFinally* node) { |
// Fill in the body of the try. |
++try_depth_; |
{ |
- TryCatchBlock tcb(this, try_handler_index); |
TryFinallyBlock tfb(this, node->finalizer()); |
+ TryCatchBlock tcb(this, try_handler_index); |
try_body += TranslateStatement(node->body()); |
} |
--try_depth_; |