Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 2603383004: Sane asynchronous debugging and stack traces (Closed)
Patch Set: rebase Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_builder.cc
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 265c3088f86794e090dc8e8031afc7559b43efc2..ffe1cd8c11d16cadfbc2068c2477fd25cec76886 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -323,7 +323,8 @@ FlowGraphBuilder::FlowGraphBuilder(
nesting_stack_(NULL),
osr_id_(osr_id),
jump_count_(0),
- await_joins_(new (Z) ZoneGrowableArray<JoinEntryInstr*>()) {}
+ await_joins_(new (Z) ZoneGrowableArray<JoinEntryInstr*>()),
+ await_token_positions_(new (Z) ZoneGrowableArray<TokenPosition>()) {}
void FlowGraphBuilder::AddCatchEntry(CatchBlockEntryInstr* entry) {
@@ -1146,6 +1147,30 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
}
}
+ if (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 Library& async_lib = Library::Handle(Library::AsyncLibrary());
+ ASSERT(!async_lib.IsNull());
+ const String& private_name = String::ZoneHandle(
+ async_lib.PrivateName(Symbols::ClearAsyncThreadStackTrace()));
+ ASSERT(!private_name.IsNull());
+ const Function& async_clear_thread_stack_trace = Function::ZoneHandle(
+ Z,
+ Resolver::ResolveStatic(async_lib, String::ZoneHandle(String::null()),
+ private_name, 0, Object::null_array()));
+ ASSERT(!async_clear_thread_stack_trace.IsNull());
+ // Mark that this function is not debuggable.
+ async_clear_thread_stack_trace.set_is_debuggable(false);
+ ZoneGrowableArray<PushArgumentInstr*>* no_arguments =
+ new (Z) ZoneGrowableArray<PushArgumentInstr*>(0);
+ StaticCallInstr* call_async_clear_thread_stack_trace = new (Z)
+ StaticCallInstr(node->token_pos().ToSynthetic(),
+ async_clear_thread_stack_trace, Object::null_array(),
+ no_arguments, owner()->ic_data_array());
+ Do(call_async_clear_thread_stack_trace);
+ }
+
// Async functions contain two types of return statements:
// 1) Returns that should complete the completer once all finally blocks have
// been inlined (call: :async_completer.complete(return_value)). These
@@ -1169,9 +1194,18 @@ void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) {
arguments->Add(PushArgument(rcv_value));
Value* returned_value = Bind(BuildLoadExprTemp(node->token_pos()));
arguments->Add(PushArgument(returned_value));
- InstanceCallInstr* call = new (Z) InstanceCallInstr(
- node->token_pos(), Symbols::CompleterComplete(), Token::kILLEGAL,
- arguments, Object::null_array(), 1, owner()->ic_data_array());
+
+ const Library& async_library = Library::Handle(Library::AsyncLibrary());
+ ASSERT(!async_library.IsNull());
+
+ const Function& complete_on_async_return_function =
+ Function::ZoneHandle(async_library.LookupFunctionAllowPrivate(
+ Symbols::CompleterCompleteOnAsyncReturn()));
+ ASSERT(!complete_on_async_return_function.IsNull());
+
+ StaticCallInstr* call = new (Z) StaticCallInstr(
+ node->token_pos().ToSynthetic(), complete_on_async_return_function,
+ Object::null_array(), arguments, owner()->ic_data_array());
Do(call);
// Rebind the return value for the actual return call to be null.
@@ -2181,6 +2215,8 @@ void EffectGraphVisitor::VisitAwaitMarkerNode(AwaitMarkerNode* node) {
Value* jump_val = Bind(new (Z) ConstantInstr(
Smi::ZoneHandle(Z, Smi::New(jump_count)), node->token_pos()));
Do(BuildStoreLocal(*jump_var, jump_val, node->token_pos()));
+ // Add a mapping from jump_count -> token_position.
+ owner()->AppendAwaitTokenPosition(node->token_pos());
// Save the current context for resuming.
BuildSaveContext(*ctx_var, node->token_pos());
}
@@ -3802,6 +3838,43 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
}
}
+ if (is_top_level_sequence &&
+ (function.IsAsyncClosure() || function.IsAsyncGenClosure())) {
+ LocalScope* top_scope = node->scope();
+ // Fetch the :async_stack_trace variable and store it into the thread.
+ LocalVariable* async_stack_trace_var =
+ top_scope->LookupVariable(Symbols::AsyncStackTraceVar(), false);
+ ASSERT((async_stack_trace_var != NULL) &&
+ async_stack_trace_var->is_captured());
+ // Load :async_stack_trace
+ Value* async_stack_trace_value = Bind(BuildLoadLocal(
+ *async_stack_trace_var, node->token_pos().ToSynthetic()));
+ // Setup arguments for _asyncSetThreadStackTrace.
+ ZoneGrowableArray<PushArgumentInstr*>* arguments =
+ new (Z) ZoneGrowableArray<PushArgumentInstr*>(1);
+ arguments->Add(PushArgument(async_stack_trace_value));
+
+ // Lookup _asyncSetThreadStackTrace
+ const Library& async_lib = Library::Handle(Library::AsyncLibrary());
+ ASSERT(!async_lib.IsNull());
+ const String& private_name = String::ZoneHandle(
+ async_lib.PrivateName(Symbols::SetAsyncThreadStackTrace()));
+ ASSERT(!private_name.IsNull());
+ const Function& async_set_thread_stack_trace = Function::ZoneHandle(
+ Z,
+ Resolver::ResolveStatic(async_lib, String::ZoneHandle(String::null()),
+ private_name, 1, Object::null_array()));
+ ASSERT(!async_set_thread_stack_trace.IsNull());
+ // Mark that this function is not debuggable.
+ async_set_thread_stack_trace.set_is_debuggable(false);
+ // Call _asyncSetThreadStackTrace
+ StaticCallInstr* call_async_set_thread_stack_trace = new (Z)
+ StaticCallInstr(node->token_pos().ToSynthetic(),
+ async_set_thread_stack_trace, Object::null_array(),
+ arguments, owner()->ic_data_array());
+ Do(call_async_set_thread_stack_trace);
+ }
+
if (FLAG_support_debugger && is_top_level_sequence &&
function.is_debuggable()) {
// Place a debug check at method entry to ensure breaking on a method always
@@ -3910,6 +3983,7 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
entry_ = NULL;
exit_ = NULL;
+ // Load the jump counter.
LoadLocalNode* load_jump_count =
new (Z) LoadLocalNode(node->token_pos(), jump_var);
ComparisonNode* check_jump_count;
@@ -4337,10 +4411,16 @@ FlowGraph* FlowGraphBuilder::BuildGraph() {
FlowGraph* graph =
new (Z) FlowGraph(parsed_function(), graph_entry_, last_used_block_id_);
+ graph->set_await_token_positions(await_token_positions_);
return graph;
}
+void FlowGraphBuilder::AppendAwaitTokenPosition(TokenPosition token_pos) {
+ await_token_positions_->Add(token_pos);
+}
+
+
void FlowGraphBuilder::PruneUnreachable() {
ASSERT(osr_id_ != Compiler::kNoOSRDeoptId);
BitVector* block_marks = new (Z) BitVector(Z, last_used_block_id_ + 1);
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698