| 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);
|
| + }
|
| }
|
|
|
|
|
|
|