Revision: 3521 Author: [email protected] Date: Wed Dec 23 07:06:21 2009 Log: Use a loop in generated code to allocate stack slots for function with many local variables.
If a function contains more than a certain number of locals (IA32: 9, X64: 6, ARM: 4) a loop for initializing the locals with 'undefined' is more compact. For less locals we unroll that loop by emitting a sequence of push instructions. Review URL: http://codereview.chromium.org/515012 http://code.google.com/p/v8/source/detail?r=3521 Modified: /branches/bleeding_edge/src/arm/virtual-frame-arm.cc /branches/bleeding_edge/src/arm/virtual-frame-arm.h /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h /branches/bleeding_edge/src/x64/virtual-frame-x64.cc /branches/bleeding_edge/src/x64/virtual-frame-x64.h ======================================= --- /branches/bleeding_edge/src/arm/virtual-frame-arm.cc Tue Dec 22 04:41:45 2009 +++ /branches/bleeding_edge/src/arm/virtual-frame-arm.cc Wed Dec 23 07:06:21 2009 @@ -143,12 +143,25 @@ if (count > 0) { Comment cmnt(masm(), "[ Allocate space for locals"); Adjust(count); - // Initialize stack slots with 'undefined' value. + // Initialize stack slots with 'undefined' value. __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); - } - __ LoadRoot(r2, Heap::kStackLimitRootIndex); - for (int i = 0; i < count; i++) { - __ push(ip); + __ LoadRoot(r2, Heap::kStackLimitRootIndex); + if (count < kLocalVarBound) { + // For less locals the unrolled loop is more compact. + for (int i = 0; i < count; i++) { + __ push(ip); + } + } else { + // For more locals a loop in generated code is more compact. + Label alloc_locals_loop; + __ mov(r1, Operand(count)); + __ bind(&alloc_locals_loop); + __ push(ip); + __ sub(r1, r1, Operand(1), SetCC); + __ b(ne, &alloc_locals_loop); + } + } else { + __ LoadRoot(r2, Heap::kStackLimitRootIndex); } // Check the stack for overflow or a break request. // Put the lr setup instruction in the delay slot. The kInstrSize is added ======================================= --- /branches/bleeding_edge/src/arm/virtual-frame-arm.h Tue Dec 22 04:41:45 2009 +++ /branches/bleeding_edge/src/arm/virtual-frame-arm.h Wed Dec 23 07:06:21 2009 @@ -180,6 +180,9 @@ // shared return site. Emits code for spills. void PrepareForReturn(); + // Number of local variables after when we use a loop for allocating. + static const int kLocalVarBound = 5; + // Allocate and initialize the frame-allocated locals. void AllocateStackSlots(); ======================================= --- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Thu Dec 17 02:23:20 2009 +++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc Wed Dec 23 07:06:21 2009 @@ -513,13 +513,33 @@ Handle<Object> undefined = Factory::undefined_value(); FrameElement initial_value = FrameElement::ConstantElement(undefined, FrameElement::SYNCED); - Result temp = cgen()->allocator()->Allocate(); - ASSERT(temp.is_valid()); - __ Set(temp.reg(), Immediate(undefined)); + if (count == 1) { + __ push(Immediate(undefined)); + } else if (count < kLocalVarBound) { + // For less locals the unrolled loop is more compact. + Result temp = cgen()->allocator()->Allocate(); + ASSERT(temp.is_valid()); + __ Set(temp.reg(), Immediate(undefined)); + for (int i = 0; i < count; i++) { + __ push(temp.reg()); + } + } else { + // For more locals a loop in generated code is more compact. + Label alloc_locals_loop; + Result cnt = cgen()->allocator()->Allocate(); + Result tmp = cgen()->allocator()->Allocate(); + ASSERT(cnt.is_valid()); + ASSERT(tmp.is_valid()); + __ mov(cnt.reg(), Immediate(count)); + __ mov(tmp.reg(), Immediate(undefined)); + __ bind(&alloc_locals_loop); + __ push(tmp.reg()); + __ dec(cnt.reg()); + __ j(not_zero, &alloc_locals_loop); + } for (int i = 0; i < count; i++) { elements_.Add(initial_value); stack_pointer_++; - __ push(temp.reg()); } } } ======================================= --- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Thu Dec 17 02:23:20 2009 +++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h Wed Dec 23 07:06:21 2009 @@ -199,6 +199,9 @@ // shared return site. Emits code for spills. void PrepareForReturn(); + // Number of local variables after when we use a loop for allocating. + static const int kLocalVarBound = 10; + // Allocate and initialize the frame-allocated locals. void AllocateStackSlots(); ======================================= --- /branches/bleeding_edge/src/x64/virtual-frame-x64.cc Tue Nov 10 06:58:16 2009 +++ /branches/bleeding_edge/src/x64/virtual-frame-x64.cc Wed Dec 23 07:06:21 2009 @@ -129,11 +129,29 @@ Handle<Object> undefined = Factory::undefined_value(); FrameElement initial_value = FrameElement::ConstantElement(undefined, FrameElement::SYNCED); - __ movq(kScratchRegister, undefined, RelocInfo::EMBEDDED_OBJECT); + if (count == 1) { + __ Push(undefined); + } else if (count < kLocalVarBound) { + // For less locals the unrolled loop is more compact. + __ movq(kScratchRegister, undefined, RelocInfo::EMBEDDED_OBJECT); + for (int i = 0; i < count; i++) { + __ push(kScratchRegister); + } + } else { + // For more locals a loop in generated code is more compact. + Label alloc_locals_loop; + Result cnt = cgen()->allocator()->Allocate(); + ASSERT(cnt.is_valid()); + __ movq(cnt.reg(), Immediate(count)); + __ movq(kScratchRegister, undefined, RelocInfo::EMBEDDED_OBJECT); + __ bind(&alloc_locals_loop); + __ push(kScratchRegister); + __ decl(cnt.reg()); + __ j(not_zero, &alloc_locals_loop); + } for (int i = 0; i < count; i++) { elements_.Add(initial_value); stack_pointer_++; - __ push(kScratchRegister); } } } ======================================= --- /branches/bleeding_edge/src/x64/virtual-frame-x64.h Thu Oct 8 05:36:12 2009 +++ /branches/bleeding_edge/src/x64/virtual-frame-x64.h Wed Dec 23 07:06:21 2009 @@ -200,6 +200,9 @@ // shared return site. Emits code for spills. void PrepareForReturn(); + // Number of local variables after when we use a loop for allocating. + static const int kLocalVarBound = 7; + // Allocate and initialize the frame-allocated locals. void AllocateStackSlots(); -- v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev
