Fix a braino in the stack layout.

Also do some refactoring to have this code be just in CodeGenerator.

Change-Id: I88de109889138af8d60027973c12a64bee813cb7
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index b0e6a75..e0db0f1 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -38,7 +38,7 @@
 
   DCHECK_EQ(frame_size_, kUninitializedFrameSize);
   ComputeFrameSize(GetGraph()->GetMaximumNumberOfOutVRegs()
-                   + GetGraph()->GetNumberOfVRegs()
+                   + GetGraph()->GetNumberOfLocalVRegs()
                    + GetGraph()->GetNumberOfTemporaries()
                    + 1 /* filler */);
   GenerateFrameEntry();
@@ -106,6 +106,39 @@
   return -1;
 }
 
+void CodeGenerator::ComputeFrameSize(size_t number_of_spill_slots) {
+  SetFrameSize(RoundUp(
+      number_of_spill_slots * kVRegSize
+      + kVRegSize  // Art method
+      + FrameEntrySpillSize(),
+      kStackAlignment));
+}
+
+Location CodeGenerator::GetTemporaryLocation(HTemporary* temp) const {
+  uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
+  // Use the temporary region (right below the dex registers).
+  int32_t slot = GetFrameSize() - FrameEntrySpillSize()
+                                - kVRegSize  // filler
+                                - (number_of_locals * kVRegSize)
+                                - ((1 + temp->GetIndex()) * kVRegSize);
+  return Location::StackSlot(slot);
+}
+
+int32_t CodeGenerator::GetStackSlot(HLocal* local) const {
+  uint16_t reg_number = local->GetRegNumber();
+  uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
+  if (reg_number >= number_of_locals) {
+    // Local is a parameter of the method. It is stored in the caller's frame.
+    return GetFrameSize() + kVRegSize  // ART method
+                          + (reg_number - number_of_locals) * kVRegSize;
+  } else {
+    // Local is a temporary in this method. It is stored in this method's frame.
+    return GetFrameSize() - FrameEntrySpillSize()
+                          - kVRegSize  // filler.
+                          - (number_of_locals * kVRegSize)
+                          + (reg_number * kVRegSize);
+  }
+}
 
 void CodeGenerator::AllocateRegistersLocally(HInstruction* instruction) const {
   LocationSummary* locations = instruction->GetLocations();
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index abfb790..18e3e5a 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -96,7 +96,10 @@
   virtual HGraphVisitor* GetInstructionVisitor() = 0;
   virtual Assembler* GetAssembler() = 0;
   virtual size_t GetWordSize() const = 0;
-  virtual void ComputeFrameSize(size_t number_of_spill_slots) = 0;
+  void ComputeFrameSize(size_t number_of_spill_slots);
+  virtual size_t FrameEntrySpillSize() const = 0;
+  int32_t GetStackSlot(HLocal* local) const;
+  Location GetTemporaryLocation(HTemporary* temp) const;
 
   uint32_t GetFrameSize() const { return frame_size_; }
   void SetFrameSize(uint32_t size) { frame_size_ = size; }
@@ -150,7 +153,6 @@
   size_t AllocateFreeRegisterInternal(bool* blocked_registers, size_t number_of_registers) const;
 
   virtual Location GetStackLocation(HLoadLocal* load) const = 0;
-  virtual Location GetTemporaryLocation(HTemporary* temp) const = 0;
 
   // Frame size required for this method.
   uint32_t frame_size_;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index e702407..73c2d48 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -99,6 +99,10 @@
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetArena(), this) {}
 
+size_t CodeGeneratorARM::FrameEntrySpillSize() const {
+  return kNumberOfPushedRegistersAtEntry * kArmWordSize;
+}
+
 static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
   return blocked_registers + kNumberOfAllocIds;
 }
@@ -200,14 +204,6 @@
         assembler_(codegen->GetAssembler()),
         codegen_(codegen) {}
 
-void CodeGeneratorARM::ComputeFrameSize(size_t number_of_spill_slots) {
-  SetFrameSize(RoundUp(
-      number_of_spill_slots * kVRegSize
-      + kVRegSize  // Art method
-      + kNumberOfPushedRegistersAtEntry * kArmWordSize,
-      kStackAlignment));
-}
-
 void CodeGeneratorARM::GenerateFrameEntry() {
   core_spill_mask_ |= (1 << LR | 1 << R6 | 1 << R7);
   __ PushList(1 << LR | 1 << R6 | 1 << R7);
@@ -226,33 +222,6 @@
   __ Bind(label);
 }
 
-Location CodeGeneratorARM::GetTemporaryLocation(HTemporary* temp) const {
-  uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
-  // Use the temporary region (right below the dex registers).
-  int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
-                                - kVRegSize  // filler
-                                - (number_of_vregs * kVRegSize)
-                                - ((1 + temp->GetIndex()) * kVRegSize);
-  return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorARM::GetStackSlot(HLocal* local) const {
-  uint16_t reg_number = local->GetRegNumber();
-  uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
-  uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
-  if (reg_number >= number_of_vregs - number_of_in_vregs) {
-    // Local is a parameter of the method. It is stored in the caller's frame.
-    return GetFrameSize() + kVRegSize  // ART method
-                          + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
-  } else {
-    // Local is a temporary in this method. It is stored in this method's frame.
-    return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kArmWordSize)
-                          - kVRegSize  // filler.
-                          - (number_of_vregs * kVRegSize)
-                          + (reg_number * kVRegSize);
-  }
-}
-
 Location CodeGeneratorARM::GetStackLocation(HLoadLocal* load) const {
   switch (load->GetType()) {
     case Primitive::kPrimLong:
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index b7322b2..1b5974f 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -126,7 +126,6 @@
   explicit CodeGeneratorARM(HGraph* graph);
   virtual ~CodeGeneratorARM() { }
 
-  virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
   virtual void GenerateFrameEntry() OVERRIDE;
   virtual void GenerateFrameExit() OVERRIDE;
   virtual void Bind(Label* label) OVERRIDE;
@@ -136,6 +135,8 @@
     return kArmWordSize;
   }
 
+  virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
   virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
     return &location_builder_;
   }
@@ -153,9 +154,7 @@
       Primitive::Type type, bool* blocked_registers) const OVERRIDE;
   virtual size_t GetNumberOfRegisters() const OVERRIDE;
 
-  int32_t GetStackSlot(HLocal* local) const;
   virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
-  virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
 
   virtual size_t GetNumberOfCoreRegisters() const OVERRIDE {
     return kNumberOfCoreRegisters;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 52cb39d..4e69a0c 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -83,12 +83,8 @@
       instruction_visitor_(graph, this),
       move_resolver_(graph->GetArena(), this) {}
 
-void CodeGeneratorX86::ComputeFrameSize(size_t number_of_spill_slots) {
-  SetFrameSize(RoundUp(
-      number_of_spill_slots * kVRegSize
-      + kVRegSize  // Art method
-      + kNumberOfPushedRegistersAtEntry * kX86WordSize,
-      kStackAlignment));
+size_t CodeGeneratorX86::FrameEntrySpillSize() const {
+  return kNumberOfPushedRegistersAtEntry * kX86WordSize;
 }
 
 static bool* GetBlockedRegisterPairs(bool* blocked_registers) {
@@ -204,34 +200,6 @@
   __ movl(reg, Address(ESP, kCurrentMethodStackOffset));
 }
 
-Location CodeGeneratorX86::GetTemporaryLocation(HTemporary* temp) const {
-  uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
-  // Use the temporary region (right below the dex registers).
-  int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
-                                - kVRegSize  // filler
-                                - (number_of_vregs * kVRegSize)
-                                - ((1 + temp->GetIndex()) * kVRegSize);
-  return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorX86::GetStackSlot(HLocal* local) const {
-  uint16_t reg_number = local->GetRegNumber();
-  uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
-  uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
-  if (reg_number >= number_of_vregs - number_of_in_vregs) {
-    // Local is a parameter of the method. It is stored in the caller's frame.
-    return GetFrameSize() + kVRegSize  // ART method
-                          + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
-  } else {
-    // Local is a temporary in this method. It is stored in this method's frame.
-    return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86WordSize)
-                          - kVRegSize  // filler.
-                          - (number_of_vregs * kVRegSize)
-                          + (reg_number * kVRegSize);
-  }
-}
-
-
 Location CodeGeneratorX86::GetStackLocation(HLoadLocal* load) const {
   switch (load->GetType()) {
     case Primitive::kPrimLong:
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 2a45954..d622d2a 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -128,7 +128,6 @@
   explicit CodeGeneratorX86(HGraph* graph);
   virtual ~CodeGeneratorX86() { }
 
-  virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
   virtual void GenerateFrameEntry() OVERRIDE;
   virtual void GenerateFrameExit() OVERRIDE;
   virtual void Bind(Label* label) OVERRIDE;
@@ -138,6 +137,8 @@
     return kX86WordSize;
   }
 
+  virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
   virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
     return &location_builder_;
   }
@@ -155,9 +156,7 @@
   virtual ManagedRegister AllocateFreeRegister(
       Primitive::Type type, bool* blocked_registers) const OVERRIDE;
 
-  int32_t GetStackSlot(HLocal* local) const;
   virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
-  virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
 
   virtual size_t GetNumberOfCoreRegisters() const OVERRIDE {
     return kNumberOfCpuRegisters;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 93d74ee..e3ce5ce 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -91,6 +91,10 @@
         instruction_visitor_(graph, this),
         move_resolver_(graph->GetArena(), this) {}
 
+size_t CodeGeneratorX86_64::FrameEntrySpillSize() const {
+  return kNumberOfPushedRegistersAtEntry * kX86_64WordSize;
+}
+
 InstructionCodeGeneratorX86_64::InstructionCodeGeneratorX86_64(HGraph* graph, CodeGeneratorX86_64* codegen)
       : HGraphVisitor(graph),
         assembler_(codegen->GetAssembler()),
@@ -137,16 +141,6 @@
   blocked_registers[R15] = true;
 }
 
-void CodeGeneratorX86_64::ComputeFrameSize(size_t number_of_spill_slots) {
-  // Add the current ART method to the frame size, the return PC, and the filler.
-  SetFrameSize(RoundUp(
-      number_of_spill_slots * kVRegSize
-      + kVRegSize  // filler
-      + kVRegSize  // Art method
-      + kNumberOfPushedRegistersAtEntry * kX86_64WordSize,
-      kStackAlignment));
-}
-
 void CodeGeneratorX86_64::GenerateFrameEntry() {
   // Create a fake register to mimic Quick.
   static const int kFakeReturnRegister = 16;
@@ -170,33 +164,6 @@
   __ movl(reg, Address(CpuRegister(RSP), kCurrentMethodStackOffset));
 }
 
-Location CodeGeneratorX86_64::GetTemporaryLocation(HTemporary* temp) const {
-  uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
-  // Use the temporary region (right below the dex registers).
-  int32_t slot = GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86_64WordSize)
-                                - kVRegSize  // filler
-                                - (number_of_vregs * kVRegSize)
-                                - ((1 + temp->GetIndex()) * kVRegSize);
-  return Location::StackSlot(slot);
-}
-
-int32_t CodeGeneratorX86_64::GetStackSlot(HLocal* local) const {
-  uint16_t reg_number = local->GetRegNumber();
-  uint16_t number_of_vregs = GetGraph()->GetNumberOfVRegs();
-  uint16_t number_of_in_vregs = GetGraph()->GetNumberOfInVRegs();
-  if (reg_number >= number_of_vregs - number_of_in_vregs) {
-    // Local is a parameter of the method. It is stored in the caller's frame.
-    return GetFrameSize() + kVRegSize  // ART method
-                          + (reg_number - number_of_vregs + number_of_in_vregs) * kVRegSize;
-  } else {
-    // Local is a temporary in this method. It is stored in this method's frame.
-    return GetFrameSize() - (kNumberOfPushedRegistersAtEntry * kX86_64WordSize)
-                          - kVRegSize  // filler
-                          - (number_of_vregs * kVRegSize)
-                          + (reg_number * kVRegSize);
-  }
-}
-
 Location CodeGeneratorX86_64::GetStackLocation(HLoadLocal* load) const {
   switch (load->GetType()) {
     case Primitive::kPrimLong:
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 97a0b2e..8283dda 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -125,7 +125,6 @@
   explicit CodeGeneratorX86_64(HGraph* graph);
   virtual ~CodeGeneratorX86_64() {}
 
-  virtual void ComputeFrameSize(size_t number_of_spill_slots) OVERRIDE;
   virtual void GenerateFrameEntry() OVERRIDE;
   virtual void GenerateFrameExit() OVERRIDE;
   virtual void Bind(Label* label) OVERRIDE;
@@ -135,6 +134,8 @@
     return kX86_64WordSize;
   }
 
+  virtual size_t FrameEntrySpillSize() const OVERRIDE;
+
   virtual HGraphVisitor* GetLocationBuilder() OVERRIDE {
     return &location_builder_;
   }
@@ -151,9 +152,7 @@
     return &move_resolver_;
   }
 
-  int32_t GetStackSlot(HLocal* local) const;
   virtual Location GetStackLocation(HLoadLocal* load) const OVERRIDE;
-  virtual Location GetTemporaryLocation(HTemporary* temp) const OVERRIDE;
 
   virtual size_t GetNumberOfRegisters() const OVERRIDE {
     return kNumberOfRegIds;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 689aab0..ca846b3 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -138,6 +138,10 @@
     return number_of_in_vregs_;
   }
 
+  uint16_t GetNumberOfLocalVRegs() const {
+    return number_of_vregs_ - number_of_in_vregs_;
+  }
+
   const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
     return reverse_post_order_;
   }
diff --git a/test/401-optimizing-compiler/expected.txt b/test/401-optimizing-compiler/expected.txt
index 97492a4..d6ef64b 100644
--- a/test/401-optimizing-compiler/expected.txt
+++ b/test/401-optimizing-compiler/expected.txt
@@ -11,3 +11,4 @@
 Forced GC
 Forced GC
 Forced GC
+Forced GC
diff --git a/test/401-optimizing-compiler/src/Main.java b/test/401-optimizing-compiler/src/Main.java
index e5706a5..a5192e1 100644
--- a/test/401-optimizing-compiler/src/Main.java
+++ b/test/401-optimizing-compiler/src/Main.java
@@ -71,6 +71,10 @@
     if (m.$opt$TestOtherParameter(new Main()) == m) {
       throw new Error("Unexpected value returned");
     }
+
+    if (m.$opt$TestReturnNewObject(m) == m) {
+      throw new Error("Unexpected value returned");
+    }
   }
 
   static int $opt$TestInvokeIntParameter(int param) {
@@ -108,6 +112,12 @@
     return other;
   }
 
+  Object $opt$TestReturnNewObject(Object other) {
+    Object o = new Object();
+    forceGCStaticMethod();
+    return o;
+  }
+
   public static void $opt$TestInvokeStatic() {
     printStaticMethod();
     printStaticMethodWith2Args(1, 2);