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

Unified Diff: runtime/vm/parser.cc

Issue 2646443005: Track async causal stack traces (Closed)
Patch Set: rebase Created 3 years, 10 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/object_store.cc ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 51bca8edb4ca6ceafe29d1e8a11f00b97bdd2c92..167ea1ea98c23ff637ae53577500ee1c9c714eac 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -3571,10 +3571,16 @@ SequenceNode* Parser::ParseFunc(const Function& func, bool check_semicolon) {
ASSERT(!func.is_generated_body());
// The code of an async function is synthesized. Disable debugging.
func.set_is_debuggable(false);
+ // In order to collect causal asynchronous stacks efficiently we rely on
+ // this function not being inlined.
+ func.set_is_inlinable(!FLAG_causal_async_stacks);
generated_body_closure = OpenAsyncFunction(func.token_pos());
} else if (func.IsAsyncClosure()) {
// The closure containing the body of an async function is debuggable.
ASSERT(func.is_debuggable());
+ // In order to collect causal asynchronous stacks efficiently we rely on
+ // this function not being inlined.
+ func.set_is_inlinable(!FLAG_causal_async_stacks);
OpenAsyncClosure();
} else if (func.IsSyncGenerator()) {
// The code of a sync generator is synthesized. Disable debugging.
@@ -3586,10 +3592,16 @@ SequenceNode* Parser::ParseFunc(const Function& func, bool check_semicolon) {
async_temp_scope_ = current_block_->scope;
} else if (func.IsAsyncGenerator()) {
func.set_is_debuggable(false);
+ // In order to collect causal asynchronous stacks efficiently we rely on
+ // this function not being inlined.
+ func.set_is_inlinable(!FLAG_causal_async_stacks);
generated_body_closure = OpenAsyncGeneratorFunction(func.token_pos());
} else if (func.IsAsyncGenClosure()) {
// The closure containing the body of an async* function is debuggable.
ASSERT(func.is_debuggable());
+ // In order to collect causal asynchronous stacks efficiently we rely on
+ // this function not being inlined.
+ func.set_is_inlinable(!FLAG_causal_async_stacks);
OpenAsyncGeneratorClosure();
}
@@ -7037,6 +7049,7 @@ void Parser::AddAsyncClosureVariables() {
// var :async_then_callback;
// var :async_catch_error_callback;
// var :async_completer;
+ // var :async_stack_trace;
LocalVariable* async_op_var =
new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::AsyncOperation(), Object::dynamic_type());
@@ -7053,6 +7066,10 @@ void Parser::AddAsyncClosureVariables() {
new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::AsyncCompleter(), Object::dynamic_type());
current_block_->scope->AddVariable(async_completer);
+ LocalVariable* async_stack_trace = new (Z)
+ LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::AsyncStackTraceVar(), Object::dynamic_type());
+ current_block_->scope->AddVariable(async_stack_trace);
}
@@ -7065,6 +7082,7 @@ void Parser::AddAsyncGeneratorVariables() {
// var :async_op;
// var :async_then_callback;
// var :async_catch_error_callback;
+ // var :async_stack_trace;
// These variables are used to store the async generator closure containing
// the body of the async* function. They are used by the await operator.
LocalVariable* controller_var =
@@ -7083,6 +7101,10 @@ void Parser::AddAsyncGeneratorVariables() {
LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::AsyncCatchErrorCallback(), Object::dynamic_type());
current_block_->scope->AddVariable(async_catch_error_callback_var);
+ LocalVariable* async_stack_trace = new (Z)
+ LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
+ Symbols::AsyncStackTraceVar(), Object::dynamic_type());
+ current_block_->scope->AddVariable(async_stack_trace);
}
@@ -7180,6 +7202,9 @@ SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure_func,
existing_var = closure_body->scope()->LookupVariable(
Symbols::AsyncCatchErrorCallback(), false);
ASSERT((existing_var != NULL) && existing_var->is_captured());
+ existing_var = closure_body->scope()->LookupVariable(
+ Symbols::AsyncStackTraceVar(), false);
+ ASSERT((existing_var != NULL) && existing_var->is_captured());
const Library& async_lib = Library::Handle(Library::AsyncLibrary());
@@ -7199,6 +7224,28 @@ SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure_func,
current_block_->statements->Add(
new (Z) StoreLocalNode(TokenPosition::kNoSource, jump_var, init_value));
+ TokenPosition token_pos = TokenPosition::kNoSource;
+
+ if (FLAG_causal_async_stacks) {
+ // Add to AST:
+ // :async_stack_trace = _asyncStackTraceHelper();
+ const Function& async_stack_trace_helper = Function::ZoneHandle(
+ Z,
+ async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper()));
+ ASSERT(!async_stack_trace_helper.IsNull());
+ ArgumentListNode* async_stack_trace_helper_args =
+ new (Z) ArgumentListNode(TokenPosition::kNoSource);
+ StaticCallNode* async_stack_trace_helper_call = new (Z) StaticCallNode(
+ token_pos, async_stack_trace_helper, async_stack_trace_helper_args);
+ LocalVariable* async_stack_trace_var =
+ current_block_->scope->LookupVariable(Symbols::AsyncStackTraceVar(),
+ false);
+ StoreLocalNode* store_async_stack_trace = new (Z) StoreLocalNode(
+ token_pos, async_stack_trace_var, async_stack_trace_helper_call);
+ current_block_->statements->Add(store_async_stack_trace);
+ }
+
+
// Add to AST:
// :async_op = <closure>; (containing the original body)
LocalVariable* async_op_var =
@@ -7342,6 +7389,9 @@ SequenceNode* Parser::CloseAsyncFunction(const Function& closure,
existing_var =
closure_body->scope()->LookupVariable(Symbols::AsyncCompleter(), false);
ASSERT((existing_var != NULL) && existing_var->is_captured());
+ existing_var = closure_body->scope()->LookupVariable(
+ Symbols::AsyncStackTraceVar(), false);
+ ASSERT((existing_var != NULL) && existing_var->is_captured());
// Create and return a new future that executes a closure with the current
// body.
@@ -7394,6 +7444,26 @@ SequenceNode* Parser::CloseAsyncFunction(const Function& closure,
current_block_->statements->Add(store_async_op);
const Library& async_lib = Library::Handle(Library::AsyncLibrary());
+
+ if (FLAG_causal_async_stacks) {
+ // Add to AST:
+ // :async_stack_trace = _asyncStackTraceHelper();
+ const Function& async_stack_trace_helper = Function::ZoneHandle(
+ Z,
+ async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper()));
+ ASSERT(!async_stack_trace_helper.IsNull());
+ ArgumentListNode* async_stack_trace_helper_args =
+ new (Z) ArgumentListNode(token_pos);
+ StaticCallNode* async_stack_trace_helper_call = new (Z) StaticCallNode(
+ token_pos, async_stack_trace_helper, async_stack_trace_helper_args);
+ LocalVariable* async_stack_trace_var =
+ current_block_->scope->LookupVariable(Symbols::AsyncStackTraceVar(),
+ false);
+ StoreLocalNode* store_async_stack_trace = new (Z) StoreLocalNode(
+ token_pos, async_stack_trace_var, async_stack_trace_helper_call);
+ current_block_->statements->Add(store_async_stack_trace);
+ }
+
// :async_then_callback = _asyncThenWrapperHelper(:async_op)
const Function& async_then_wrapper_helper = Function::ZoneHandle(
Z,
« no previous file with comments | « runtime/vm/object_store.cc ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698