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 3f0d127a76aee16c8a0f227c19cfcb577102f01c..e08d786853e53541d7a1ae60f17dcf57cca02f8c 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" |
| @@ -1094,9 +1093,15 @@ 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()) { |
| + // 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
|
| + // 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()); |
| } |
| @@ -1626,13 +1631,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; |
| @@ -2949,11 +2954,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 |
|
jensj
2017/08/11 06:24:54
ditto
sjindel
2017/08/14 11:05:49
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); |
| @@ -2966,6 +2981,15 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfConvertedClosureFunction( |
| // to that function as the first parameter. |
| body += LoadLocal(LookupVariable(ReaderOffset())); // 0th variable offset. |
| body += flow_graph_builder_->LoadField(Closure::context_offset()); |
| + LocalVariable* context = MakeTemporary(); |
| + |
| + 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
|
| + body += LoadLocal(context); |
| + body += flow_graph_builder_->LoadField(Context::variable_offset(0)); |
| + body += PushArgument(); |
| + } |
| + |
| + body += LoadLocal(context); |
| body += PushArgument(); |
| SkipVariableDeclaration(); // read 0th variable. |
| @@ -2994,11 +3018,14 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfConvertedClosureFunction( |
| // Forward them to the target. |
| const intptr_t argument_count = |
| - positional_argument_count + named_argument_count; |
| + 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
|
| 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) |
| @@ -4404,9 +4431,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( |
| @@ -5825,9 +5853,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. |
| + |
| + // KERNEL_GENERIC_METHODS_UNDONE(sjindel): When generic methods are fully |
|
jensj
2017/08/11 06:24:54
todo?
|
| + // 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; |
| } |