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. |