Index: runtime/vm/kernel_binary_flowgraph.cc |
diff --git a/runtime/vm/kernel_binary_flowgraph.cc b/runtime/vm/kernel_binary_flowgraph.cc |
index 0ac620dbefe7e43a9048f9d3b935187d41a2725e..2dae760b556adedd47a004042b5b615e20a26ce0 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(30455): 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; |
@@ -2986,11 +2990,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()); |
+ // TODO(30455): Kernel generic methods undone. Since the frontend can't yet |
+ // emit 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); |
@@ -3004,6 +3018,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. |
@@ -3036,12 +3059,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) |
@@ -4469,9 +4495,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( |
@@ -5890,8 +5917,25 @@ Fragment StreamingFlowGraphBuilder::BuildClosureCreation( |
instructions += Drop(); |
- SkipDartType(); // skip function type of the closure. |
- SkipListOfDartTypes(); // skip list of type arguments. |
+ SkipDartType(); // skip function type of the closure. |
+ |
+ // TODO(30455): 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; |
} |