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() {
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
......
......@@ -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();
......
......@@ -513,13 +513,33 @@ void VirtualFrame::AllocateStackSlots() {
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());
}
}
}
......
......@@ -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();
......
......@@ -129,11 +129,29 @@ void VirtualFrame::AllocateStackSlots() {
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);
}
}
}
......
......@@ -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();
......
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