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
// 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();
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());
}
}
}
// 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();
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);
}
}
}
// 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();