| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <map> | 5 #include <map> |
| 6 #include <set> | 6 #include <set> |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "vm/kernel_to_il.h" | 9 #include "vm/kernel_to_il.h" |
| 10 | 10 |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 --depth_.catch_; | 676 --depth_.catch_; |
| 677 } | 677 } |
| 678 | 678 |
| 679 | 679 |
| 680 void ScopeBuilder::VisitFunctionNode(FunctionNode* node) { | 680 void ScopeBuilder::VisitFunctionNode(FunctionNode* node) { |
| 681 List<TypeParameter>& type_parameters = node->type_parameters(); | 681 List<TypeParameter>& type_parameters = node->type_parameters(); |
| 682 for (intptr_t i = 0; i < type_parameters.length(); ++i) { | 682 for (intptr_t i = 0; i < type_parameters.length(); ++i) { |
| 683 VisitTypeParameter(type_parameters[i]); | 683 VisitTypeParameter(type_parameters[i]); |
| 684 } | 684 } |
| 685 | 685 |
| 686 if (FLAG_causal_async_stacks && |
| 687 (node->dart_async_marker() == FunctionNode::kAsync || |
| 688 node->dart_async_marker() == FunctionNode::kAsyncStar)) { |
| 689 LocalVariable* asyncStackTraceVar = MakeVariable( |
| 690 TokenPosition::kNoSource, TokenPosition::kNoSource, |
| 691 Symbols::AsyncStackTraceVar(), AbstractType::dynamic_type()); |
| 692 scope_->AddVariable(asyncStackTraceVar); |
| 693 } |
| 694 |
| 686 if (node->async_marker() == FunctionNode::kSyncYielding) { | 695 if (node->async_marker() == FunctionNode::kSyncYielding) { |
| 687 LocalScope* scope = parsed_function_->node_sequence()->scope(); | 696 LocalScope* scope = parsed_function_->node_sequence()->scope(); |
| 688 intptr_t offset = parsed_function_->function().num_fixed_parameters(); | 697 intptr_t offset = parsed_function_->function().num_fixed_parameters(); |
| 689 for (intptr_t i = 0; | 698 for (intptr_t i = 0; |
| 690 i < parsed_function_->function().NumOptionalPositionalParameters(); | 699 i < parsed_function_->function().NumOptionalPositionalParameters(); |
| 691 i++) { | 700 i++) { |
| 692 scope->VariableAt(offset + i)->set_is_forced_stack(); | 701 scope->VariableAt(offset + i)->set_is_forced_stack(); |
| 693 } | 702 } |
| 694 } | 703 } |
| 695 | 704 |
| 696 // Do not visit the positional and named parameters, because they've | 705 // Do not visit the positional and named parameters, because they've |
| 697 // already been added to the scope. | 706 // already been added to the scope. |
| 698 if (node->body() != NULL) { | 707 if (node->body() != NULL) { |
| 699 node->body()->AcceptStatementVisitor(this); | 708 node->body()->AcceptStatementVisitor(this); |
| 700 } | 709 } |
| 701 | 710 |
| 702 // Ensure that :await_jump_var, :await_ctx_var and :async_op are captured. | 711 // Ensure that :await_jump_var, :await_ctx_var, :async_op and |
| 712 // :async_stack_trace are captured. |
| 703 if (node->async_marker() == FunctionNode::kSyncYielding) { | 713 if (node->async_marker() == FunctionNode::kSyncYielding) { |
| 704 { | 714 { |
| 705 LocalVariable* temp = NULL; | 715 LocalVariable* temp = NULL; |
| 706 LookupCapturedVariableByName( | 716 LookupCapturedVariableByName( |
| 707 (depth_.function_ == 0) ? &result_->yield_jump_variable : &temp, | 717 (depth_.function_ == 0) ? &result_->yield_jump_variable : &temp, |
| 708 Symbols::AwaitJumpVar()); | 718 Symbols::AwaitJumpVar()); |
| 709 } | 719 } |
| 710 { | 720 { |
| 711 LocalVariable* temp = NULL; | 721 LocalVariable* temp = NULL; |
| 712 LookupCapturedVariableByName( | 722 LookupCapturedVariableByName( |
| 713 (depth_.function_ == 0) ? &result_->yield_context_variable : &temp, | 723 (depth_.function_ == 0) ? &result_->yield_context_variable : &temp, |
| 714 Symbols::AwaitContextVar()); | 724 Symbols::AwaitContextVar()); |
| 715 } | 725 } |
| 716 { | 726 { |
| 717 LocalVariable* temp = | 727 LocalVariable* temp = |
| 718 scope_->LookupVariable(Symbols::AsyncOperation(), true); | 728 scope_->LookupVariable(Symbols::AsyncOperation(), true); |
| 719 if (temp != NULL) { | 729 if (temp != NULL) { |
| 720 scope_->CaptureVariable(temp); | 730 scope_->CaptureVariable(temp); |
| 721 } | 731 } |
| 722 } | 732 } |
| 733 if (FLAG_causal_async_stacks) { |
| 734 LocalVariable* temp = |
| 735 scope_->LookupVariable(Symbols::AsyncStackTraceVar(), true); |
| 736 if (temp != NULL) { |
| 737 scope_->CaptureVariable(temp); |
| 738 } |
| 739 } |
| 723 } | 740 } |
| 724 } | 741 } |
| 725 | 742 |
| 726 | 743 |
| 727 void ScopeBuilder::VisitYieldStatement(YieldStatement* node) { | 744 void ScopeBuilder::VisitYieldStatement(YieldStatement* node) { |
| 728 ASSERT(node->is_native()); | 745 ASSERT(node->is_native()); |
| 729 if (depth_.function_ == 0) { | 746 if (depth_.function_ == 0) { |
| 730 AddSwitchVariable(); | 747 AddSwitchVariable(); |
| 731 // Promote all currently visible local variables into the context. | 748 // Promote all currently visible local variables into the context. |
| 732 // TODO(27590) CaptureLocalVariables promotes to many variables into | 749 // TODO(27590) CaptureLocalVariables promotes to many variables into |
| (...skipping 1816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2549 Value* value = Pop(); | 2566 Value* value = Pop(); |
| 2550 ASSERT(stack_ == NULL); | 2567 ASSERT(stack_ == NULL); |
| 2551 | 2568 |
| 2552 const Function& function = parsed_function_->function(); | 2569 const Function& function = parsed_function_->function(); |
| 2553 if (FLAG_support_debugger && position.IsDebugPause() && | 2570 if (FLAG_support_debugger && position.IsDebugPause() && |
| 2554 !function.is_native()) { | 2571 !function.is_native()) { |
| 2555 instructions <<= | 2572 instructions <<= |
| 2556 new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall); | 2573 new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall); |
| 2557 } | 2574 } |
| 2558 | 2575 |
| 2576 if (FLAG_causal_async_stacks && |
| 2577 (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { |
| 2578 // We are returning from an asynchronous closure. Before we do that, be |
| 2579 // sure to clear the thread's asynchronous stack trace. |
| 2580 const Function& target = Function::ZoneHandle( |
| 2581 Z, I->object_store()->async_clear_thread_stack_trace()); |
| 2582 ASSERT(!target.IsNull()); |
| 2583 instructions += StaticCall(TokenPosition::kNoSource, target, 0); |
| 2584 instructions += Drop(); |
| 2585 } |
| 2586 |
| 2559 ReturnInstr* return_instr = new (Z) ReturnInstr(position, value); | 2587 ReturnInstr* return_instr = new (Z) ReturnInstr(position, value); |
| 2560 if (exit_collector_ != NULL) exit_collector_->AddExit(return_instr); | 2588 if (exit_collector_ != NULL) exit_collector_->AddExit(return_instr); |
| 2561 | 2589 |
| 2562 instructions <<= return_instr; | 2590 instructions <<= return_instr; |
| 2563 | 2591 |
| 2564 return instructions.closed(); | 2592 return instructions.closed(); |
| 2565 } | 2593 } |
| 2566 | 2594 |
| 2567 | 2595 |
| 2568 Fragment FlowGraphBuilder::StaticCall(TokenPosition position, | 2596 Fragment FlowGraphBuilder::StaticCall(TokenPosition position, |
| (...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3149 body += Drop(); | 3177 body += Drop(); |
| 3150 } | 3178 } |
| 3151 for (intptr_t i = 0; i < named.length(); i++) { | 3179 for (intptr_t i = 0; i < named.length(); i++) { |
| 3152 VariableDeclaration* variable = named[i]; | 3180 VariableDeclaration* variable = named[i]; |
| 3153 body += LoadLocal(LookupVariable(variable)); | 3181 body += LoadLocal(LookupVariable(variable)); |
| 3154 body += CheckVariableTypeInCheckedMode(variable); | 3182 body += CheckVariableTypeInCheckedMode(variable); |
| 3155 body += Drop(); | 3183 body += Drop(); |
| 3156 } | 3184 } |
| 3157 } | 3185 } |
| 3158 | 3186 |
| 3187 if (FLAG_causal_async_stacks && |
| 3188 (dart_function.IsAsyncFunction() || dart_function.IsAsyncGenerator())) { |
| 3189 LocalScope* scope = parsed_function_->node_sequence()->scope(); |
| 3190 // :async_stack_trace = _asyncStackTraceHelper(); |
| 3191 const dart::Library& async_lib = |
| 3192 dart::Library::Handle(dart::Library::AsyncLibrary()); |
| 3193 const Function& target = Function::ZoneHandle( |
| 3194 Z, |
| 3195 async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper())); |
| 3196 ASSERT(!target.IsNull()); |
| 3197 |
| 3198 body += StaticCall(TokenPosition::kNoSource, target, 0); |
| 3199 LocalVariable* async_stack_trace_var = |
| 3200 scope->LookupVariable(Symbols::AsyncStackTraceVar(), false); |
| 3201 ASSERT(async_stack_trace_var != NULL); |
| 3202 body += StoreLocal(TokenPosition::kNoSource, async_stack_trace_var); |
| 3203 body += Drop(); |
| 3204 } |
| 3205 |
| 3159 if (dart_function.is_native()) { | 3206 if (dart_function.is_native()) { |
| 3160 body += NativeFunctionBody(function, dart_function); | 3207 body += NativeFunctionBody(function, dart_function); |
| 3161 } else if (function->body() != NULL) { | 3208 } else if (function->body() != NULL) { |
| 3162 body += TranslateStatement(function->body()); | 3209 body += TranslateStatement(function->body()); |
| 3163 } | 3210 } |
| 3164 if (body.is_open()) { | 3211 if (body.is_open()) { |
| 3165 body += NullConstant(); | 3212 body += NullConstant(); |
| 3166 body += Return(dart_function.end_token_pos()); | 3213 body += Return(dart_function.end_token_pos()); |
| 3167 } | 3214 } |
| 3168 | 3215 |
| 3169 // If functions body contains any yield points build switch statement that | 3216 // If functions body contains any yield points build switch statement that |
| 3170 // selects a continuation point based on the value of :await_jump_var. | 3217 // selects a continuation point based on the value of :await_jump_var. |
| 3171 if (!yield_continuations_.is_empty()) { | 3218 if (!yield_continuations_.is_empty()) { |
| 3172 // The code we are building will be executed right after we enter | 3219 // The code we are building will be executed right after we enter |
| 3173 // the function and before any nested contexts are allocated. | 3220 // the function and before any nested contexts are allocated. |
| 3174 // Reset current context_depth_ to match this. | 3221 // Reset current context_depth_ to match this. |
| 3175 intptr_t current_context_depth = context_depth_; | 3222 const intptr_t current_context_depth = context_depth_; |
| 3176 context_depth_ = scopes_->yield_jump_variable->owner()->context_level(); | 3223 context_depth_ = scopes_->yield_jump_variable->owner()->context_level(); |
| 3177 | 3224 |
| 3178 // Prepend an entry corresponding to normal entry to the function. | 3225 // Prepend an entry corresponding to normal entry to the function. |
| 3179 yield_continuations_.InsertAt( | 3226 yield_continuations_.InsertAt( |
| 3180 0, YieldContinuation(new (Z) DropTempsInstr(0, NULL), | 3227 0, YieldContinuation(new (Z) DropTempsInstr(0, NULL), |
| 3181 CatchClauseNode::kInvalidTryIndex)); | 3228 CatchClauseNode::kInvalidTryIndex)); |
| 3182 yield_continuations_[0].entry->LinkTo(body.entry); | 3229 yield_continuations_[0].entry->LinkTo(body.entry); |
| 3183 | 3230 |
| 3184 // Build a switch statement. | 3231 // Build a switch statement. |
| 3185 Fragment dispatch; | 3232 Fragment dispatch; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3231 | 3278 |
| 3232 // False branch will contain the next comparison. | 3279 // False branch will contain the next comparison. |
| 3233 dispatch = Fragment(dispatch.entry, otherwise); | 3280 dispatch = Fragment(dispatch.entry, otherwise); |
| 3234 block = otherwise; | 3281 block = otherwise; |
| 3235 } | 3282 } |
| 3236 body = dispatch; | 3283 body = dispatch; |
| 3237 | 3284 |
| 3238 context_depth_ = current_context_depth; | 3285 context_depth_ = current_context_depth; |
| 3239 } | 3286 } |
| 3240 | 3287 |
| 3288 if (FLAG_causal_async_stacks && |
| 3289 (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) { |
| 3290 // The code we are building will be executed right after we enter |
| 3291 // the function and before any nested contexts are allocated. |
| 3292 // Reset current context_depth_ to match this. |
| 3293 const intptr_t current_context_depth = context_depth_; |
| 3294 context_depth_ = scopes_->yield_jump_variable->owner()->context_level(); |
| 3295 |
| 3296 Fragment instructions; |
| 3297 LocalScope* scope = parsed_function_->node_sequence()->scope(); |
| 3298 |
| 3299 const Function& target = Function::ZoneHandle( |
| 3300 Z, I->object_store()->async_set_thread_stack_trace()); |
| 3301 ASSERT(!target.IsNull()); |
| 3302 |
| 3303 // Fetch and load :async_stack_trace |
| 3304 LocalVariable* async_stack_trace_var = |
| 3305 scope->LookupVariable(Symbols::AsyncStackTraceVar(), false); |
| 3306 ASSERT((async_stack_trace_var != NULL) && |
| 3307 async_stack_trace_var->is_captured()); |
| 3308 instructions += LoadLocal(async_stack_trace_var); |
| 3309 instructions += PushArgument(); |
| 3310 |
| 3311 // Call _asyncSetThreadStackTrace |
| 3312 instructions += StaticCall(TokenPosition::kNoSource, target, 1); |
| 3313 instructions += Drop(); |
| 3314 |
| 3315 body = instructions + body; |
| 3316 context_depth_ = current_context_depth; |
| 3317 } |
| 3318 |
| 3241 if (FLAG_support_debugger && function->position().IsDebugPause() && | 3319 if (FLAG_support_debugger && function->position().IsDebugPause() && |
| 3242 !dart_function.is_native() && dart_function.is_debuggable()) { | 3320 !dart_function.is_native() && dart_function.is_debuggable()) { |
| 3243 // If a switch was added above: Start the switch by injecting a debugable | 3321 // If a switch was added above: Start the switch by injecting a debugable |
| 3244 // safepoint so stepping over an await works. | 3322 // safepoint so stepping over an await works. |
| 3245 // If not, still start the body with a debugable safepoint to ensure | 3323 // If not, still start the body with a debugable safepoint to ensure |
| 3246 // breaking on a method always happens, even if there are no | 3324 // breaking on a method always happens, even if there are no |
| 3247 // assignments/calls/runtimecalls in the first basic block. | 3325 // assignments/calls/runtimecalls in the first basic block. |
| 3248 // Place this check at the last parameter to ensure parameters | 3326 // Place this check at the last parameter to ensure parameters |
| 3249 // are in scope in the debugger at method entry. | 3327 // are in scope in the debugger at method entry. |
| 3250 const int num_params = dart_function.NumParameters(); | 3328 const int num_params = dart_function.NumParameters(); |
| (...skipping 2882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6133 *name, parsed_function_->function(), position); | 6211 *name, parsed_function_->function(), position); |
| 6134 | 6212 |
| 6135 function.set_is_debuggable(node->dart_async_marker() == | 6213 function.set_is_debuggable(node->dart_async_marker() == |
| 6136 FunctionNode::kSync); | 6214 FunctionNode::kSync); |
| 6137 switch (node->dart_async_marker()) { | 6215 switch (node->dart_async_marker()) { |
| 6138 case FunctionNode::kSyncStar: | 6216 case FunctionNode::kSyncStar: |
| 6139 function.set_modifier(RawFunction::kSyncGen); | 6217 function.set_modifier(RawFunction::kSyncGen); |
| 6140 break; | 6218 break; |
| 6141 case FunctionNode::kAsync: | 6219 case FunctionNode::kAsync: |
| 6142 function.set_modifier(RawFunction::kAsync); | 6220 function.set_modifier(RawFunction::kAsync); |
| 6221 function.set_is_inlinable(!FLAG_causal_async_stacks); |
| 6143 break; | 6222 break; |
| 6144 case FunctionNode::kAsyncStar: | 6223 case FunctionNode::kAsyncStar: |
| 6145 function.set_modifier(RawFunction::kAsyncGen); | 6224 function.set_modifier(RawFunction::kAsyncGen); |
| 6225 function.set_is_inlinable(!FLAG_causal_async_stacks); |
| 6146 break; | 6226 break; |
| 6147 default: | 6227 default: |
| 6148 // no special modifier | 6228 // no special modifier |
| 6149 break; | 6229 break; |
| 6150 } | 6230 } |
| 6151 function.set_is_generated_body(node->async_marker() == | 6231 function.set_is_generated_body(node->async_marker() == |
| 6152 FunctionNode::kSyncYielding); | 6232 FunctionNode::kSyncYielding); |
| 6233 if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) { |
| 6234 function.set_is_inlinable(!FLAG_causal_async_stacks); |
| 6235 } |
| 6153 | 6236 |
| 6154 function.set_end_token_pos(node->end_position()); | 6237 function.set_end_token_pos(node->end_position()); |
| 6155 LocalScope* scope = scopes_->function_scopes[i].scope; | 6238 LocalScope* scope = scopes_->function_scopes[i].scope; |
| 6156 const ContextScope& context_scope = | 6239 const ContextScope& context_scope = |
| 6157 ContextScope::Handle(Z, scope->PreserveOuterScope(context_depth_)); | 6240 ContextScope::Handle(Z, scope->PreserveOuterScope(context_depth_)); |
| 6158 function.set_context_scope(context_scope); | 6241 function.set_context_scope(context_scope); |
| 6159 function.set_kernel_function(node); | 6242 function.set_kernel_function(node); |
| 6160 KernelReader::SetupFunctionParameters(H, T, dart::Class::Handle(Z), | 6243 KernelReader::SetupFunctionParameters(H, T, dart::Class::Handle(Z), |
| 6161 function, node, | 6244 function, node, |
| 6162 false, // is_method | 6245 false, // is_method |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6299 thread->clear_sticky_error(); | 6382 thread->clear_sticky_error(); |
| 6300 return error.raw(); | 6383 return error.raw(); |
| 6301 } | 6384 } |
| 6302 } | 6385 } |
| 6303 | 6386 |
| 6304 | 6387 |
| 6305 } // namespace kernel | 6388 } // namespace kernel |
| 6306 } // namespace dart | 6389 } // namespace dart |
| 6307 | 6390 |
| 6308 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 6391 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| OLD | NEW |