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

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

Issue 2998803002: [kernel] Support for top-level generic functions. (Closed)
Patch Set: Fix test. Created 3 years, 4 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 "vm/kernel_binary_flowgraph.h" 5 #include "vm/kernel_binary_flowgraph.h"
6
7 #include "vm/compiler.h" 6 #include "vm/compiler.h"
8 #include "vm/longjump.h" 7 #include "vm/longjump.h"
9 #include "vm/object_store.h" 8 #include "vm/object_store.h"
10 9
11 #if !defined(DART_PRECOMPILED_RUNTIME) 10 #if !defined(DART_PRECOMPILED_RUNTIME)
12 11
13 namespace dart { 12 namespace dart {
14 namespace kernel { 13 namespace kernel {
15 14
16 #define Z (zone_) 15 #define Z (zone_)
(...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after
1087 Function& function = Function::Handle(Z, parsed_function_->function().raw()); 1086 Function& function = Function::Handle(Z, parsed_function_->function().raw());
1088 while (function.IsClosureFunction()) { 1087 while (function.IsClosureFunction()) {
1089 function = function.parent_function(); 1088 function = function.parent_function();
1090 } 1089 }
1091 1090
1092 if (function.IsFactory()) { 1091 if (function.IsFactory()) {
1093 // The type argument vector is passed as the very first argument to the 1092 // The type argument vector is passed as the very first argument to the
1094 // factory constructor function. 1093 // factory constructor function.
1095 HandleSpecialLoad(&result_->type_arguments_variable, 1094 HandleSpecialLoad(&result_->type_arguments_variable,
1096 Symbols::TypeArgumentsParameter()); 1095 Symbols::TypeArgumentsParameter());
1097 } else { 1096 } else if (!function.IsGeneric()) {
1098 // The type argument vector is stored on the instance object. We therefore 1097 // KERNEL_GENERIC_METHODS_UNDONE(sjindel):
jensj 2017/08/11 06:24:54 Maybe this should be a TODO(sjindel) instead?
sjindel 2017/08/11 09:21:06 I gave it this name so it'll be easy to find when
jensj 2017/08/14 06:47:12 wouldn't "TODO(sjindel): Kernel generic methods u
sjindel 2017/08/14 11:05:49 Done, but splitting the "kernel generic methods" p
1099 // need to capture `this`. 1098 // Currently we only support generic toplevel methods. For no special load
1099 // needs to be prepared for these, because the 'LocalVariable' for the type
1100 // arguments is set on the 'ParsedFunction' directly. So we do nothing for
1101 // generic methods.
1102
1103 // The type argument vector is stored on the
1104 // instance object. We therefore need to capture `this`.
1100 HandleSpecialLoad(&result_->this_variable, Symbols::This()); 1105 HandleSpecialLoad(&result_->this_variable, Symbols::This());
1101 } 1106 }
1102 1107
1103 builder_->ReadUInt(); // read index for parameter. 1108 builder_->ReadUInt(); // read index for parameter.
1104 builder_->SkipOptionalDartType(); // read bound bound. 1109 builder_->SkipOptionalDartType(); // read bound bound.
1105 } 1110 }
1106 1111
1107 void StreamingScopeBuilder::HandleLocalFunction(intptr_t parent_kernel_offset) { 1112 void StreamingScopeBuilder::HandleLocalFunction(intptr_t parent_kernel_offset) {
1108 // "Peek" ahead into the function node 1113 // "Peek" ahead into the function node
1109 intptr_t offset = builder_->ReaderOffset(); 1114 intptr_t offset = builder_->ReaderOffset();
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after
1619 } 1624 }
1620 parameter_index -= class_types.Length(); 1625 parameter_index -= class_types.Length();
1621 } 1626 }
1622 1627
1623 intptr_t procedure_type_parameter_count = 1628 intptr_t procedure_type_parameter_count =
1624 active_class_->MemberIsProcedure() 1629 active_class_->MemberIsProcedure()
1625 ? active_class_->MemberTypeParameterCount(Z) 1630 ? active_class_->MemberTypeParameterCount(Z)
1626 : 0; 1631 : 0;
1627 if (procedure_type_parameter_count > 0) { 1632 if (procedure_type_parameter_count > 0) {
1628 if (procedure_type_parameter_count > parameter_index) { 1633 if (procedure_type_parameter_count > parameter_index) {
1629 // Here we technically could load the correct one via something like 1634 if (FLAG_reify_generic_functions) {
1630 // result_ ^= dart::TypeArguments::Handle( 1635 result_ ^= dart::TypeArguments::Handle(
1631 // Z, active_class_->member->type_parameters()) 1636 Z, active_class_->member->type_parameters())
1632 // .TypeAt(parameter_index); 1637 .TypeAt(parameter_index);
1633 // but that isn't currently supported elsewhere 1638 } else {
1634 // (FlowGraphBuilder::LoadFunctionTypeArguments()). 1639 result_ ^= dart::Type::DynamicType();
1635 result_ ^= dart::Type::DynamicType(); 1640 }
1636 return; 1641 return;
1637 } 1642 }
1638 parameter_index -= procedure_type_parameter_count; 1643 parameter_index -= procedure_type_parameter_count;
1639 } 1644 }
1640 } 1645 }
1641 1646
1642 if (type_parameter_scope_ != NULL && parameter_index >= 0 && 1647 if (type_parameter_scope_ != NULL && parameter_index >= 0 &&
1643 parameter_index < type_parameter_scope_->outer_parameter_count() + 1648 parameter_index < type_parameter_scope_->outer_parameter_count() +
1644 type_parameter_scope_->parameters_count()) { 1649 type_parameter_scope_->parameters_count()) {
1645 result_ ^= dart::Type::DynamicType(); 1650 result_ ^= dart::Type::DynamicType();
(...skipping 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after
2942 const Function& function) { 2947 const Function& function) {
2943 const Function& target = Function::ZoneHandle(Z, function.parent_function()); 2948 const Function& target = Function::ZoneHandle(Z, function.parent_function());
2944 2949
2945 TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry(); 2950 TargetEntryInstr* normal_entry = flow_graph_builder_->BuildTargetEntry();
2946 flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr( 2951 flow_graph_builder_->graph_entry_ = new (Z) GraphEntryInstr(
2947 *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId); 2952 *parsed_function(), normal_entry, Compiler::kNoOSRDeoptId);
2948 SetupDefaultParameterValues(); 2953 SetupDefaultParameterValues();
2949 2954
2950 Fragment body(normal_entry); 2955 Fragment body(normal_entry);
2951 body += flow_graph_builder_->CheckStackOverflowInPrologue(); 2956 body += flow_graph_builder_->CheckStackOverflowInPrologue();
2957 body += NullConstant();
2958 LocalVariable* result = MakeTemporary();
2952 2959
2953 // Load all the arguments. 2960 // Load all the arguments.
2954 ASSERT(target.is_static()); 2961 ASSERT(target.is_static());
2955 2962
2963 // KERNEL_GENERIC_METHODS_UNDONE(sjindel): Since the frontend can't yet emit
jensj 2017/08/11 06:24:54 ditto
sjindel 2017/08/14 11:05:49 Done.
2964 // generic methods into kernel, all type parameters to the target must come
2965 // from the context. When generic methods are fully supported, we will need to
2966 // get the type arguments provided by the caller and append them to the
2967 // captured type arguments via 'prependTypeArguments'.
2968
2956 FunctionNodeHelper function_node_helper(this); 2969 FunctionNodeHelper function_node_helper(this);
2970 function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
2971 intptr_t type_param_count = PeekUInt();
2957 function_node_helper.ReadUntilExcluding( 2972 function_node_helper.ReadUntilExcluding(
2958 FunctionNodeHelper::kPositionalParameters); 2973 FunctionNodeHelper::kPositionalParameters);
2959 2974
2960 // Positional. 2975 // Positional.
2961 const intptr_t positional_argument_count = ReadListLength(); 2976 const intptr_t positional_argument_count = ReadListLength();
2962 2977
2963 // The first argument is the instance of the closure class. For converted 2978 // The first argument is the instance of the closure class. For converted
2964 // closures its context field contains the context vector that is used by the 2979 // closures its context field contains the context vector that is used by the
2965 // converted top-level function (target) explicitly and that should be passed 2980 // converted top-level function (target) explicitly and that should be passed
2966 // to that function as the first parameter. 2981 // to that function as the first parameter.
2967 body += LoadLocal(LookupVariable(ReaderOffset())); // 0th variable offset. 2982 body += LoadLocal(LookupVariable(ReaderOffset())); // 0th variable offset.
2968 body += flow_graph_builder_->LoadField(Closure::context_offset()); 2983 body += flow_graph_builder_->LoadField(Closure::context_offset());
2984 LocalVariable* context = MakeTemporary();
2985
2986 if (type_param_count) {
jensj 2017/08/11 06:24:54 could this be made explicit? I suppose it means "i
sjindel 2017/08/11 09:21:06 It means "!= 0", but it can't be negative, because
2987 body += LoadLocal(context);
2988 body += flow_graph_builder_->LoadField(Context::variable_offset(0));
2989 body += PushArgument();
2990 }
2991
2992 body += LoadLocal(context);
2969 body += PushArgument(); 2993 body += PushArgument();
2970 SkipVariableDeclaration(); // read 0th variable. 2994 SkipVariableDeclaration(); // read 0th variable.
2971 2995
2972 // The rest of the parameters are the same for the method of the Closure class 2996 // The rest of the parameters are the same for the method of the Closure class
2973 // being invoked and the top-level function (target). 2997 // being invoked and the top-level function (target).
2974 for (intptr_t i = 1; i < positional_argument_count; i++) { 2998 for (intptr_t i = 1; i < positional_argument_count; i++) {
2975 body += LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset. 2999 body += LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset.
2976 body += PushArgument(); 3000 body += PushArgument();
2977 SkipVariableDeclaration(); // read ith variable. 3001 SkipVariableDeclaration(); // read ith variable.
2978 } 3002 }
2979 3003
2980 // Named. 3004 // Named.
2981 const intptr_t named_argument_count = ReadListLength(); 3005 const intptr_t named_argument_count = ReadListLength();
2982 Array& argument_names = Array::ZoneHandle(Z); 3006 Array& argument_names = Array::ZoneHandle(Z);
2983 if (named_argument_count > 0) { 3007 if (named_argument_count > 0) {
2984 argument_names = Array::New(named_argument_count); 3008 argument_names = Array::New(named_argument_count);
2985 for (intptr_t i = 0; i < named_argument_count; i++) { 3009 for (intptr_t i = 0; i < named_argument_count; i++) {
2986 body += 3010 body +=
2987 LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset. 3011 LoadLocal(LookupVariable(ReaderOffset())); // ith variable offset.
2988 body += PushArgument(); 3012 body += PushArgument();
2989 argument_names.SetAt( 3013 argument_names.SetAt(
2990 i, H.DartSymbol(GetNameFromVariableDeclaration(ReaderOffset()))); 3014 i, H.DartSymbol(GetNameFromVariableDeclaration(ReaderOffset())));
2991 SkipVariableDeclaration(); // read ith variable. 3015 SkipVariableDeclaration(); // read ith variable.
2992 } 3016 }
2993 } 3017 }
2994 3018
2995 // Forward them to the target. 3019 // Forward them to the target.
2996 const intptr_t argument_count = 3020 const intptr_t argument_count =
2997 positional_argument_count + named_argument_count; 3021 positional_argument_count + named_argument_count + !!type_param_count;
jensj 2017/08/11 06:24:54 "!!type_param_count"?
sjindel 2017/08/11 09:21:06 "!!" converts a number to 1 or 0, depending on whe
2998 body += StaticCall(TokenPosition::kNoSource, target, argument_count, 3022 body += StaticCall(TokenPosition::kNoSource, target, argument_count,
2999 argument_names); 3023 argument_names, type_param_count);
3000 3024
3001 // Return the result. 3025 // Return the result.
3026 body += StoreLocal(TokenPosition::kNoSource, result);
3027 body += Drop();
3028 body += Drop();
3002 body += Return(function_node_helper.end_position_); 3029 body += Return(function_node_helper.end_position_);
3003 3030
3004 return new (Z) 3031 return new (Z)
3005 FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_, 3032 FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
3006 flow_graph_builder_->next_block_id_ - 1); 3033 flow_graph_builder_->next_block_id_ - 1);
3007 } 3034 }
3008 3035
3009 FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction( 3036 FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(
3010 intptr_t constructor_class_parent_offset) { 3037 intptr_t constructor_class_parent_offset) {
3011 const Function& dart_function = parsed_function()->function(); 3038 const Function& dart_function = parsed_function()->function();
(...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after
4397 4424
4398 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, 4425 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
4399 const Function& target, 4426 const Function& target,
4400 intptr_t argument_count) { 4427 intptr_t argument_count) {
4401 return flow_graph_builder_->StaticCall(position, target, argument_count); 4428 return flow_graph_builder_->StaticCall(position, target, argument_count);
4402 } 4429 }
4403 4430
4404 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, 4431 Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
4405 const Function& target, 4432 const Function& target,
4406 intptr_t argument_count, 4433 intptr_t argument_count,
4407 const Array& argument_names) { 4434 const Array& argument_names,
4435 intptr_t type_args_count) {
4408 return flow_graph_builder_->StaticCall(position, target, argument_count, 4436 return flow_graph_builder_->StaticCall(position, target, argument_count,
4409 argument_names); 4437 argument_names, type_args_count);
4410 } 4438 }
4411 4439
4412 Fragment StreamingFlowGraphBuilder::InstanceCall( 4440 Fragment StreamingFlowGraphBuilder::InstanceCall(
4413 TokenPosition position, 4441 TokenPosition position,
4414 const dart::String& name, 4442 const dart::String& name,
4415 Token::Kind kind, 4443 Token::Kind kind,
4416 intptr_t argument_count, 4444 intptr_t argument_count,
4417 intptr_t checked_argument_count) { 4445 intptr_t checked_argument_count) {
4418 return flow_graph_builder_->InstanceCall(position, name, kind, argument_count, 4446 return flow_graph_builder_->InstanceCall(position, name, kind, argument_count,
4419 checked_argument_count); 4447 checked_argument_count);
(...skipping 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after
5818 instructions += Constant(function); 5846 instructions += Constant(function);
5819 instructions += 5847 instructions +=
5820 StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset()); 5848 StoreInstanceField(TokenPosition::kNoSource, Closure::function_offset());
5821 5849
5822 instructions += LoadLocal(closure); 5850 instructions += LoadLocal(closure);
5823 instructions += LoadLocal(context); 5851 instructions += LoadLocal(context);
5824 instructions += 5852 instructions +=
5825 StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset()); 5853 StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset());
5826 5854
5827 instructions += Drop(); 5855 instructions += Drop();
5856 SkipDartType(); // skip function type of the closure.
5828 5857
5829 SkipDartType(); // skip function type of the closure. 5858 // KERNEL_GENERIC_METHODS_UNDONE(sjindel): When generic methods are fully
jensj 2017/08/11 06:24:54 todo?
5830 SkipListOfDartTypes(); // skip list of type arguments. 5859 // supported in kernel, we'll need to store a NULL in the type arguments slot
5860 // when type arguments are absent, so the wrapper for the target function can
5861 // tell how many type args are captured vs. provided by the caller of the
5862 // closure.
5863
5864 intptr_t types_count = ReadListLength(); // read type count.
5865 if (types_count > 0) {
5866 instructions += LoadLocal(context);
5867
5868 const TypeArguments& type_args =
5869 T.BuildTypeArguments(types_count); // read list of type arguments.
5870 instructions += TranslateInstantiatedTypeArguments(type_args);
5871
5872 instructions += StoreInstanceField(TokenPosition::kNoSource,
5873 Context::variable_offset(0));
5874 }
5831 5875
5832 return instructions; 5876 return instructions;
5833 } 5877 }
5834 5878
5835 Fragment StreamingFlowGraphBuilder::BuildInvalidStatement() { 5879 Fragment StreamingFlowGraphBuilder::BuildInvalidStatement() {
5836 H.ReportError("Invalid statements not implemented yet!"); 5880 H.ReportError("Invalid statements not implemented yet!");
5837 return Fragment(); 5881 return Fragment();
5838 } 5882 }
5839 5883
5840 Fragment StreamingFlowGraphBuilder::BuildExpressionStatement() { 5884 Fragment StreamingFlowGraphBuilder::BuildExpressionStatement() {
(...skipping 1360 matching lines...) Expand 10 before | Expand all | Expand 10 after
7201 } 7245 }
7202 } 7246 }
7203 7247
7204 return Array::Handle(Array::null()); 7248 return Array::Handle(Array::null());
7205 } 7249 }
7206 7250
7207 } // namespace kernel 7251 } // namespace kernel
7208 } // namespace dart 7252 } // namespace dart
7209 7253
7210 #endif // !defined(DART_PRECOMPILED_RUNTIME) 7254 #endif // !defined(DART_PRECOMPILED_RUNTIME)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698