Index: runtime/vm/stub_code_ia32.cc |
=================================================================== |
--- runtime/vm/stub_code_ia32.cc (revision 403) |
+++ runtime/vm/stub_code_ia32.cc (working copy) |
@@ -1242,12 +1242,12 @@ |
// Called for inline allocation of closures. |
// Input parameters: |
-// ESP + 4 : receiver (only if non-static implicit closure). |
+// ESP + 8 : receiver (only if implicit instance closure). |
+// ESP + 4 : type arguments object (only if signature class is parameterized). |
// ESP : points to return address. |
siva
2011/10/13 20:52:21
if signature class is not parameterized ESP + 4 w
regis
2011/10/13 21:33:46
Done.
|
// 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 +1255,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 +1330,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 +1351,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 +1362,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 { |
+ __ PushObject(TypeArguments::ZoneHandle()); // Push null type arguments. |
siva
2011/10/13 20:52:21
why not use pushl(raw_null) here?
regis
2011/10/13 21:33:46
Done here and at some other locations.
|
+ } |
if (is_implicit_static_closure) { |
__ CallRuntimeFromStub(kAllocateImplicitStaticClosureRuntimeEntry); |
} else if (is_implicit_instance_closure) { |
@@ -1357,6 +1377,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 +1414,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. |