Chromium Code Reviews| Index: runtime/vm/stub_code_ia32.cc |
| =================================================================== |
| --- runtime/vm/stub_code_ia32.cc (revision 348) |
| +++ runtime/vm/stub_code_ia32.cc (working copy) |
| @@ -1240,20 +1240,37 @@ |
| } |
| -static void ClosureAllocationStub(Assembler* assembler, |
| - const Function& func, |
| - bool is_static_implicit_closure) { |
| +// Called for inline allocation of closures. |
| +// Input parameters: |
| +// ESP + 4 : receiver (only if non-static implicit closure). |
| +// 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())); |
| - intptr_t instance_size = Closure::InstanceSize(); |
| - if (FLAG_inline_alloc && PageSpace::IsPageAllocatableSize(instance_size)) { |
| + ASSERT(func.IsClosureFunction()); |
| + const bool is_static_implicit_closure = |
| + func.IsImplicitClosureFunction() && func.is_static(); |
| + const bool is_implicit_closure = |
| + func.IsImplicitClosureFunction() && !func.is_static(); |
| + 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())); |
| - __ leal(EBX, Address(EAX, instance_size)); |
| + __ leal(EBX, Address(EAX, closure_size)); |
| + if (is_implicit_closure) { |
| + __ movl(ECX, EBX); // ECX: new context address. |
| + __ addl(EBX, Immediate(context_size)); |
| + } |
| // Check if the allocation fits into the remaining space. |
| - // EAX: potential new object. |
| + // EAX: potential new closure object. |
| + // ECX: potential new context object (only if is_implicit_closure). |
| // EBX: potential next object start. |
| __ cmpl(EBX, Address::Absolute(heap->EndAddress())); |
| __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump); |
| @@ -1263,16 +1280,17 @@ |
| __ movl(Address::Absolute(heap->TopAddress()), EBX); |
| // Initialize the class field in the object. |
| - // EAX: new object. |
| - // EBX: next object start. |
| - __ LoadObject(ECX, cls); // Load signature class of closure. |
| - __ movl(Address(EAX, Closure::class_offset()), ECX); |
| + // EAX: new closure object. |
| + // ECX: new context object (only if is_implicit_closure). |
| + __ LoadObject(EDX, cls); // Load signature class of closure. |
| + __ movl(Address(EAX, Closure::class_offset()), EDX); |
| // Initialize the function field in the object. |
| - // EAX: new object. |
| + // EAX: new closure object. |
| + // ECX: new context object (only if is_implicit_closure). |
| // EBX: next object start. |
| - __ LoadObject(ECX, func); // Load function of closure to be allocated. |
| - __ movl(Address(EAX, Closure::function_offset()), ECX); |
| + __ LoadObject(EDX, func); // Load function of closure to be allocated. |
| + __ movl(Address(EAX, Closure::function_offset()), EDX); |
| // Setup the context for this closure. |
| if (is_static_implicit_closure) { |
| @@ -1280,7 +1298,31 @@ |
| ASSERT(object_store != NULL); |
| const Context& empty_context = |
| Context::ZoneHandle(object_store->empty_context()); |
| - __ LoadObject(ECX, empty_context); |
| + __ LoadObject(EDX, empty_context); |
| + __ movl(Address(EAX, Closure::context_offset()), EDX); |
| + } else if (is_implicit_closure) { |
| + // Initialize the new context capturing the receiver. |
| + |
| + // Set the class field to the Context class. |
| + __ LoadObject(EBX, Class::ZoneHandle(Object::context_class())); |
| + __ movl(Address(ECX, Context::class_offset()), EBX); |
| + |
| + // Set number of variables field to 1 (for captured receiver). |
| + __ movl(Address(ECX, Context::num_variables_offset()), Immediate(1)); |
| + |
| + // Set isolate field to isolate of current context. |
| + __ movl(EDX, FieldAddress(CTX, Context::isolate_offset())); |
| + __ movl(Address(ECX, Context::isolate_offset()), EDX); |
| + |
| + // Set the parent field to null. |
| + __ movl(Address(ECX, Context::parent_offset()), raw_null); |
| + |
| + // Initialize the context variable to the receiver. |
| + __ movl(EDX, Address(ESP, kReceiverOffset)); |
| + __ movl(Address(ECX, Context::variable_offset(0)), EDX); |
| + |
| + // Set the newly allocated context in the newly allocated closure. |
| + __ addl(ECX, Immediate(kHeapObjectTag)); |
| __ movl(Address(EAX, Closure::context_offset()), ECX); |
| } else { |
|
siva
2011/10/11 21:00:46
add a comment // Regular closure.
regis
2011/10/11 23:40:19
Added ASSERT.
|
| __ movl(Address(EAX, Closure::context_offset()), CTX); |
| @@ -1297,6 +1339,9 @@ |
| __ Bind(&slow_case); |
| } |
| + if (is_implicit_closure) { |
| + __ movl(EAX, Address(ESP, kReceiverOffset)); |
| + } |
| // Create a stub frame. |
| __ EnterFrame(0); |
| const Closure& new_closure = Closure::ZoneHandle(); |
| @@ -1304,6 +1349,10 @@ |
| __ PushObject(func); |
| if (is_static_implicit_closure) { |
| __ CallRuntimeFromStub(kAllocateStaticImplicitClosureRuntimeEntry); |
| + } else if (is_implicit_closure) { |
| + __ pushl(EAX); // Receiver. |
| + __ CallRuntimeFromStub(kAllocateImplicitClosureRuntimeEntry); |
| + __ popl(EAX); // Pop receiver. |
| } else { |
| __ CallRuntimeFromStub(kAllocateClosureRuntimeEntry); |
| } |
| @@ -1316,26 +1365,6 @@ |
| } |
| -// Called for inline allocation of closures. |
| -// Input parameters: |
| -// Uses EAX, EBX, ECX as temporary registers. |
| -void StubCode::GenerateAllocationStubForClosure(Assembler* assembler, |
| - const Function& func) { |
| - static const bool kIsNotStaticImplicitClosure = false; |
| - ClosureAllocationStub(assembler, func, kIsNotStaticImplicitClosure); |
| -} |
| - |
| - |
| -// Called for inline allocation of implicit closures. |
| -// Input parameters: |
| -// Uses EAX, EBX, ECX as temporary registers. |
| -void StubCode::GenerateAllocationStubForStaticImplicitClosure( |
| - Assembler* assembler, const Function& func) { |
| - static const bool kIsStaticImplicitClosure = true; |
| - ClosureAllocationStub(assembler, func, kIsStaticImplicitClosure); |
| -} |
| - |
| - |
| // Called for invoking noSuchMethod function from the entry code of a dart |
| // function after an error in passed named arguments is detected. |
| // Input parameters: |