Chromium Code Reviews| 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 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 713 (depth_.function_ == 0) ? &result_->yield_context_variable : &temp, | 713 (depth_.function_ == 0) ? &result_->yield_context_variable : &temp, |
| 714 Symbols::AwaitContextVar()); | 714 Symbols::AwaitContextVar()); |
| 715 } | 715 } |
| 716 { | 716 { |
| 717 LocalVariable* temp = | 717 LocalVariable* temp = |
| 718 scope_->LookupVariable(Symbols::AsyncOperation(), true); | 718 scope_->LookupVariable(Symbols::AsyncOperation(), true); |
| 719 if (temp != NULL) { | 719 if (temp != NULL) { |
| 720 scope_->CaptureVariable(temp); | 720 scope_->CaptureVariable(temp); |
| 721 } | 721 } |
| 722 } | 722 } |
| 723 if (FLAG_causal_async_stacks) { | |
| 724 LocalVariable* temp = | |
| 725 scope_->LookupVariable(Symbols::AsyncStackTraceVar(), true); | |
| 726 if (temp != NULL) { | |
| 727 scope_->CaptureVariable(temp); | |
| 728 } | |
| 729 } | |
| 723 } | 730 } |
| 724 } | 731 } |
| 725 | 732 |
| 726 | 733 |
| 727 void ScopeBuilder::VisitYieldStatement(YieldStatement* node) { | 734 void ScopeBuilder::VisitYieldStatement(YieldStatement* node) { |
| 728 ASSERT(node->is_native()); | 735 ASSERT(node->is_native()); |
| 729 if (depth_.function_ == 0) { | 736 if (depth_.function_ == 0) { |
| 730 AddSwitchVariable(); | 737 AddSwitchVariable(); |
| 731 // Promote all currently visible local variables into the context. | 738 // Promote all currently visible local variables into the context. |
| 732 // TODO(27590) CaptureLocalVariables promotes to many variables into | 739 // 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(); | 2556 Value* value = Pop(); |
| 2550 ASSERT(stack_ == NULL); | 2557 ASSERT(stack_ == NULL); |
| 2551 | 2558 |
| 2552 const Function& function = parsed_function_->function(); | 2559 const Function& function = parsed_function_->function(); |
| 2553 if (FLAG_support_debugger && position.IsDebugPause() && | 2560 if (FLAG_support_debugger && position.IsDebugPause() && |
| 2554 !function.is_native()) { | 2561 !function.is_native()) { |
| 2555 instructions <<= | 2562 instructions <<= |
| 2556 new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall); | 2563 new (Z) DebugStepCheckInstr(position, RawPcDescriptors::kRuntimeCall); |
| 2557 } | 2564 } |
| 2558 | 2565 |
| 2566 if (FLAG_causal_async_stacks && | |
| 2567 (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { | |
| 2568 // We are returning from an asynchronous closure. Before we do that, be | |
| 2569 // sure to clear the thread's asynchronous stack trace. | |
| 2570 const Function& target = Function::ZoneHandle( | |
| 2571 Z, I->object_store()->async_clear_thread_stack_trace()); | |
| 2572 ASSERT(!target.IsNull()); | |
| 2573 instructions += StaticCall(TokenPosition::kNoSource, target, 0); | |
| 2574 instructions += Drop(); | |
| 2575 } | |
| 2576 | |
| 2559 ReturnInstr* return_instr = new (Z) ReturnInstr(position, value); | 2577 ReturnInstr* return_instr = new (Z) ReturnInstr(position, value); |
| 2560 if (exit_collector_ != NULL) exit_collector_->AddExit(return_instr); | 2578 if (exit_collector_ != NULL) exit_collector_->AddExit(return_instr); |
| 2561 | 2579 |
| 2562 instructions <<= return_instr; | 2580 instructions <<= return_instr; |
| 2563 | 2581 |
| 2564 return instructions.closed(); | 2582 return instructions.closed(); |
| 2565 } | 2583 } |
| 2566 | 2584 |
| 2567 | 2585 |
| 2568 Fragment FlowGraphBuilder::StaticCall(TokenPosition position, | 2586 Fragment FlowGraphBuilder::StaticCall(TokenPosition position, |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3165 body += NullConstant(); | 3183 body += NullConstant(); |
| 3166 body += Return(dart_function.end_token_pos()); | 3184 body += Return(dart_function.end_token_pos()); |
| 3167 } | 3185 } |
| 3168 | 3186 |
| 3169 // If functions body contains any yield points build switch statement that | 3187 // If functions body contains any yield points build switch statement that |
| 3170 // selects a continuation point based on the value of :await_jump_var. | 3188 // selects a continuation point based on the value of :await_jump_var. |
| 3171 if (!yield_continuations_.is_empty()) { | 3189 if (!yield_continuations_.is_empty()) { |
| 3172 // The code we are building will be executed right after we enter | 3190 // The code we are building will be executed right after we enter |
| 3173 // the function and before any nested contexts are allocated. | 3191 // the function and before any nested contexts are allocated. |
| 3174 // Reset current context_depth_ to match this. | 3192 // Reset current context_depth_ to match this. |
| 3175 intptr_t current_context_depth = context_depth_; | 3193 const intptr_t current_context_depth = context_depth_; |
| 3176 context_depth_ = scopes_->yield_jump_variable->owner()->context_level(); | 3194 context_depth_ = scopes_->yield_jump_variable->owner()->context_level(); |
| 3177 | 3195 |
| 3178 // Prepend an entry corresponding to normal entry to the function. | 3196 // Prepend an entry corresponding to normal entry to the function. |
| 3179 yield_continuations_.InsertAt( | 3197 yield_continuations_.InsertAt( |
| 3180 0, YieldContinuation(new (Z) DropTempsInstr(0, NULL), | 3198 0, YieldContinuation(new (Z) DropTempsInstr(0, NULL), |
| 3181 CatchClauseNode::kInvalidTryIndex)); | 3199 CatchClauseNode::kInvalidTryIndex)); |
| 3182 yield_continuations_[0].entry->LinkTo(body.entry); | 3200 yield_continuations_[0].entry->LinkTo(body.entry); |
| 3183 | 3201 |
| 3184 // Build a switch statement. | 3202 // Build a switch statement. |
| 3185 Fragment dispatch; | 3203 Fragment dispatch; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3231 | 3249 |
| 3232 // False branch will contain the next comparison. | 3250 // False branch will contain the next comparison. |
| 3233 dispatch = Fragment(dispatch.entry, otherwise); | 3251 dispatch = Fragment(dispatch.entry, otherwise); |
| 3234 block = otherwise; | 3252 block = otherwise; |
| 3235 } | 3253 } |
| 3236 body = dispatch; | 3254 body = dispatch; |
| 3237 | 3255 |
| 3238 context_depth_ = current_context_depth; | 3256 context_depth_ = current_context_depth; |
| 3239 } | 3257 } |
| 3240 | 3258 |
| 3259 if (FLAG_causal_async_stacks && | |
| 3260 (dart_function.IsAsyncClosure() || dart_function.IsAsyncGenClosure())) { | |
| 3261 // The code we are building will be executed right after we enter | |
| 3262 // the function and before any nested contexts are allocated. | |
| 3263 // Reset current context_depth_ to match this. | |
| 3264 const intptr_t current_context_depth = context_depth_; | |
| 3265 context_depth_ = scopes_->yield_jump_variable->owner()->context_level(); | |
| 3266 | |
| 3267 Fragment instructions; | |
| 3268 LocalScope* scope = parsed_function_->node_sequence()->scope(); | |
| 3269 | |
| 3270 const Function& target = Function::ZoneHandle( | |
| 3271 Z, I->object_store()->async_set_thread_stack_trace()); | |
| 3272 ASSERT(!target.IsNull()); | |
| 3273 | |
| 3274 // Fetch and load :async_stack_trace | |
| 3275 LocalVariable* async_stack_trace_var = | |
| 3276 scope->LookupVariable(Symbols::AsyncStackTraceVar(), false); | |
| 3277 ASSERT((async_stack_trace_var != NULL) && | |
| 3278 async_stack_trace_var->is_captured()); | |
| 3279 instructions += LoadLocal(async_stack_trace_var); | |
| 3280 instructions += PushArgument(); | |
| 3281 | |
| 3282 // Call _asyncSetThreadStackTrace | |
| 3283 instructions += StaticCall(TokenPosition::kNoSource, target, 1); | |
| 3284 instructions += Drop(); | |
| 3285 | |
| 3286 body = instructions + body; | |
| 3287 context_depth_ = current_context_depth; | |
| 3288 } | |
| 3289 | |
| 3241 if (FLAG_support_debugger && function->position().IsDebugPause() && | 3290 if (FLAG_support_debugger && function->position().IsDebugPause() && |
| 3242 !dart_function.is_native() && dart_function.is_debuggable()) { | 3291 !dart_function.is_native() && dart_function.is_debuggable()) { |
| 3243 // If a switch was added above: Start the switch by injecting a debugable | 3292 // If a switch was added above: Start the switch by injecting a debugable |
| 3244 // safepoint so stepping over an await works. | 3293 // safepoint so stepping over an await works. |
| 3245 // If not, still start the body with a debugable safepoint to ensure | 3294 // If not, still start the body with a debugable safepoint to ensure |
| 3246 // breaking on a method always happens, even if there are no | 3295 // breaking on a method always happens, even if there are no |
| 3247 // assignments/calls/runtimecalls in the first basic block. | 3296 // assignments/calls/runtimecalls in the first basic block. |
| 3248 // Place this check at the last parameter to ensure parameters | 3297 // Place this check at the last parameter to ensure parameters |
| 3249 // are in scope in the debugger at method entry. | 3298 // are in scope in the debugger at method entry. |
| 3250 const int num_params = dart_function.NumParameters(); | 3299 const int num_params = dart_function.NumParameters(); |
| (...skipping 2845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6096 | 6145 |
| 6097 fragment_ = continuation; | 6146 fragment_ = continuation; |
| 6098 } | 6147 } |
| 6099 | 6148 |
| 6100 | 6149 |
| 6101 Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node, | 6150 Fragment FlowGraphBuilder::TranslateFunctionNode(FunctionNode* node, |
| 6102 TreeNode* parent) { | 6151 TreeNode* parent) { |
| 6103 // The VM has a per-isolate table of functions indexed by the enclosing | 6152 // The VM has a per-isolate table of functions indexed by the enclosing |
| 6104 // function and token position. | 6153 // function and token position. |
| 6105 Function& function = Function::ZoneHandle(Z); | 6154 Function& function = Function::ZoneHandle(Z); |
| 6155 LocalScope* scope = NULL; | |
| 6106 for (intptr_t i = 0; i < scopes_->function_scopes.length(); ++i) { | 6156 for (intptr_t i = 0; i < scopes_->function_scopes.length(); ++i) { |
| 6107 if (scopes_->function_scopes[i].function != node) continue; | 6157 if (scopes_->function_scopes[i].function != node) continue; |
| 6108 | 6158 |
| 6109 TokenPosition position = node->position(); | 6159 TokenPosition position = node->position(); |
| 6110 if (parent->IsFunctionDeclaration()) { | 6160 if (parent->IsFunctionDeclaration()) { |
| 6111 position = FunctionDeclaration::Cast(parent)->position(); | 6161 position = FunctionDeclaration::Cast(parent)->position(); |
| 6112 } | 6162 } |
| 6113 if (!position.IsReal()) { | 6163 if (!position.IsReal()) { |
| 6114 // Positions has to be unique in regards to the parent. | 6164 // Positions has to be unique in regards to the parent. |
| 6115 // A non-real at this point is probably -1, we cannot blindly use that | 6165 // A non-real at this point is probably -1, we cannot blindly use that |
| 6116 // as others might use it too. Create a new dummy non-real TokenPosition. | 6166 // as others might use it too. Create a new dummy non-real TokenPosition. |
| 6117 position = TokenPosition(i).ToSynthetic(); | 6167 position = TokenPosition(i).ToSynthetic(); |
| 6118 } | 6168 } |
| 6119 | 6169 |
| 6120 // NOTE: This is not TokenPosition in the general sense! | 6170 // NOTE: This is not TokenPosition in the general sense! |
| 6121 function = I->LookupClosureFunction(parsed_function_->function(), position); | 6171 function = I->LookupClosureFunction(parsed_function_->function(), position); |
| 6172 scope = scopes_->function_scopes[i].scope; | |
| 6122 if (function.IsNull()) { | 6173 if (function.IsNull()) { |
| 6123 const dart::String* name; | 6174 const dart::String* name; |
| 6124 if (parent->IsFunctionExpression()) { | 6175 if (parent->IsFunctionExpression()) { |
| 6125 name = &Symbols::AnonymousClosure(); | 6176 name = &Symbols::AnonymousClosure(); |
| 6126 } else { | 6177 } else { |
| 6127 ASSERT(parent->IsFunctionDeclaration()); | 6178 ASSERT(parent->IsFunctionDeclaration()); |
| 6128 name = &H.DartSymbol( | 6179 name = &H.DartSymbol( |
| 6129 FunctionDeclaration::Cast(parent)->variable()->name()); | 6180 FunctionDeclaration::Cast(parent)->variable()->name()); |
| 6130 } | 6181 } |
| 6131 // NOTE: This is not TokenPosition in the general sense! | 6182 // NOTE: This is not TokenPosition in the general sense! |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 6145 function.set_modifier(RawFunction::kAsyncGen); | 6196 function.set_modifier(RawFunction::kAsyncGen); |
| 6146 break; | 6197 break; |
| 6147 default: | 6198 default: |
| 6148 // no special modifier | 6199 // no special modifier |
| 6149 break; | 6200 break; |
| 6150 } | 6201 } |
| 6151 function.set_is_generated_body(node->async_marker() == | 6202 function.set_is_generated_body(node->async_marker() == |
| 6152 FunctionNode::kSyncYielding); | 6203 FunctionNode::kSyncYielding); |
| 6153 | 6204 |
| 6154 function.set_end_token_pos(node->end_position()); | 6205 function.set_end_token_pos(node->end_position()); |
| 6155 LocalScope* scope = scopes_->function_scopes[i].scope; | |
| 6156 const ContextScope& context_scope = | 6206 const ContextScope& context_scope = |
| 6157 ContextScope::Handle(Z, scope->PreserveOuterScope(context_depth_)); | 6207 ContextScope::Handle(Z, scope->PreserveOuterScope(context_depth_)); |
| 6158 function.set_context_scope(context_scope); | 6208 function.set_context_scope(context_scope); |
| 6159 function.set_kernel_function(node); | 6209 function.set_kernel_function(node); |
| 6160 KernelReader::SetupFunctionParameters(H, T, dart::Class::Handle(Z), | 6210 KernelReader::SetupFunctionParameters(H, T, dart::Class::Handle(Z), |
| 6161 function, node, | 6211 function, node, |
| 6162 false, // is_method | 6212 false, // is_method |
| 6163 true); // is_closure | 6213 true); // is_closure |
| 6164 // Finalize function type. | 6214 // Finalize function type. |
| 6165 Type& signature_type = Type::Handle(Z, function.SignatureType()); | 6215 Type& signature_type = Type::Handle(Z, function.SignatureType()); |
| 6166 signature_type ^= ClassFinalizer::FinalizeType( | 6216 signature_type ^= ClassFinalizer::FinalizeType( |
| 6167 *active_class_.klass, signature_type, ClassFinalizer::kCanonicalize); | 6217 *active_class_.klass, signature_type, ClassFinalizer::kCanonicalize); |
| 6168 function.SetSignatureType(signature_type); | 6218 function.SetSignatureType(signature_type); |
| 6169 | 6219 |
| 6170 I->AddClosureFunction(function); | 6220 I->AddClosureFunction(function); |
| 6171 } | 6221 } |
| 6172 break; | 6222 break; |
| 6173 } | 6223 } |
| 6174 | 6224 |
| 6225 Fragment instructions; | |
| 6226 | |
| 6227 if (FLAG_causal_async_stacks && | |
|
kustermann
2017/02/23 10:30:37
You can move this code to FlowGraphBuilder::BuildG
| |
| 6228 (function.IsAsyncClosure() || function.IsAsyncGenClosure())) { | |
| 6229 // :async_stack_trace = _asyncStackTraceHelper(); | |
| 6230 const dart::Library& async_lib = | |
| 6231 dart::Library::Handle(dart::Library::AsyncLibrary()); | |
| 6232 const Function& target = Function::ZoneHandle( | |
| 6233 Z, | |
| 6234 async_lib.LookupFunctionAllowPrivate(Symbols::AsyncStackTraceHelper())); | |
| 6235 ASSERT(!target.IsNull()); | |
| 6236 instructions += StaticCall(TokenPosition::kNoSource, target, 0); | |
| 6237 LocalVariable* async_stack_trace_var = | |
| 6238 scope->LookupVariable(Symbols::AsyncStackTraceVar(), false); | |
| 6239 ASSERT(async_stack_trace_var != NULL); | |
| 6240 instructions += StoreLocal(TokenPosition::kNoSource, async_stack_trace_var); | |
| 6241 instructions += Drop(); | |
| 6242 } | |
| 6243 | |
| 6175 const dart::Class& closure_class = | 6244 const dart::Class& closure_class = |
| 6176 dart::Class::ZoneHandle(Z, I->object_store()->closure_class()); | 6245 dart::Class::ZoneHandle(Z, I->object_store()->closure_class()); |
| 6177 ASSERT(!closure_class.IsNull()); | 6246 ASSERT(!closure_class.IsNull()); |
| 6178 Fragment instructions = AllocateObject(closure_class, function); | 6247 instructions += AllocateObject(closure_class, function); |
| 6179 LocalVariable* closure = MakeTemporary(); | 6248 LocalVariable* closure = MakeTemporary(); |
| 6180 | 6249 |
| 6181 // TODO(27590): Generic closures need type arguments. | 6250 // TODO(27590): Generic closures need type arguments. |
| 6182 | 6251 |
| 6183 // Store the function and the context in the closure. | 6252 // Store the function and the context in the closure. |
| 6184 instructions += LoadLocal(closure); | 6253 instructions += LoadLocal(closure); |
| 6185 instructions += Constant(function); | 6254 instructions += Constant(function); |
| 6186 instructions += StoreInstanceField(Closure::function_offset()); | 6255 instructions += StoreInstanceField(Closure::function_offset()); |
| 6187 | 6256 |
| 6188 instructions += LoadLocal(closure); | 6257 instructions += LoadLocal(closure); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6299 thread->clear_sticky_error(); | 6368 thread->clear_sticky_error(); |
| 6300 return error.raw(); | 6369 return error.raw(); |
| 6301 } | 6370 } |
| 6302 } | 6371 } |
| 6303 | 6372 |
| 6304 | 6373 |
| 6305 } // namespace kernel | 6374 } // namespace kernel |
| 6306 } // namespace dart | 6375 } // namespace dart |
| 6307 | 6376 |
| 6308 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 6377 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
| OLD | NEW |