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 <set> | 5 #include <set> |
6 | 6 |
7 #include "vm/kernel_to_il.h" | 7 #include "vm/kernel_to_il.h" |
8 | 8 |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/intermediate_language.h" | 10 #include "vm/intermediate_language.h" |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
322 | 322 |
323 LocalVariable* context_var = parsed_function->current_context_var(); | 323 LocalVariable* context_var = parsed_function->current_context_var(); |
324 context_var->set_is_forced_stack(); | 324 context_var->set_is_forced_stack(); |
325 scope_->AddVariable(context_var); | 325 scope_->AddVariable(context_var); |
326 | 326 |
327 parsed_function->SetNodeSequence( | 327 parsed_function->SetNodeSequence( |
328 new SequenceNode(TokenPosition::kNoSource, scope_)); | 328 new SequenceNode(TokenPosition::kNoSource, scope_)); |
329 | 329 |
330 switch (function.kind()) { | 330 switch (function.kind()) { |
331 case RawFunction::kClosureFunction: | 331 case RawFunction::kClosureFunction: |
332 case RawFunction::kConvertedClosureFunction: | |
332 case RawFunction::kRegularFunction: | 333 case RawFunction::kRegularFunction: |
333 case RawFunction::kGetterFunction: | 334 case RawFunction::kGetterFunction: |
334 case RawFunction::kSetterFunction: | 335 case RawFunction::kSetterFunction: |
335 case RawFunction::kConstructor: { | 336 case RawFunction::kConstructor: { |
336 FunctionNode* node; | 337 FunctionNode* node; |
337 if (node_->IsProcedure()) { | 338 if (node_->IsProcedure()) { |
338 node = Procedure::Cast(node_)->function(); | 339 node = Procedure::Cast(node_)->function(); |
339 } else if (node_->IsConstructor()) { | 340 } else if (node_->IsConstructor()) { |
340 node = Constructor::Cast(node_)->function(); | 341 node = Constructor::Cast(node_)->function(); |
341 } else { | 342 } else { |
342 node = FunctionNode::Cast(node_); | 343 node = FunctionNode::Cast(node_); |
343 } | 344 } |
344 current_function_node_ = node; | 345 current_function_node_ = node; |
345 | 346 |
346 intptr_t pos = 0; | 347 intptr_t pos = 0; |
347 if (function.IsClosureFunction()) { | 348 if (function.IsClosureFunction()) { |
348 LocalVariable* variable = MakeVariable( | 349 LocalVariable* variable = MakeVariable( |
349 TokenPosition::kNoSource, TokenPosition::kNoSource, | 350 TokenPosition::kNoSource, TokenPosition::kNoSource, |
350 Symbols::ClosureParameter(), AbstractType::dynamic_type()); | 351 Symbols::ClosureParameter(), AbstractType::dynamic_type()); |
351 variable->set_is_forced_stack(); | 352 variable->set_is_forced_stack(); |
352 scope_->InsertParameterAt(pos++, variable); | 353 scope_->InsertParameterAt(pos++, variable); |
354 } else if (function.IsConvertedClosureFunction()) { | |
355 // Do nothing. The explicit context parameter is already included into | |
356 // the parameter list of the parent function. | |
353 } else if (!function.is_static()) { | 357 } else if (!function.is_static()) { |
354 // We use [is_static] instead of [IsStaticFunction] because the latter | 358 // We use [is_static] instead of [IsStaticFunction] because the latter |
355 // returns `false` for constructors. | 359 // returns `false` for constructors. |
356 dart::Class& klass = dart::Class::Handle(Z, function.Owner()); | 360 dart::Class& klass = dart::Class::Handle(Z, function.Owner()); |
357 Type& klass_type = H.GetCanonicalType(klass); | 361 Type& klass_type = H.GetCanonicalType(klass); |
358 LocalVariable* variable = | 362 LocalVariable* variable = |
359 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, | 363 MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
360 Symbols::This(), klass_type); | 364 Symbols::This(), klass_type); |
361 scope_->InsertParameterAt(pos++, variable); | 365 scope_->InsertParameterAt(pos++, variable); |
362 result_->this_variable = variable; | 366 result_->this_variable = variable; |
(...skipping 14 matching lines...) Expand all Loading... | |
377 } | 381 } |
378 } else if (function.IsFactory()) { | 382 } else if (function.IsFactory()) { |
379 LocalVariable* variable = MakeVariable( | 383 LocalVariable* variable = MakeVariable( |
380 TokenPosition::kNoSource, TokenPosition::kNoSource, | 384 TokenPosition::kNoSource, TokenPosition::kNoSource, |
381 Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type()); | 385 Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type()); |
382 scope_->InsertParameterAt(pos++, variable); | 386 scope_->InsertParameterAt(pos++, variable); |
383 result_->type_arguments_variable = variable; | 387 result_->type_arguments_variable = variable; |
384 } | 388 } |
385 AddParameters(node, pos); | 389 AddParameters(node, pos); |
386 | 390 |
387 // We generate a syntethic body for implicit closure functions - which | 391 // We generate a syntethic body for implicit closure functions and |
388 // will forward the call to the real function. | 392 // converted |
393 // closure functions - which will forward the call to the real function. | |
389 // -> see BuildGraphOfImplicitClosureFunction | 394 // -> see BuildGraphOfImplicitClosureFunction |
390 if (!function.IsImplicitClosureFunction()) { | 395 // -> see BuildGraphOfConvertedClosureFunction |
396 | |
397 if (!function.IsImplicitClosureFunction() && | |
398 !function.IsConvertedClosureFunction()) { | |
391 // TODO(jensj): HACK: Push the begin token to after any parameters to | 399 // TODO(jensj): HACK: Push the begin token to after any parameters to |
392 // avoid crash when breaking on definition line of async method in | 400 // avoid crash when breaking on definition line of async method in |
393 // debugger. It seems that another scope needs to be added | 401 // debugger. It seems that another scope needs to be added |
394 // in which captures are made, but I can't make that work. | 402 // in which captures are made, but I can't make that work. |
395 // This 'solution' doesn't crash, but I cannot see the parameters at | 403 // This 'solution' doesn't crash, but I cannot see the parameters at |
396 // that particular breakpoint either. | 404 // that particular breakpoint either. |
397 // Also push the end token to after the "}" to avoid crashing on | 405 // Also push the end token to after the "}" to avoid crashing on |
398 // stepping past the last line (to the "}" character). | 406 // stepping past the last line (to the "}" character). |
399 if (node->body() != NULL && node->body()->position().IsReal()) { | 407 if (node->body() != NULL && node->body()->position().IsReal()) { |
400 scope_->set_begin_token_pos(node->body()->position()); | 408 scope_->set_begin_token_pos(node->body()->position()); |
(...skipping 2793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3194 | 3202 |
3195 // The IR builder will create its own local variables and scopes, and it | 3203 // The IR builder will create its own local variables and scopes, and it |
3196 // will not need an AST. The code generator will assume that there is a | 3204 // will not need an AST. The code generator will assume that there is a |
3197 // local variable stack slot allocated for the current context and (I | 3205 // local variable stack slot allocated for the current context and (I |
3198 // think) that the runtime will expect it to be at a fixed offset which | 3206 // think) that the runtime will expect it to be at a fixed offset which |
3199 // requires allocating an unused expression temporary variable. | 3207 // requires allocating an unused expression temporary variable. |
3200 scopes_ = parsed_function_->EnsureKernelScopes(); | 3208 scopes_ = parsed_function_->EnsureKernelScopes(); |
3201 | 3209 |
3202 switch (function.kind()) { | 3210 switch (function.kind()) { |
3203 case RawFunction::kClosureFunction: | 3211 case RawFunction::kClosureFunction: |
3212 case RawFunction::kConvertedClosureFunction: | |
3204 case RawFunction::kRegularFunction: | 3213 case RawFunction::kRegularFunction: |
3205 case RawFunction::kGetterFunction: | 3214 case RawFunction::kGetterFunction: |
3206 case RawFunction::kSetterFunction: { | 3215 case RawFunction::kSetterFunction: { |
3207 FunctionNode* kernel_function = node_->IsProcedure() | 3216 FunctionNode* kernel_function = node_->IsProcedure() |
3208 ? Procedure::Cast(node_)->function() | 3217 ? Procedure::Cast(node_)->function() |
3209 : FunctionNode::Cast(node_); | 3218 : FunctionNode::Cast(node_); |
3210 ActiveFunctionScope active_function_scope(&active_class_, | 3219 ActiveFunctionScope active_function_scope(&active_class_, |
3211 kernel_function); | 3220 kernel_function); |
3212 return function.IsImplicitClosureFunction() | 3221 if (function.IsImplicitClosureFunction()) { |
3213 ? BuildGraphOfImplicitClosureFunction(kernel_function, | 3222 return BuildGraphOfImplicitClosureFunction(kernel_function, function); |
3214 function) | 3223 } else if (function.IsConvertedClosureFunction()) { |
3215 : BuildGraphOfFunction(kernel_function); | 3224 return BuildGraphOfConvertedClosureFunction(kernel_function, function); |
3225 } else { | |
3226 return BuildGraphOfFunction(kernel_function); | |
3227 } | |
3216 } | 3228 } |
3217 case RawFunction::kConstructor: { | 3229 case RawFunction::kConstructor: { |
3218 bool is_factory = function.IsFactory(); | 3230 bool is_factory = function.IsFactory(); |
3219 if (is_factory) { | 3231 if (is_factory) { |
3220 Procedure* procedure = Procedure::Cast(node_); | 3232 Procedure* procedure = Procedure::Cast(node_); |
3221 FunctionNode* function = procedure->function(); | 3233 FunctionNode* function = procedure->function(); |
3222 ActiveFunctionScope active_function_scope(&active_class_, function); | 3234 ActiveFunctionScope active_function_scope(&active_class_, function); |
3223 return BuildGraphOfFunction(function, NULL); | 3235 return BuildGraphOfFunction(function, NULL); |
3224 } else { | 3236 } else { |
3225 Constructor* constructor = Constructor::Cast(node_); | 3237 Constructor* constructor = Constructor::Cast(node_); |
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4021 body += StaticCall(TokenPosition::kNoSource, target, argument_count, | 4033 body += StaticCall(TokenPosition::kNoSource, target, argument_count, |
4022 argument_names); | 4034 argument_names); |
4023 | 4035 |
4024 // Return the result. | 4036 // Return the result. |
4025 body += Return(kernel_function->end_position()); | 4037 body += Return(kernel_function->end_position()); |
4026 | 4038 |
4027 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1); | 4039 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1); |
4028 } | 4040 } |
4029 | 4041 |
4030 | 4042 |
4043 // This method follows the logic similar to that of | |
4044 // FlowGraphBuilder::BuildGraphOfImplicitClosureFunction. For additional | |
4045 // details on converted closure functions, please, see the comment on the method | |
4046 // Function::ConvertedClosureFunction. | |
4047 FlowGraph* FlowGraphBuilder::BuildGraphOfConvertedClosureFunction( | |
4048 FunctionNode* kernel_function, | |
4049 const Function& function) { | |
4050 const Function& target = Function::ZoneHandle(Z, function.parent_function()); | |
4051 | |
4052 TargetEntryInstr* normal_entry = BuildTargetEntry(); | |
4053 graph_entry_ = new (Z) | |
4054 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId); | |
4055 SetupDefaultParameterValues(kernel_function); | |
4056 | |
4057 Fragment body(normal_entry); | |
4058 body += CheckStackOverflowInPrologue(); | |
4059 | |
4060 // Load all the arguments. | |
4061 ASSERT(target.is_static()); | |
4062 // The first argument is the value that the target function is converted over. | |
4063 // It is stored in the context field of the Closure class instance. The | |
4064 // instance is passed as the first argument to the call. | |
4065 body += LoadLocal(parsed_function_->node_sequence()->scope()->VariableAt(0)); | |
4066 body += LoadField(Closure::context_offset()); | |
4067 body += PushArgument(); | |
4068 | |
4069 // The rest of the parameters are the same for the method of the Closure class | |
4070 // being invoked and the top-level target function. | |
4071 intptr_t positional_argument_count = | |
4072 kernel_function->positional_parameters().length(); | |
4073 for (intptr_t i = 1; i < positional_argument_count; i++) { | |
4074 body += | |
4075 LoadLocal(LookupVariable(kernel_function->positional_parameters()[i])); | |
4076 body += PushArgument(); | |
4077 } | |
4078 intptr_t named_argument_count = kernel_function->named_parameters().length(); | |
4079 Array& argument_names = Array::ZoneHandle(Z); | |
4080 if (named_argument_count > 0) { | |
4081 argument_names = Array::New(named_argument_count); | |
4082 for (intptr_t i = 0; i < named_argument_count; i++) { | |
4083 VariableDeclaration* variable = kernel_function->named_parameters()[i]; | |
4084 body += LoadLocal(LookupVariable(variable)); | |
4085 body += PushArgument(); | |
4086 argument_names.SetAt(i, H.DartSymbol(variable->name())); | |
4087 } | |
4088 } | |
4089 // Forward them to the target. | |
4090 intptr_t argument_count = positional_argument_count + named_argument_count; | |
4091 body += StaticCall(TokenPosition::kNoSource, target, argument_count, | |
4092 argument_names); | |
4093 | |
4094 // Return the result. | |
4095 body += Return(kernel_function->end_position()); | |
4096 | |
4097 return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1); | |
4098 } | |
4099 | |
4100 | |
4031 FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher( | 4101 FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher( |
4032 const Function& function) { | 4102 const Function& function) { |
4033 // This function is specialized for a receiver class, a method name, and | 4103 // This function is specialized for a receiver class, a method name, and |
4034 // the arguments descriptor at a call site. | 4104 // the arguments descriptor at a call site. |
4035 | 4105 |
4036 TargetEntryInstr* normal_entry = BuildTargetEntry(); | 4106 TargetEntryInstr* normal_entry = BuildTargetEntry(); |
4037 graph_entry_ = new (Z) | 4107 graph_entry_ = new (Z) |
4038 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId); | 4108 GraphEntryInstr(*parsed_function_, normal_entry, Compiler::kNoOSRDeoptId); |
4039 | 4109 |
4040 // The backend will expect an array of default values for all the named | 4110 // The backend will expect an array of default values for all the named |
(...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4724 void DartTypeTranslator::VisitDynamicType(DynamicType* node) { | 4794 void DartTypeTranslator::VisitDynamicType(DynamicType* node) { |
4725 result_ = Object::dynamic_type().raw(); | 4795 result_ = Object::dynamic_type().raw(); |
4726 } | 4796 } |
4727 | 4797 |
4728 | 4798 |
4729 void DartTypeTranslator::VisitVoidType(VoidType* node) { | 4799 void DartTypeTranslator::VisitVoidType(VoidType* node) { |
4730 result_ = Object::void_type().raw(); | 4800 result_ = Object::void_type().raw(); |
4731 } | 4801 } |
4732 | 4802 |
4733 | 4803 |
4804 void DartTypeTranslator::VisitVectorType(VectorType* node) { | |
4805 result_ = Object::vector_type().raw(); | |
4806 } | |
4807 | |
4808 | |
4734 void DartTypeTranslator::VisitBottomType(BottomType* node) { | 4809 void DartTypeTranslator::VisitBottomType(BottomType* node) { |
4735 result_ = | 4810 result_ = |
4736 dart::Class::Handle(Z, I->object_store()->null_class()).CanonicalType(); | 4811 dart::Class::Handle(Z, I->object_store()->null_class()).CanonicalType(); |
4737 } | 4812 } |
4738 | 4813 |
4739 | 4814 |
4740 const TypeArguments& DartTypeTranslator::TranslateTypeArguments( | 4815 const TypeArguments& DartTypeTranslator::TranslateTypeArguments( |
4741 DartType** dart_types, | 4816 DartType** dart_types, |
4742 intptr_t length) { | 4817 intptr_t length) { |
4743 bool only_dynamic = true; | 4818 bool only_dynamic = true; |
(...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5652 fragment_ = instructions; | 5727 fragment_ = instructions; |
5653 } | 5728 } |
5654 | 5729 |
5655 | 5730 |
5656 void FlowGraphBuilder::VisitRethrow(Rethrow* node) { | 5731 void FlowGraphBuilder::VisitRethrow(Rethrow* node) { |
5657 fragment_ = | 5732 fragment_ = |
5658 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); | 5733 streaming_flow_graph_builder_->BuildExpressionAt(node->kernel_offset()); |
5659 } | 5734 } |
5660 | 5735 |
5661 | 5736 |
5737 void FlowGraphBuilder::VisitVectorCreation(VectorCreation* node) { | |
5738 ASSERT(node->value() > 0); | |
jensj
2017/05/18 11:19:06
STREAM_EXPRESSION_IF_POSSIBLE(node); ? (the same f
Dmitry Stefantsov
2017/05/18 12:18:53
Yep, that explains why the code worked without the
| |
5739 Fragment instructions = AllocateContext(node->value()); | |
5740 fragment_ = instructions; | |
5741 } | |
5742 | |
5743 | |
5744 void FlowGraphBuilder::VisitVectorGet(VectorGet* node) { | |
5745 Fragment instructions; | |
5746 | |
5747 instructions += TranslateExpression(node->vector_expression()); | |
5748 instructions += LoadField(Context::variable_offset(node->index())); | |
5749 | |
5750 fragment_ = instructions; | |
5751 } | |
5752 | |
5753 | |
5754 void FlowGraphBuilder::VisitVectorSet(VectorSet* node) { | |
5755 Fragment instructions; | |
5756 | |
5757 instructions += TranslateExpression(node->vector_expression()); | |
5758 instructions += TranslateExpression(node->value()); | |
5759 LocalVariable* result = MakeTemporary(); | |
5760 | |
5761 Value* value = Pop(); | |
5762 StoreInstanceFieldInstr* store = new (Z) | |
5763 StoreInstanceFieldInstr(Context::variable_offset(node->index()), Pop(), | |
5764 value, kNoStoreBarrier, TokenPosition::kNoSource); | |
5765 instructions <<= store; | |
5766 | |
5767 // Result of a vector-set operation is its rhs. It is useful, especially for | |
5768 // assignment chains. | |
5769 instructions += LoadLocal(result); | |
5770 | |
5771 fragment_ = instructions; | |
5772 } | |
5773 | |
5774 | |
5775 void FlowGraphBuilder::VisitVectorCopy(VectorCopy* node) { | |
5776 Fragment instructions; | |
5777 | |
5778 instructions += TranslateExpression(node->vector_expression()); | |
5779 CloneContextInstr* clone_instruction = | |
5780 new (Z) CloneContextInstr(TokenPosition::kNoSource, Pop()); | |
5781 instructions <<= clone_instruction; | |
5782 Push(clone_instruction); | |
5783 | |
5784 fragment_ = instructions; | |
5785 } | |
5786 | |
5787 | |
5788 void FlowGraphBuilder::VisitClosureCreation(ClosureCreation* node) { | |
5789 Fragment instructions; | |
5790 | |
5791 Function& function = Function::ZoneHandle( | |
5792 Z, H.LookupStaticMethodByKernelProcedure(node->top_level_function())); | |
5793 function = function.ConvertedClosureFunction(); | |
5794 ASSERT(!function.IsNull()); | |
5795 | |
5796 const dart::Class& closure_class = | |
5797 dart::Class::ZoneHandle(Z, I->object_store()->closure_class()); | |
5798 instructions += AllocateObject(closure_class, function); | |
5799 LocalVariable* closure = MakeTemporary(); | |
5800 | |
5801 instructions += TranslateExpression(node->context_vector()); | |
5802 LocalVariable* context = MakeTemporary(); | |
5803 | |
5804 instructions += LoadLocal(closure); | |
5805 instructions += Constant(function); | |
5806 instructions += | |
5807 StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset()); | |
5808 | |
5809 instructions += LoadLocal(closure); | |
5810 instructions += LoadLocal(context); | |
5811 instructions += | |
5812 StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset()); | |
5813 | |
5814 instructions += Drop(); | |
5815 | |
5816 fragment_ = instructions; | |
5817 } | |
5818 | |
5819 | |
5662 Fragment FlowGraphBuilder::TranslateArguments(Arguments* node, | 5820 Fragment FlowGraphBuilder::TranslateArguments(Arguments* node, |
5663 Array* argument_names) { | 5821 Array* argument_names) { |
5664 Fragment instructions; | 5822 Fragment instructions; |
5665 | 5823 |
5666 List<Expression>& positional = node->positional(); | 5824 List<Expression>& positional = node->positional(); |
5667 for (intptr_t i = 0; i < positional.length(); ++i) { | 5825 for (intptr_t i = 0; i < positional.length(); ++i) { |
5668 instructions += TranslateExpression(positional[i]); | 5826 instructions += TranslateExpression(positional[i]); |
5669 instructions += PushArgument(); | 5827 instructions += PushArgument(); |
5670 } | 5828 } |
5671 | 5829 |
(...skipping 1143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6815 thread->clear_sticky_error(); | 6973 thread->clear_sticky_error(); |
6816 return error.raw(); | 6974 return error.raw(); |
6817 } | 6975 } |
6818 } | 6976 } |
6819 | 6977 |
6820 | 6978 |
6821 } // namespace kernel | 6979 } // namespace kernel |
6822 } // namespace dart | 6980 } // namespace dart |
6823 | 6981 |
6824 #endif // !defined(DART_PRECOMPILED_RUNTIME) | 6982 #endif // !defined(DART_PRECOMPILED_RUNTIME) |
OLD | NEW |