Index: runtime/vm/stub_code_ia32.cc |
=================================================================== |
--- runtime/vm/stub_code_ia32.cc (revision 415) |
+++ runtime/vm/stub_code_ia32.cc (working copy) |
@@ -1067,6 +1067,8 @@ |
const Class& cls) { |
const intptr_t kObjectTypeArgumentsOffset = 2 * kWordSize; |
const intptr_t kInstantiatorTypeArgumentsOffset = 1 * kWordSize; |
+ const Immediate raw_null = |
+ Immediate(reinterpret_cast<intptr_t>(Object::null())); |
// The generated code is different if the class is parameterized. |
const bool is_cls_parameterized = |
cls.type_arguments_instance_field_offset() != Class::kNoTypeArguments; |
@@ -1088,8 +1090,6 @@ |
// A new InstantiatedTypeArguments object only needs to be allocated if |
// the instantiator is non-null. |
Label null_instantiator; |
- const Immediate raw_null = |
- Immediate(reinterpret_cast<intptr_t>(Object::null())); |
__ cmpl(Address(ESP, kInstantiatorTypeArgumentsOffset), raw_null); |
__ j(EQUAL, &null_instantiator, Assembler::kNearJump); |
__ addl(EBX, Immediate(type_args_size)); |
@@ -1225,8 +1225,8 @@ |
__ pushl(EAX); // Push type arguments of object to be allocated. |
__ pushl(EDX); // Push type arguments of instantiator. |
} else { |
- __ PushObject(TypeArguments::ZoneHandle()); // Push null type arguments. |
- __ PushObject(TypeArguments::ZoneHandle()); // Push null instantiator. |
+ __ pushl(raw_null); // Push null type arguments. |
+ __ pushl(raw_null); // Push null instantiator. |
} |
__ CallRuntimeFromStub(kAllocateObjectRuntimeEntry); // Allocate object. |
__ popl(EAX); // Pop argument (instantiator). |
@@ -1242,12 +1242,14 @@ |
// Called for inline allocation of closures. |
// Input parameters: |
-// ESP + 4 : receiver (only if non-static implicit closure). |
+// If the signature class is not parameterized, the receiver, if any, will be |
+// at ESP + 4 instead of ESP + 8, since no type arguments are passed. |
+// ESP + 8 (or ESP + 4): receiver (only if implicit instance closure). |
+// ESP + 4 : type arguments object (only if signature class is parameterized). |
// ESP : points to return address. |
// Uses EAX, EBX, ECX, EDX as temporary registers. |
void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
const Function& func) { |
- const intptr_t kReceiverOffset = 1 * kWordSize; |
const Immediate raw_null = |
Immediate(reinterpret_cast<intptr_t>(Object::null())); |
ASSERT(func.IsClosureFunction()); |
@@ -1255,11 +1257,14 @@ |
func.IsImplicitStaticClosureFunction(); |
const bool is_implicit_instance_closure = |
func.IsImplicitInstanceClosureFunction(); |
+ const Class& cls = Class::ZoneHandle(func.signature_class()); |
+ const bool is_cls_parameterized = cls.IsParameterized(); |
+ const intptr_t kTypeArgumentsOffset = 1 * kWordSize; |
+ const intptr_t kReceiverOffset = (is_cls_parameterized ? 2 : 1) * kWordSize; |
const intptr_t closure_size = Closure::InstanceSize(); |
const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. |
if (FLAG_inline_alloc && |
PageSpace::IsPageAllocatableSize(closure_size + context_size)) { |
- const Class& cls = Class::ZoneHandle(func.signature_class()); |
Label slow_case; |
Heap* heap = Isolate::Current()->heap(); |
__ movl(EAX, Address::Absolute(heap->TopAddress())); |
@@ -1327,11 +1332,20 @@ |
} else { |
__ movl(Address(EAX, Closure::context_offset()), CTX); |
} |
+ |
+ // Set the type arguments field in the newly allocated closure. |
+ if (is_cls_parameterized) { |
+ ASSERT(!is_implicit_static_closure); |
+ // Use the passed-in type arguments. |
+ __ movl(EDX, Address(ESP, kTypeArgumentsOffset)); |
+ __ movl(Address(EAX, Closure::type_arguments_offset()), EDX); |
+ } else { |
+ // Set to null. |
+ __ movl(Address(EAX, Closure::type_arguments_offset()), raw_null); |
+ } |
+ |
__ movl(Address(EAX, Closure::smrck_offset()), raw_null); |
- // TODO(regis): Store the actual type arguments. |
- __ movl(Address(EAX, Closure::type_arguments_offset()), raw_null); |
- |
// Done allocating and initializing the instance. |
// EAX: new object. |
__ addl(EAX, Immediate(kHeapObjectTag)); |
@@ -1339,6 +1353,9 @@ |
__ Bind(&slow_case); |
} |
+ if (is_cls_parameterized) { |
+ __ movl(ECX, Address(ESP, kTypeArgumentsOffset)); |
+ } |
if (is_implicit_instance_closure) { |
__ movl(EAX, Address(ESP, kReceiverOffset)); |
} |
@@ -1347,6 +1364,11 @@ |
const Closure& new_closure = Closure::ZoneHandle(); |
__ PushObject(new_closure); // Push Null closure for return value. |
__ PushObject(func); |
+ if (is_cls_parameterized) { |
+ __ pushl(ECX); // Push type arguments of closure to be allocated. |
+ } else { |
+ __ pushl(raw_null); // Push null type arguments. |
+ } |
if (is_implicit_static_closure) { |
__ CallRuntimeFromStub(kAllocateImplicitStaticClosureRuntimeEntry); |
} else if (is_implicit_instance_closure) { |
@@ -1357,6 +1379,7 @@ |
ASSERT(func.IsNonImplicitClosureFunction()); |
__ CallRuntimeFromStub(kAllocateClosureRuntimeEntry); |
} |
+ __ popl(EAX); // Pop argument (type arguments of object). |
__ popl(EAX); // Pop function object. |
__ popl(EAX); |
// EAX: new object |
@@ -1393,7 +1416,6 @@ |
__ EnterFrame(0); |
// Setup space for return value on stack by pushing smi 0. |
- // TODO(regis): Why are we using smi 0 instead of raw_null in stubs? |
__ pushl(Immediate(0)); // Result from noSuchMethod. |
__ pushl(EAX); // Receiver. |
__ pushl(ECX); // Function name. |