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
parent c3fa79ab
...@@ -143,12 +143,25 @@ void VirtualFrame::AllocateStackSlots() { ...@@ -143,12 +143,25 @@ void VirtualFrame::AllocateStackSlots() {
if (count > 0) { if (count > 0) {
Comment cmnt(masm(), "[ Allocate space for locals"); Comment cmnt(masm(), "[ Allocate space for locals");
Adjust(count); Adjust(count);
// Initialize stack slots with 'undefined' value. // Initialize stack slots with 'undefined' value.
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex); __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
} __ LoadRoot(r2, Heap::kStackLimitRootIndex);
__ LoadRoot(r2, Heap::kStackLimitRootIndex); if (count < kLocalVarBound) {
for (int i = 0; i < count; i++) { // For less locals the unrolled loop is more compact.
__ push(ip); 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. // Check the stack for overflow or a break request.
// Put the lr setup instruction in the delay slot. The kInstrSize is added // Put the lr setup instruction in the delay slot. The kInstrSize is added
......
...@@ -180,6 +180,9 @@ class VirtualFrame : public ZoneObject { ...@@ -180,6 +180,9 @@ class VirtualFrame : public ZoneObject {
// shared return site. Emits code for spills. // shared return site. Emits code for spills.
void PrepareForReturn(); 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. // Allocate and initialize the frame-allocated locals.
void AllocateStackSlots(); void AllocateStackSlots();
......
...@@ -513,13 +513,33 @@ void VirtualFrame::AllocateStackSlots() { ...@@ -513,13 +513,33 @@ void VirtualFrame::AllocateStackSlots() {
Handle<Object> undefined = Factory::undefined_value(); Handle<Object> undefined = Factory::undefined_value();
FrameElement initial_value = FrameElement initial_value =
FrameElement::ConstantElement(undefined, FrameElement::SYNCED); FrameElement::ConstantElement(undefined, FrameElement::SYNCED);
Result temp = cgen()->allocator()->Allocate(); if (count == 1) {
ASSERT(temp.is_valid()); __ push(Immediate(undefined));
__ Set(temp.reg(), 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++) { for (int i = 0; i < count; i++) {
elements_.Add(initial_value); elements_.Add(initial_value);
stack_pointer_++; stack_pointer_++;
__ push(temp.reg());
} }
} }
} }
......
...@@ -199,6 +199,9 @@ class VirtualFrame: public ZoneObject { ...@@ -199,6 +199,9 @@ class VirtualFrame: public ZoneObject {
// shared return site. Emits code for spills. // shared return site. Emits code for spills.
void PrepareForReturn(); 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. // Allocate and initialize the frame-allocated locals.
void AllocateStackSlots(); void AllocateStackSlots();
......
...@@ -129,11 +129,29 @@ void VirtualFrame::AllocateStackSlots() { ...@@ -129,11 +129,29 @@ void VirtualFrame::AllocateStackSlots() {
Handle<Object> undefined = Factory::undefined_value(); Handle<Object> undefined = Factory::undefined_value();
FrameElement initial_value = FrameElement initial_value =
FrameElement::ConstantElement(undefined, FrameElement::SYNCED); 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++) { for (int i = 0; i < count; i++) {
elements_.Add(initial_value); elements_.Add(initial_value);
stack_pointer_++; stack_pointer_++;
__ push(kScratchRegister);
} }
} }
} }
......
...@@ -200,6 +200,9 @@ class VirtualFrame : public ZoneObject { ...@@ -200,6 +200,9 @@ class VirtualFrame : public ZoneObject {
// shared return site. Emits code for spills. // shared return site. Emits code for spills.
void PrepareForReturn(); 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. // Allocate and initialize the frame-allocated locals.
void AllocateStackSlots(); void AllocateStackSlots();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment