Revision: 3521
Author: [email protected]
Date: Wed Dec 23 07:06:21 2009
Log: 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
http://code.google.com/p/v8/source/detail?r=3521

Modified:
  /branches/bleeding_edge/src/arm/virtual-frame-arm.cc
  /branches/bleeding_edge/src/arm/virtual-frame-arm.h
  /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc
  /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h
  /branches/bleeding_edge/src/x64/virtual-frame-x64.cc
  /branches/bleeding_edge/src/x64/virtual-frame-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/virtual-frame-arm.cc        Tue Dec 22  
04:41:45 2009
+++ /branches/bleeding_edge/src/arm/virtual-frame-arm.cc        Wed Dec 23  
07:06:21 2009
@@ -143,12 +143,25 @@
    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
=======================================
--- /branches/bleeding_edge/src/arm/virtual-frame-arm.h Tue Dec 22 04:41:45  
2009
+++ /branches/bleeding_edge/src/arm/virtual-frame-arm.h Wed Dec 23 07:06:21  
2009
@@ -180,6 +180,9 @@
    // 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();

=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc      Thu Dec 17  
02:23:20 2009
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.cc      Wed Dec 23  
07:06:21 2009
@@ -513,13 +513,33 @@
      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());
      }
    }
  }
=======================================
--- /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h       Thu Dec 17  
02:23:20 2009
+++ /branches/bleeding_edge/src/ia32/virtual-frame-ia32.h       Wed Dec 23  
07:06:21 2009
@@ -199,6 +199,9 @@
    // 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();

=======================================
--- /branches/bleeding_edge/src/x64/virtual-frame-x64.cc        Tue Nov 10  
06:58:16 2009
+++ /branches/bleeding_edge/src/x64/virtual-frame-x64.cc        Wed Dec 23  
07:06:21 2009
@@ -129,11 +129,29 @@
      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);
      }
    }
  }
=======================================
--- /branches/bleeding_edge/src/x64/virtual-frame-x64.h Thu Oct  8 05:36:12  
2009
+++ /branches/bleeding_edge/src/x64/virtual-frame-x64.h Wed Dec 23 07:06:21  
2009
@@ -200,6 +200,9 @@
    // 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();

-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to