Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index 923526885ecea9685b32b527aa03bcd12b6b9592..ecca6cf805e911ccc9d31e20095331b4cf2afab8 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -3468,10 +3468,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 produce sane asynchronous stacks we rely on this function |
rmacnak
2017/01/26 18:05:58
To collect them efficiently.
Cutch
2017/01/31 23:45:31
Done (here and elsewhere).
|
+ // not being inlined. |
+ func.set_is_inlinable(!FLAG_sane_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 produce sane asynchronous stacks we rely on this function |
+ // not being inlined. |
+ func.set_is_inlinable(!FLAG_sane_async_stacks); |
OpenAsyncClosure(); |
} else if (func.IsSyncGenerator()) { |
// The code of a sync generator is synthesized. Disable debugging. |
@@ -3483,10 +3489,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 produce sane asynchronous stacks we rely on this function |
+ // not being inlined. |
+ func.set_is_inlinable(!FLAG_sane_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 produce sane asynchronous stacks we rely on this function |
+ // not being inlined. |
+ func.set_is_inlinable(!FLAG_sane_async_stacks); |
OpenAsyncGeneratorClosure(); |
} |
@@ -6861,6 +6873,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()); |
@@ -6877,6 +6890,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); |
} |
@@ -6889,6 +6906,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 = |
@@ -6907,6 +6925,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); |
} |
@@ -7004,6 +7026,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()); |
@@ -7023,6 +7048,24 @@ 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; |
+ |
+ // Add to AST: |
rmacnak
2017/01/26 18:05:58
if (FLAG_sane_async_stacks)
|
+ // :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 = |
@@ -7166,6 +7209,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. |
@@ -7218,6 +7264,23 @@ SequenceNode* Parser::CloseAsyncFunction(const Function& closure, |
current_block_->statements->Add(store_async_op); |
const Library& async_lib = Library::Handle(Library::AsyncLibrary()); |
+ |
+ // Add to AST: |
rmacnak
2017/01/26 18:05:58
if (FLAG_sane_async_stacks)
Cutch
2017/01/31 23:45:31
Done.
|
+ // :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, |