Use a loop in generated code to allocate stack slots for function with many local...
authorfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 23 Dec 2009 15:06:21 +0000 (15:06 +0000)
committerfschneider@chromium.org <fschneider@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 23 Dec 2009 15:06:21 +0000 (15:06 +0000)
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
src/arm/virtual-frame-arm.h
src/ia32/virtual-frame-ia32.cc
src/ia32/virtual-frame-ia32.h
src/x64/virtual-frame-x64.cc
src/x64/virtual-frame-x64.h

index e8403f7..a33ebd4 100644 (file)
@@ -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
index 39be1bc..b2f0eea 100644 (file)
@@ -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();
 
index ba64886..104d187 100644 (file)
@@ -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());
     }
   }
 }
index 6c6b481..1383e2a 100644 (file)
@@ -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();
 
index fe65d34..6e84ed1 100644 (file)
@@ -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);
     }
   }
 }
index e492305..88cf2bc 100644 (file)
@@ -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();