Index: runtime/vm/intermediate_language_ia32.cc |
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc |
index c575924bf5062b5d4b886c05dc0da93d53698246..aad76e4998899989997ffa7b8ddb4f0fd0638fe8 100644 |
--- a/runtime/vm/intermediate_language_ia32.cc |
+++ b/runtime/vm/intermediate_language_ia32.cc |
@@ -2537,12 +2537,52 @@ void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
ASSERT(fp_sp_dist <= 0); |
__ leal(ESP, Address(EBP, fp_sp_dist)); |
- // Restore stack and initialize the two exception variables: |
- // exception and stack trace variables. |
- __ movl(Address(EBP, exception_var().index() * kWordSize), |
- kExceptionObjectReg); |
- __ movl(Address(EBP, stacktrace_var().index() * kWordSize), |
- kStackTraceObjectReg); |
+ // 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()); |
+ __ movl(CTX, Address(EBP, closure_parameter->index() * kWordSize)); |
+ __ movl(CTX, FieldAddress(CTX, Closure::context_offset())); |
+ |
+#ifdef DEBUG |
+ Label ok; |
+ __ LoadClassId(EBX, CTX); |
+ __ cmpl(EBX, Immediate(kContextCid)); |
+ __ j(EQUAL, &ok, Assembler::kNearJump); |
+ __ Stop("Incorrect context at entry"); |
+ __ Bind(&ok); |
+#endif |
+ |
+ const intptr_t context_index = |
+ parsed_function.current_context_var()->index(); |
+ __ movl(Address(EBP, context_index * kWordSize), CTX); |
+ } |
+ |
+ // Initialize exception and stack trace variables. |
+ if (exception_var().is_captured()) { |
+ ASSERT(stacktrace_var().is_captured()); |
+ __ StoreIntoObject( |
+ CTX, |
+ FieldAddress(CTX, Context::variable_offset(exception_var().index())), |
+ kExceptionObjectReg); |
+ __ StoreIntoObject( |
+ CTX, |
+ FieldAddress(CTX, Context::variable_offset(stacktrace_var().index())), |
+ kStackTraceObjectReg); |
+ } else { |
+ // Restore stack and initialize the two exception variables: |
+ // exception and stack trace variables. |
+ __ movl(Address(EBP, exception_var().index() * kWordSize), |
+ kExceptionObjectReg); |
+ __ movl(Address(EBP, stacktrace_var().index() * kWordSize), |
+ kStackTraceObjectReg); |
+ } |
} |