Chromium Code Reviews| Index: runtime/vm/kernel_to_il.cc |
| diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc |
| index 942a70f5e26ad0f46503d782cda6fcf3f37cdfd8..0b27355e6682c4cecce65cbf15b57540084fce94 100644 |
| --- a/runtime/vm/kernel_to_il.cc |
| +++ b/runtime/vm/kernel_to_il.cc |
| @@ -720,6 +720,13 @@ void ScopeBuilder::VisitFunctionNode(FunctionNode* node) { |
| scope_->CaptureVariable(temp); |
| } |
| } |
| + if (FLAG_causal_async_stacks) { |
| + LocalVariable* temp = |
| + scope_->LookupVariable(Symbols::AsyncStackTraceVar(), true); |
| + if (temp != NULL) { |
| + scope_->CaptureVariable(temp); |
| + } |
| + } |
| } |
| } |
| @@ -2556,6 +2563,17 @@ Fragment FlowGraphBuilder::Return(TokenPosition position) { |
| new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall); |
| } |
| + if (FLAG_causal_async_stacks && |
| + (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { |
| + // We are returning from an asynchronous closure. Before we do that, be |
| + // sure to clear the thread's asynchronous stack trace. |
| + const Function& target = Function::ZoneHandle( |
| + Z, I->object_store()->async_clear_thread_stack_trace()); |
| + ASSERT(!target.IsNull()); |
| + instructions += StaticCall(TokenPosition::kNoSource, target, 0); |
| + instructions += Drop(); |
| + } |
| + |
| ReturnInstr* return_instr = new (Z) ReturnInstr(position, value); |
| if (exit_collector_ != NULL) exit_collector_->AddExit(return_instr); |
| @@ -3172,7 +3190,7 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function, |
| // The code we are building will be executed right after we enter |
| // the function and before any nested contexts are allocated. |
| // Reset current context_depth_ to match this. |
| - intptr_t current_context_depth = context_depth_; |
| + const intptr_t current_context_depth = context_depth_; |
| context_depth_ = scopes_->yield_jump_variable->owner()->context_level(); |
| // Prepend an entry corresponding to normal entry to the function. |
| @@ -3238,6 +3256,37 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function, |
| context_depth_ = current_context_depth; |
| } |
| + if (FLAG_causal_async_stacks && |
| + (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) { |
| + // The code we are building will be executed right after we enter |
| + // the function and before any nested contexts are allocated. |
| + // Reset current context_depth_ to match this. |
| + const intptr_t current_context_depth = context_depth_; |
| + context_depth_ = scopes_->yield_jump_variable->owner()->context_level(); |
| + |
| + Fragment instructions; |
| + LocalScope* scope = parsed_function_->node_sequence()->scope(); |
| + |
| + const Function& target = Function::ZoneHandle( |
| + Z, I->object_store()->async_set_thread_stack_trace()); |
| + ASSERT(!target.IsNull()); |
| + |
| + // Fetch and load :async_stack_trace |
| + LocalVariable* async_stack_trace_var = |
| + scope->LookupVariable(Symbols::AsyncStackTraceVar(), false); |
| + ASSERT((async_stack_trace_var != NULL) && |
| + async_stack_trace_var->is_captured()); |
| + instructions += LoadLocal(async_stack_trace_var); |
| + instructions += PushArgument(); |
| + |
| + // Call _asyncSetThreadStackTrace |
| + instructions += StaticCall(TokenPosition::kNoSource, target, 1); |
| + instructions += Drop(); |
| + |
| + body = instructions + body; |
| + context_depth_ = current_context_depth; |
| + } |
| + |
| if (FLAG_support_debugger && function->position().IsDebugPause() && |
| !dart_function.is_native() && dart_function.is_debuggable()) { |
| // If a switch was added above: Start the switch by injecting a debugable |
| @@ -6103,6 +6152,7 @@ Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node, |
| // The VM has a per-isolate table of functions indexed by the enclosing |
| // function and token position. |
| Function& function = Function::ZoneHandle(Z); |
| + LocalScope* scope = NULL; |
| for (intptr_t i = 0; i < scopes_->function_scopes.length(); ++i) { |
| if (scopes_->function_scopes[i].function != node) continue; |
| @@ -6119,6 +6169,7 @@ Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node, |
| // NOTE: This is not TokenPosition in the general sense! |
| function = I->LookupClosureFunction(parsed_function_->function(), position); |
| + scope = scopes_->function_scopes[i].scope; |
| if (function.IsNull()) { |
| const dart::String* name; |
| if (parent->IsFunctionExpression()) { |
| @@ -6152,7 +6203,6 @@ Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node, |
| FunctionNode::kSyncYielding); |
| function.set_end_token_pos(node->end_position()); |
| - LocalScope* scope = scopes_->function_scopes[i].scope; |
| const ContextScope& context_scope = |
| ContextScope::Handle(Z, scope->PreserveOuterScope(context_depth_)); |
| function.set_context_scope(context_scope); |
| @@ -6172,10 +6222,29 @@ Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node, |
| break; |
| } |
| + Fragment instructions; |
| + |
| + if (FLAG_causal_async_stacks && |
|
kustermann
2017/02/23 10:30:37
You can move this code to FlowGraphBuilder::BuildG
|
| + (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { |
| + // :async_stack_trace = _asyncStackTraceHelper(); |
| + const dart::Library& async_lib = |
| + dart::Library::Handle(dart::Library::AsyncLibrary()); |
| + const Function& target = Function::ZoneHandle( |
| + Z, |
| + async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper())); |
| + ASSERT(!target.IsNull()); |
| + instructions += StaticCall(TokenPosition::kNoSource, target, 0); |
| + LocalVariable* async_stack_trace_var = |
| + scope->LookupVariable(Symbols::AsyncStackTraceVar(), false); |
| + ASSERT(async_stack_trace_var != NULL); |
| + instructions += StoreLocal(TokenPosition::kNoSource, async_stack_trace_var); |
| + instructions += Drop(); |
| + } |
| + |
| const dart::Class& closure_class = |
| dart::Class::ZoneHandle(Z, I->object_store()->closure_class()); |
| ASSERT(!closure_class.IsNull()); |
| - Fragment instructions = AllocateObject(closure_class, function); |
| + instructions += AllocateObject(closure_class, function); |
| LocalVariable* closure = MakeTemporary(); |
| // TODO(27590): Generic closures need type arguments. |