Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(356)

Unified Diff: runtime/vm/code_generator_ia32.cc

Issue 8271008: Set type argument vector at run time in instantiated closure objects. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_generator_ia32.cc
===================================================================
--- runtime/vm/code_generator_ia32.cc (revision 415)
+++ runtime/vm/code_generator_ia32.cc (working copy)
@@ -845,6 +845,7 @@
}
+// TODO(regis): Consider merging all 3 closure node flavors into a single one.
void CodeGenerator::VisitClosureNode(ClosureNode* node) {
const int current_context_level = state()->context_level();
const ContextScope& context_scope = ContextScope::ZoneHandle(
@@ -854,10 +855,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 +897,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.
if (IsResultNeeded(node)) {
__ pushl(EAX);
@@ -1436,24 +1459,9 @@
__ 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.
+ __ pushl(raw_null); // Null instantiator.
}
GenerateCallRuntime(token_index, kInstanceofRuntimeEntry);
// Pop the two parameters supplied to the runtime entry. The result of the
@@ -1608,24 +1616,9 @@
__ 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.
+ __ pushl(raw_null); // Null instantiator.
}
__ PushObject(dst_name); // Push the name of the destination.
GenerateCallRuntime(token_index, kTypeCheckRuntimeEntry);
@@ -2205,6 +2198,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
@@ -2219,6 +2233,8 @@
// e.g. class A extends Array<int>.
void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node,
bool is_cls_parameterized) {
+ const Immediate raw_null =
+ Immediate(reinterpret_cast<intptr_t>(Object::null()));
// Instantiate the type arguments if necessary.
if (node->type_arguments().IsNull() ||
node->type_arguments().IsInstantiated()) {
@@ -2227,33 +2243,18 @@
__ PushObject(node->type_arguments());
if (!node->constructor().IsFactory()) {
// The allocator additionally requires the instantiator type arguments.
- __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator.
+ __ pushl(raw_null); // Null instantiator.
}
}
} else {
// The type arguments are uninstantiated.
- ASSERT(parsed_function().instantiator() != NULL);
ASSERT(node->constructor().IsFactory() || is_cls_parameterized);
- parsed_function().instantiator()->Visit(this);
+ GenerateInstantiatorTypeArguments();
__ 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));
- }
// 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.
Label type_arguments_instantiated, type_arguments_uninstantiated;
- const Immediate raw_null =
- Immediate(reinterpret_cast<intptr_t>(Object::null()));
__ cmpl(EAX, raw_null);
__ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
@@ -2294,7 +2295,7 @@
__ Bind(&type_arguments_instantiated);
__ pushl(EAX); // Instantiated type arguments.
- __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator.
+ __ pushl(raw_null); // Null instantiator.
__ Bind(&type_arguments_pushed);
}
}
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698