| Index: runtime/vm/intermediate_language_dbc.cc
|
| diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
|
| index 2f64861a0de662bc3ecac805d2d8519eb5f5f935..9904d01b5f35557ae6820aab3b10b5ef7da4b2f7 100644
|
| --- a/runtime/vm/intermediate_language_dbc.cc
|
| +++ b/runtime/vm/intermediate_language_dbc.cc
|
| @@ -1185,24 +1185,67 @@ EMIT_NATIVE_CODE(CatchBlockEntry, 0) {
|
| if (HasParallelMove()) {
|
| compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
|
| }
|
| - if (compiler->is_optimizing()) {
|
| - // In optimized code, variables at the catch block entry reside at the top
|
| - // of the allocatable register range.
|
| - const intptr_t num_non_copied_params =
|
| - compiler->flow_graph().num_non_copied_params();
|
| - const intptr_t exception_reg =
|
| - kNumberOfCpuRegisters -
|
| - (-exception_var().index() + num_non_copied_params);
|
| - const intptr_t stacktrace_reg =
|
| - kNumberOfCpuRegisters -
|
| - (-stacktrace_var().index() + num_non_copied_params);
|
| - __ MoveSpecial(exception_reg, Simulator::kExceptionSpecialIndex);
|
| - __ MoveSpecial(stacktrace_reg, Simulator::kStackTraceSpecialIndex);
|
| +
|
| + Register context_reg = kNoRegister;
|
| +
|
| + // Auxiliary variables introduced by the try catch can be captured if we are
|
| + // inside a function with yield/resume points. In this case we first need
|
| + // to restore the context to match the context at entry into the closure.
|
| + if (should_restore_closure_context()) {
|
| + const ParsedFunction& parsed_function = compiler->parsed_function();
|
| +
|
| + ASSERT(parsed_function.function().IsClosureFunction());
|
| + LocalScope* scope = parsed_function.node_sequence()->scope();
|
| +
|
| + LocalVariable* closure_parameter = scope->VariableAt(0);
|
| + ASSERT(!closure_parameter->is_captured());
|
| +
|
| + const LocalVariable& current_context_var =
|
| + *parsed_function.current_context_var();
|
| +
|
| + context_reg = compiler->is_optimizing()
|
| + ? compiler->CatchEntryRegForVariable(current_context_var)
|
| + : LocalVarIndex(0, current_context_var.index());
|
| +
|
| + Register closure_reg;
|
| + if (closure_parameter->index() > 0) {
|
| + __ Move(context_reg, LocalVarIndex(0, closure_parameter->index()));
|
| + closure_reg = context_reg;
|
| + } else {
|
| + closure_reg = LocalVarIndex(0, closure_parameter->index());
|
| + }
|
| +
|
| + __ LoadField(context_reg, closure_reg,
|
| + Closure::context_offset() / kWordSize);
|
| + }
|
| +
|
| + if (exception_var().is_captured()) {
|
| + ASSERT(stacktrace_var().is_captured());
|
| + ASSERT(context_reg != kNoRegister);
|
| + // This will be SP[1] register so we are free to use it as a temporary.
|
| + const Register temp = compiler->StackSize();
|
| + __ MoveSpecial(temp, Simulator::kExceptionSpecialIndex);
|
| + __ StoreField(context_reg,
|
| + Context::variable_offset(exception_var().index()) / kWordSize,
|
| + temp);
|
| + __ MoveSpecial(temp, Simulator::kStackTraceSpecialIndex);
|
| + __ StoreField(
|
| + context_reg,
|
| + Context::variable_offset(stacktrace_var().index()) / kWordSize, temp);
|
| } else {
|
| - __ MoveSpecial(LocalVarIndex(0, exception_var().index()),
|
| - Simulator::kExceptionSpecialIndex);
|
| - __ MoveSpecial(LocalVarIndex(0, stacktrace_var().index()),
|
| - Simulator::kStackTraceSpecialIndex);
|
| + if (compiler->is_optimizing()) {
|
| + const intptr_t exception_reg =
|
| + compiler->CatchEntryRegForVariable(exception_var());
|
| + const intptr_t stacktrace_reg =
|
| + compiler->CatchEntryRegForVariable(stacktrace_var());
|
| + __ MoveSpecial(exception_reg, Simulator::kExceptionSpecialIndex);
|
| + __ MoveSpecial(stacktrace_reg, Simulator::kStackTraceSpecialIndex);
|
| + } else {
|
| + __ MoveSpecial(LocalVarIndex(0, exception_var().index()),
|
| + Simulator::kExceptionSpecialIndex);
|
| + __ MoveSpecial(LocalVarIndex(0, stacktrace_var().index()),
|
| + Simulator::kStackTraceSpecialIndex);
|
| + }
|
| }
|
| __ SetFrame(compiler->StackSize());
|
| }
|
|
|