Chromium Code Reviews| Index: runtime/vm/kernel_binary_flowgraph.cc |
| diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc |
| index 43e9545798e197b22479d7b39bc2bf24108d3f87..c0e00c300ba5f61f75e4593e1f69de9691166b24 100644 |
| --- a/runtime/vm/kernel_binary_flowgraph.cc |
| +++ b/runtime/vm/kernel_binary_flowgraph.cc |
| @@ -3,7 +3,6 @@ |
| // BSD-style license that can be found in the LICENSE file. |
| #include "vm/kernel_binary_flowgraph.h" |
| - |
| #include "vm/compiler.h" |
| #include "vm/longjump.h" |
| #include "vm/object_store.h" |
| @@ -1101,9 +1100,14 @@ void StreamingScopeBuilder::VisitTypeParameterType() { |
| // factory constructor function. |
| HandleSpecialLoad(&result_->type_arguments_variable, |
| Symbols::TypeArgumentsParameter()); |
| - } else { |
| - // The type argument vector is stored on the instance object. We therefore |
| - // need to capture `this`. |
| + } else if (!function.IsGeneric()) { |
| + // TODO(sjindel): Kernel generic methods undone. Currently we only support |
| + // generic toplevel methods. For no special load needs to be prepared for |
| + // these, because the 'LocalVariable' for the type arguments is set on the |
| + // 'ParsedFunction' directly. So we do nothing for generic methods. |
| + |
| + // The type argument vector is stored on the |
| + // instance object. We therefore need to capture `this`. |
| HandleSpecialLoad(&result_->this_variable, Symbols::This()); |
| } |
| @@ -1630,13 +1634,13 @@ void StreamingDartTypeTranslator::BuildTypeParameterType() { |
| : 0; |
| if (procedure_type_parameter_count > 0) { |
| if (procedure_type_parameter_count > parameter_index) { |
| - // Here we technically could load the correct one via something like |
| - // result_ ^= dart::TypeArguments::Handle( |
| - // Z, active_class_->member->type_parameters()) |
| - // .TypeAt(parameter_index); |
| - // but that isn't currently supported elsewhere |
| - // (FlowGraphBuilder::LoadFunctionTypeArguments()). |
| - result_ ^= dart::Type::DynamicType(); |
| + if (FLAG_reify_generic_functions) { |
| + result_ ^= dart::TypeArguments::Handle( |
| + Z, active_class_->member->type_parameters()) |
| + .TypeAt(parameter_index); |
| + } else { |
| + result_ ^= dart::Type::DynamicType(); |
| + } |
| return; |
| } |
| parameter_index -= procedure_type_parameter_count; |
| @@ -2981,11 +2985,21 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfConvertedClosureFunction( |
| Fragment body(normal_entry); |
| body += flow_graph_builder_->CheckStackOverflowInPrologue(); |
| + body += NullConstant(); |
| + LocalVariable* result = MakeTemporary(); |
| // Load all the arguments. |
| ASSERT(target.is_static()); |
| + // KERNEL_GENERIC_METHODS_UNDONE(sjindel): Since the frontend can't yet emit |
|
Dmitry Stefantsov
2017/08/16 11:44:39
How about creating an issue and using something li
sjindel
2017/08/16 12:57:12
Done.
|
| + // generic methods into kernel, all type parameters to the target must come |
| + // from the context. When generic methods are fully supported, we will need to |
| + // get the type arguments provided by the caller and append them to the |
| + // captured type arguments via 'prependTypeArguments'. |
| + |
| FunctionNodeHelper function_node_helper(this); |
| + function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters); |
| + intptr_t type_param_count = PeekUInt(); |
| function_node_helper.ReadUntilExcluding( |
| FunctionNodeHelper::kPositionalParameters); |
| @@ -2999,6 +3013,15 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfConvertedClosureFunction( |
| body += LoadLocal(LookupVariable( |
| ReaderOffset() + relative_kernel_offset_)); // 0th variable offset. |
| body += flow_graph_builder_->LoadField(Closure::context_offset()); |
| + LocalVariable* context = MakeTemporary(); |
| + |
| + if (type_param_count > 0) { |
| + body += LoadLocal(context); |
| + body += flow_graph_builder_->LoadField(Context::variable_offset(0)); |
| + body += PushArgument(); |
| + } |
| + |
| + body += LoadLocal(context); |
| body += PushArgument(); |
| SkipVariableDeclaration(); // read 0th variable. |
| @@ -3031,12 +3054,15 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfConvertedClosureFunction( |
| } |
| // Forward them to the target. |
| - const intptr_t argument_count = |
| - positional_argument_count + named_argument_count; |
| + intptr_t argument_count = positional_argument_count + named_argument_count; |
| + if (type_param_count) ++argument_count; |
| body += StaticCall(TokenPosition::kNoSource, target, argument_count, |
| - argument_names); |
| + argument_names, type_param_count); |
| // Return the result. |
| + body += StoreLocal(TokenPosition::kNoSource, result); |
| + body += Drop(); |
| + body += Drop(); |
| body += Return(function_node_helper.end_position_); |
| return new (Z) |
| @@ -4438,9 +4464,10 @@ Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, |
| Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position, |
| const Function& target, |
| intptr_t argument_count, |
| - const Array& argument_names) { |
| + const Array& argument_names, |
| + intptr_t type_args_count) { |
| return flow_graph_builder_->StaticCall(position, target, argument_count, |
| - argument_names); |
| + argument_names, type_args_count); |
| } |
| Fragment StreamingFlowGraphBuilder::InstanceCall( |
| @@ -5858,9 +5885,25 @@ Fragment StreamingFlowGraphBuilder::BuildClosureCreation( |
| StoreInstanceField(TokenPosition::kNoSource, Closure::context_offset()); |
| instructions += Drop(); |
| - |
| SkipDartType(); // skip function type of the closure. |
| - SkipListOfDartTypes(); // skip list of type arguments. |
| + |
| + // TODO(sjindel): Kernel generic methods undone. When generic methods are |
| + // fully supported in kernel, we'll need to store a NULL in the type arguments |
| + // slot when type arguments are absent, so the wrapper for the target function |
| + // can tell how many type args are captured vs. provided by the caller of the |
| + // closure. |
| + |
| + intptr_t types_count = ReadListLength(); // read type count. |
| + if (types_count > 0) { |
| + instructions += LoadLocal(context); |
| + |
| + const TypeArguments& type_args = |
| + T.BuildTypeArguments(types_count); // read list of type arguments. |
| + instructions += TranslateInstantiatedTypeArguments(type_args); |
| + |
| + instructions += StoreInstanceField(TokenPosition::kNoSource, |
| + Context::variable_offset(0)); |
| + } |
| return instructions; |
| } |