Chromium Code Reviews| Index: runtime/vm/code_generator_ia32.cc |
| =================================================================== |
| --- runtime/vm/code_generator_ia32.cc (revision 403) |
| +++ runtime/vm/code_generator_ia32.cc (working copy) |
| @@ -854,10 +854,21 @@ |
| ASSERT(!function.HasCode()); |
| ASSERT(function.context_scope() == ContextScope::null()); |
| function.set_context_scope(context_scope); |
| + // The function type of a closure may be parameterized. In that case, pass |
| + // the type arguments of the instantiator. |
| + const Class& cls = Class::Handle(function.signature_class()); |
| + ASSERT(!cls.IsNull()); |
| + const bool is_cls_parameterized = cls.IsParameterized(); |
| + if (is_cls_parameterized) { |
| + GenerateInstantiatorTypeArguments(); |
| + } |
| const Code& stub = Code::Handle( |
| StubCode::GetAllocationStubForClosure(function)); |
| const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| GenerateCall(node->token_index(), &label); |
| + if (is_cls_parameterized) { |
| + __ popl(ECX); // Pop type arguments. |
| + } |
| if (IsResultNeeded(node)) { |
| __ pushl(EAX); |
| } |
| @@ -885,10 +896,21 @@ |
| ASSERT(function.IsImplicitInstanceClosureFunction()); |
| ASSERT(function.context_scope() != ContextScope::null()); |
| node->receiver()->Visit(this); |
| + // The function type of a closure may be parameterized. In that case, pass |
| + // the type arguments of the instantiator. |
| + const Class& cls = Class::Handle(function.signature_class()); |
| + ASSERT(!cls.IsNull()); |
| + const bool is_cls_parameterized = cls.IsParameterized(); |
| + if (is_cls_parameterized) { |
| + GenerateInstantiatorTypeArguments(); |
| + } |
| const Code& stub = Code::Handle( |
| StubCode::GetAllocationStubForClosure(function)); |
| const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
| GenerateCall(node->token_index(), &label); |
| + if (is_cls_parameterized) { |
| + __ popl(ECX); // Pop type arguments. |
| + } |
| __ popl(ECX); // Pop receiver. |
|
siva
2011/10/13 20:52:21
The code for VisitClosureNode and VisitImplicitIns
regis
2011/10/13 21:33:46
I tried to factorize the visiting code of all 3 cl
|
| if (IsResultNeeded(node)) { |
| __ pushl(EAX); |
| @@ -1436,22 +1458,7 @@ |
| __ pushl(EAX); // Push the instance. |
| __ PushObject(type); // Push the type. |
| if (!type.IsInstantiated()) { |
| - ASSERT(parsed_function().instantiator() != NULL); |
| - parsed_function().instantiator()->Visit(this); // Instantiator on stack. |
| - if (!parsed_function().function().IsInFactoryScope()) { |
| - __ popl(EAX); // Pop instantiator. |
| - const Class& instantiator_class = |
| - Class::Handle(parsed_function().function().owner()); |
| - // The instantiator is the receiver of the caller, which is not a factory. |
| - // The receiver cannot be null; extract its TypeArguments object. |
| - // Note that in the factory case, the instantiator is the first parameter |
| - // of the factory, i.e. already a TypeArguments object. |
| - intptr_t type_arguments_instance_field_offset = |
| - instantiator_class.type_arguments_instance_field_offset(); |
| - ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| - __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); |
| - __ pushl(EAX); // Push instantiator. |
| - } |
| + GenerateInstantiatorTypeArguments(); |
| } else { |
| __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator. |
| } |
| @@ -1608,22 +1615,7 @@ |
| __ pushl(EAX); // Push the source object. |
| __ PushObject(dst_type); // Push the type of the destination. |
| if (!dst_type.IsInstantiated()) { |
| - ASSERT(parsed_function().instantiator() != NULL); |
| - parsed_function().instantiator()->Visit(this); // Instantiator on stack. |
| - if (!parsed_function().function().IsInFactoryScope()) { |
| - __ popl(EAX); // Pop instantiator. |
| - const Class& instantiator_class = |
| - Class::Handle(parsed_function().function().owner()); |
| - // The instantiator is the receiver of the caller, which is not a factory. |
| - // The receiver cannot be null; extract its TypeArguments object. |
| - // Note that in the factory case, the instantiator is the first parameter |
| - // of the factory, i.e. already a TypeArguments object. |
| - intptr_t type_arguments_instance_field_offset = |
| - instantiator_class.type_arguments_instance_field_offset(); |
| - ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| - __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); |
| - __ pushl(EAX); // Push instantiator. |
| - } |
| + GenerateInstantiatorTypeArguments(); |
| } else { |
| __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator. |
| } |
| @@ -2205,6 +2197,27 @@ |
| } |
| +// Pushes the type arguments of the instantiator on the stack. |
| +void CodeGenerator::GenerateInstantiatorTypeArguments() { |
| + ASSERT(parsed_function().instantiator() != NULL); |
| + parsed_function().instantiator()->Visit(this); |
| + if (!parsed_function().function().IsInFactoryScope()) { |
| + __ popl(EAX); // Pop instantiator. |
| + const Class& instantiator_class = |
| + Class::Handle(parsed_function().function().owner()); |
| + // The instantiator is the receiver of the caller, which is not a factory. |
| + // The receiver cannot be null; extract its TypeArguments object. |
| + // Note that in the factory case, the instantiator is the first parameter |
| + // of the factory, i.e. already a TypeArguments object. |
| + intptr_t type_arguments_instance_field_offset = |
| + instantiator_class.type_arguments_instance_field_offset(); |
| + ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| + __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); |
| + __ pushl(EAX); |
| + } |
| +} |
| + |
| + |
| // Pushes the type arguments on the stack in preparation of a constructor or |
| // factory call. |
| // For a factory call, instantiates (possibly requiring an additional run time |
| @@ -2232,22 +2245,9 @@ |
| } |
| } else { |
| // The type arguments are uninstantiated. |
| - ASSERT(parsed_function().instantiator() != NULL); |
| ASSERT(node->constructor().IsFactory() || is_cls_parameterized); |
| - parsed_function().instantiator()->Visit(this); |
| - __ popl(EAX); // Pop instantiator. |
| - if (!parsed_function().function().IsInFactoryScope()) { |
| - const Class& instantiator_class = |
| - Class::Handle(parsed_function().function().owner()); |
| - // The instantiator is the receiver of the caller, which is not a factory. |
| - // The receiver cannot be null; extract its TypeArguments object. |
| - // Note that in the factory case, the instantiator is the first parameter |
| - // of the factory, i.e. already a TypeArguments object. |
| - intptr_t type_arguments_instance_field_offset = |
| - instantiator_class.type_arguments_instance_field_offset(); |
| - ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| - __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); |
| - } |
| + GenerateInstantiatorTypeArguments(); |
| + __ popl(EAX); |
|
siva
2011/10/13 20:52:21
// Pop instantiator.
regis
2011/10/13 21:33:46
Done.
|
| // EAX is the instantiator TypeArguments object (or null). |
| // If EAX is null, no need to instantiate the type arguments, use null, and |
| // allocate an object of a raw type. |