| Index: runtime/vm/flow_graph_compiler_x64.cc
|
| diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
|
| index fa6cd0761fe5c3d0386cfc68e2c9c798cdf596b9..b75a1ae17cf285f62abe2545dae0721d51dab88b 100644
|
| --- a/runtime/vm/flow_graph_compiler_x64.cc
|
| +++ b/runtime/vm/flow_graph_compiler_x64.cc
|
| @@ -1085,16 +1085,39 @@ void FlowGraphCompiler::CompileGraph() {
|
| }
|
| }
|
|
|
| - if (FLAG_reify_generic_functions) {
|
| - // TODO(regis): Check function type arguments of a generic function.
|
| - // For now, verify that a local variable has been allocated when necessary.
|
| - ASSERT((function.NumTypeParameters() == 0) ||
|
| - (parsed_function().function_type_arguments() != NULL));
|
| - // TODO(regis): Allocate and prepend parent type arguments when necessary.
|
| - ASSERT(!function.HasGenericParent() ||
|
| - (parsed_function().parent_type_arguments() != NULL));
|
| + // Check for a passed type argument vector if the function is generic.
|
| + if (FLAG_reify_generic_functions && function.IsGeneric()) {
|
| + __ Comment("Check passed-in type args");
|
| + Label store_type_args, ok;
|
| + __ cmpq(FieldAddress(R10, ArgumentsDescriptor::type_args_len_offset()),
|
| + Immediate(0));
|
| + if (is_optimizing()) {
|
| + // Initialize type_args to null if none passed in.
|
| + __ LoadObject(RAX, Object::null_object());
|
| + __ j(EQUAL, &store_type_args, Assembler::kNearJump);
|
| + } else {
|
| + __ j(EQUAL, &ok, Assembler::kNearJump); // Already initialized to null.
|
| + }
|
| + // TODO(regis): Verify that type_args_len is correct.
|
| + // Load the passed type args vector in RAX from
|
| + // fp[kParamEndSlotFromFp + num_args + 1]; num_args (RBX) is Smi.
|
| + __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
|
| + __ movq(RAX,
|
| + Address(RBP, RBX, TIMES_4, (kParamEndSlotFromFp + 1) * kWordSize));
|
| + // Store RAX into the stack slot reserved for the function type arguments.
|
| + // If the function type arguments variable is captured, a copy will happen
|
| + // after the context is allocated.
|
| + const intptr_t slot_base = parsed_function().first_stack_local_index();
|
| + ASSERT(parsed_function().function_type_arguments()->is_captured() ||
|
| + parsed_function().function_type_arguments()->index() == slot_base);
|
| + __ Bind(&store_type_args);
|
| + __ movq(Address(RBP, slot_base * kWordSize), RAX);
|
| + __ Bind(&ok);
|
| }
|
|
|
| + // TODO(regis): Verify that no vector is passed if not generic, unless already
|
| + // checked during resolution.
|
| +
|
| EndCodeSourceRange(TokenPosition::kDartCodePrologue);
|
| ASSERT(!block_order().is_empty());
|
| VisitBlocks();
|
| @@ -1338,7 +1361,8 @@ void FlowGraphCompiler::EmitOptimizedStaticCall(
|
| TokenPosition token_pos,
|
| LocationSummary* locs) {
|
| ASSERT(!function.IsClosureFunction());
|
| - if (function.HasOptionalParameters()) {
|
| + if (function.HasOptionalParameters() ||
|
| + (FLAG_reify_generic_functions && function.IsGeneric())) {
|
| __ LoadObject(R10, arguments_descriptor);
|
| } else {
|
| __ xorq(R10, R10); // GC safe smi zero because of stub.
|
|
|