Chromium Code Reviews| 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, |