Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: runtime/vm/kernel_to_il.cc

Issue 2891053003: Add support for converted closures with explicit contexts to VM (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698