From f7ef8800419253dd934ae6fb5108fed1c6f94abe Mon Sep 17 00:00:00 2001 From: "fschneider@chromium.org" Date: Wed, 23 Dec 2009 15:06:21 +0000 Subject: [PATCH] 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 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3521 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/virtual-frame-arm.cc | 23 ++++++++++++++++++----- src/arm/virtual-frame-arm.h | 3 +++ src/ia32/virtual-frame-ia32.cc | 28 ++++++++++++++++++++++++---- src/ia32/virtual-frame-ia32.h | 3 +++ src/x64/virtual-frame-x64.cc | 22 ++++++++++++++++++++-- src/x64/virtual-frame-x64.h | 3 +++ 6 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc index e8403f7..a33ebd4 100644 --- a/src/arm/virtual-frame-arm.cc +++ b/src/arm/virtual-frame-arm.cc @@ -143,12 +143,25 @@ void VirtualFrame::AllocateStackSlots() { 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 diff --git a/src/arm/virtual-frame-arm.h b/src/arm/virtual-frame-arm.h index 39be1bc..b2f0eea 100644 --- a/src/arm/virtual-frame-arm.h +++ b/src/arm/virtual-frame-arm.h @@ -180,6 +180,9 @@ class VirtualFrame : public ZoneObject { // 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(); diff --git a/src/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc index ba64886..104d187 100644 --- a/src/ia32/virtual-frame-ia32.cc +++ b/src/ia32/virtual-frame-ia32.cc @@ -513,13 +513,33 @@ void VirtualFrame::AllocateStackSlots() { Handle 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()); } } } diff --git a/src/ia32/virtual-frame-ia32.h b/src/ia32/virtual-frame-ia32.h index 6c6b481..1383e2a 100644 --- a/src/ia32/virtual-frame-ia32.h +++ b/src/ia32/virtual-frame-ia32.h @@ -199,6 +199,9 @@ class VirtualFrame: public ZoneObject { // 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(); diff --git a/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc index fe65d34..6e84ed1 100644 --- a/src/x64/virtual-frame-x64.cc +++ b/src/x64/virtual-frame-x64.cc @@ -129,11 +129,29 @@ void VirtualFrame::AllocateStackSlots() { Handle 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); } } } diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h index e492305..88cf2bca 100644 --- a/src/x64/virtual-frame-x64.h +++ b/src/x64/virtual-frame-x64.h @@ -200,6 +200,9 @@ class VirtualFrame : public ZoneObject { // 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(); -- 2.7.4