Revert "Revert "64bit changes to the stack walker for the Quick ABI.""

This reverts commit 8d5ead52a92675c258113d3dfa71bf8fceba5d9f.

Change-Id: I6b4774a9bd180de33551975e106322ba1192e6ab
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index df7a7c1..6c5279e 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -42,7 +42,7 @@
   RegStorage reg_arg_high = wide ? GetArgMappingToPhysicalReg(in_position + 1) :
       RegStorage::InvalidReg();
 
-  int offset = StackVisitor::GetOutVROffset(in_position);
+  int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
   if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
     /*
      * When doing a call for x86, it moves the stack pointer in order to push return.
@@ -81,7 +81,7 @@
 }
 
 void Mir2Lir::LoadArgDirect(int in_position, RegLocation rl_dest) {
-  int offset = StackVisitor::GetOutVROffset(in_position);
+  int offset = StackVisitor::GetOutVROffset(in_position, cu_->instruction_set);
   if (cu_->instruction_set == kX86 || cu_->instruction_set == kX86_64) {
     /*
      * When doing a call for x86, it moves the stack pointer in order to push return.
diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc
index 39783a2..6455572 100644
--- a/compiler/dex/quick/ralloc_util.cc
+++ b/compiler/dex/quick/ralloc_util.cc
@@ -1141,7 +1141,8 @@
 /* Returns sp-relative offset in bytes for a VReg */
 int Mir2Lir::VRegOffset(int v_reg) {
   return StackVisitor::GetVRegOffset(cu_->code_item, core_spill_mask_,
-                                     fp_spill_mask_, frame_size_, v_reg);
+                                     fp_spill_mask_, frame_size_, v_reg,
+                                     cu_->instruction_set);
 }
 
 /* Returns sp-relative offset in bytes for a SReg */
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 1a67952..412a052 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -495,7 +495,8 @@
       } else {
         uint32_t offset = StackVisitor::GetVRegOffset(code_item, oat_method.GetCoreSpillMask(),
                                                       oat_method.GetFpSpillMask(),
-                                                      oat_method.GetFrameSizeInBytes(), reg);
+                                                      oat_method.GetFrameSizeInBytes(), reg,
+                                                      GetInstructionSet());
         os << "[sp + #" << offset << "]";
       }
     }
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 2b29591..680ffbe 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -34,12 +34,6 @@
 
 // Visits the arguments as saved to the stack by a Runtime::kRefAndArgs callee save frame.
 class QuickArgumentVisitor {
-  // Size of each spilled GPR.
-#ifdef __LP64__
-  static constexpr size_t kBytesPerGprSpillLocation = 8;
-#else
-  static constexpr size_t kBytesPerGprSpillLocation = 4;
-#endif
   // Number of bytes for each out register in the caller method's frame.
   static constexpr size_t kBytesStackArgLocation = 4;
 #if defined(__arm__)
@@ -61,13 +55,12 @@
   static constexpr bool kQuickSoftFloatAbi = true;  // This is a soft float ABI.
   static constexpr size_t kNumQuickGprArgs = 3;  // 3 arguments passed in GPRs.
   static constexpr size_t kNumQuickFprArgs = 0;  // 0 arguments passed in FPRs.
-  static constexpr size_t kBytesPerFprSpillLocation = 4;  // FPR spill size is 4 bytes.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 0;  // Offset of first FPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 8;  // Offset of first GPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 44;  // Offset of return address.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_FrameSize = 48;  // Frame size.
   static size_t GprIndexToGprOffset(uint32_t gpr_index) {
-    return gpr_index * kBytesPerGprSpillLocation;
+    return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
   }
 #elif defined(__aarch64__)
   // The callee save frame is pointed to by SP.
@@ -93,13 +86,12 @@
   static constexpr bool kQuickSoftFloatAbi = false;  // This is a hard float ABI.
   static constexpr size_t kNumQuickGprArgs = 7;  // 7 arguments passed in GPRs.
   static constexpr size_t kNumQuickFprArgs = 8;  // 8 arguments passed in FPRs.
-  static constexpr size_t kBytesPerFprSpillLocation = 8;  // FPR spill size is 8 bytes.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset =16;  // Offset of first FPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 144;  // Offset of first GPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 296;  // Offset of return address.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_FrameSize = 304;  // Frame size.
   static size_t GprIndexToGprOffset(uint32_t gpr_index) {
-    return gpr_index * kBytesPerGprSpillLocation;
+    return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
   }
 #elif defined(__mips__)
   // The callee save frame is pointed to by SP.
@@ -119,13 +111,12 @@
   static constexpr bool kQuickSoftFloatAbi = true;  // This is a soft float ABI.
   static constexpr size_t kNumQuickGprArgs = 3;  // 3 arguments passed in GPRs.
   static constexpr size_t kNumQuickFprArgs = 0;  // 0 arguments passed in FPRs.
-  static constexpr size_t kBytesPerFprSpillLocation = 4;  // FPR spill size is 4 bytes.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 0;  // Offset of first FPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 4;  // Offset of first GPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 60;  // Offset of return address.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_FrameSize = 64;  // Frame size.
   static size_t GprIndexToGprOffset(uint32_t gpr_index) {
-    return gpr_index * kBytesPerGprSpillLocation;
+    return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
   }
 #elif defined(__i386__)
   // The callee save frame is pointed to by SP.
@@ -145,13 +136,12 @@
   static constexpr bool kQuickSoftFloatAbi = true;  // This is a soft float ABI.
   static constexpr size_t kNumQuickGprArgs = 3;  // 3 arguments passed in GPRs.
   static constexpr size_t kNumQuickFprArgs = 0;  // 0 arguments passed in FPRs.
-  static constexpr size_t kBytesPerFprSpillLocation = 8;  // FPR spill size is 8 bytes.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 0;  // Offset of first FPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 4;  // Offset of first GPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 28;  // Offset of return address.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_FrameSize = 32;  // Frame size.
   static size_t GprIndexToGprOffset(uint32_t gpr_index) {
-    return gpr_index * kBytesPerGprSpillLocation;
+    return gpr_index * GetBytesPerGprSpillLocation(kRuntimeISA);
   }
 #elif defined(__x86_64__)
   // The callee save frame is pointed to by SP.
@@ -184,18 +174,17 @@
   static constexpr bool kQuickSoftFloatAbi = false;  // This is a hard float ABI.
   static constexpr size_t kNumQuickGprArgs = 5;  // 3 arguments passed in GPRs.
   static constexpr size_t kNumQuickFprArgs = 8;  // 0 arguments passed in FPRs.
-  static constexpr size_t kBytesPerFprSpillLocation = 8;  // FPR spill size is 8 bytes.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Fpr1Offset = 16;  // Offset of first FPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_Gpr1Offset = 80;  // Offset of first GPR arg.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_LrOffset = 168;  // Offset of return address.
   static constexpr size_t kQuickCalleeSaveFrame_RefAndArgs_FrameSize = 176;  // Frame size.
   static size_t GprIndexToGprOffset(uint32_t gpr_index) {
     switch (gpr_index) {
-      case 0: return (4 * kBytesPerGprSpillLocation);
-      case 1: return (1 * kBytesPerGprSpillLocation);
-      case 2: return (0 * kBytesPerGprSpillLocation);
-      case 3: return (5 * kBytesPerGprSpillLocation);
-      case 4: return (6 * kBytesPerGprSpillLocation);
+      case 0: return (4 * GetBytesPerGprSpillLocation(kRuntimeISA));
+      case 1: return (1 * GetBytesPerGprSpillLocation(kRuntimeISA));
+      case 2: return (0 * GetBytesPerGprSpillLocation(kRuntimeISA));
+      case 3: return (5 * GetBytesPerGprSpillLocation(kRuntimeISA));
+      case 4: return (6 * GetBytesPerGprSpillLocation(kRuntimeISA));
       default:
         LOG(FATAL) << "Unexpected GPR index: " << gpr_index;
         return 0;
@@ -248,7 +237,7 @@
       Primitive::Type type = GetParamPrimitiveType();
       if (UNLIKELY((type == Primitive::kPrimDouble) || (type == Primitive::kPrimFloat))) {
         if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) {
-          return fpr_args_ + (fpr_index_ * kBytesPerFprSpillLocation);
+          return fpr_args_ + (fpr_index_ * GetBytesPerFprSpillLocation(kRuntimeISA));
         }
         return stack_args_ + (stack_index_ * kBytesStackArgLocation);
       }
@@ -260,7 +249,7 @@
   }
 
   bool IsSplitLongOrDouble() const {
-    if ((kBytesPerGprSpillLocation == 4) || (kBytesPerFprSpillLocation == 4)) {
+    if ((GetBytesPerGprSpillLocation(kRuntimeISA) == 4) || (GetBytesPerFprSpillLocation(kRuntimeISA) == 4)) {
       return is_split_long_or_double_;
     } else {
       return false;  // An optimization for when GPR and FPRs are 64bit.
@@ -341,7 +330,7 @@
         case Primitive::kPrimDouble:
         case Primitive::kPrimLong:
           if (kQuickSoftFloatAbi || (cur_type_ == Primitive::kPrimLong)) {
-            is_split_long_or_double_ = (kBytesPerGprSpillLocation == 4) &&
+            is_split_long_or_double_ = (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) &&
                 ((gpr_index_ + 1) == kNumQuickGprArgs);
             Visit();
             if (!kQuickSoftFloatAbi || kNumQuickGprArgs == gpr_index_) {
@@ -354,7 +343,7 @@
             }
             if (gpr_index_ < kNumQuickGprArgs) {
               gpr_index_++;
-              if (kBytesPerGprSpillLocation == 4) {
+              if (GetBytesPerGprSpillLocation(kRuntimeISA) == 4) {
                 if (gpr_index_ < kNumQuickGprArgs) {
                   gpr_index_++;
                 } else if (kQuickSoftFloatAbi) {
@@ -363,12 +352,12 @@
               }
             }
           } else {
-            is_split_long_or_double_ = (kBytesPerFprSpillLocation == 4) &&
+            is_split_long_or_double_ = (GetBytesPerFprSpillLocation(kRuntimeISA) == 4) &&
                 ((fpr_index_ + 1) == kNumQuickFprArgs);
             Visit();
             if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) {
               fpr_index_++;
-              if (kBytesPerFprSpillLocation == 4) {
+              if (GetBytesPerFprSpillLocation(kRuntimeISA) == 4) {
                 if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) {
                   fpr_index_++;
                 }
@@ -393,12 +382,13 @@
                                              uint32_t shorty_len) {
     if (kQuickSoftFloatAbi) {
       CHECK_EQ(kNumQuickFprArgs, 0U);
-      return (kNumQuickGprArgs * kBytesPerGprSpillLocation) + kBytesPerGprSpillLocation /* ArtMethod* */;
+      return (kNumQuickGprArgs * GetBytesPerGprSpillLocation(kRuntimeISA))
+          + GetBytesPerGprSpillLocation(kRuntimeISA) /* ArtMethod* */;
     } else {
       // For now, there is no reg-spill area for the targets with
       // hard float ABI. So, the offset pointing to the first method's
       // parameter ('this' for non-static methods) should be returned.
-      return kBytesPerGprSpillLocation;  // Skip Method*.
+      return GetBytesPerGprSpillLocation(kRuntimeISA);  // Skip Method*.
     }
   }
 
diff --git a/runtime/instruction_set.cc b/runtime/instruction_set.cc
index cbcd2e0..c1931a9 100644
--- a/runtime/instruction_set.cc
+++ b/runtime/instruction_set.cc
@@ -86,6 +86,52 @@
   }
 }
 
+size_t GetBytesPerGprSpillLocation(InstructionSet isa) {
+  switch (isa) {
+    case kArm:
+      // Fall-through.
+    case kThumb2:
+      return 4;
+    case kArm64:
+      return 8;
+    case kX86:
+      return 4;
+    case kX86_64:
+      return 8;
+    case kMips:
+      return 4;
+    case kNone:
+      LOG(FATAL) << "ISA kNone does not have spills.";
+      return 0;
+    default:
+      LOG(FATAL) << "Unknown ISA " << isa;
+      return 0;
+  }
+}
+
+size_t GetBytesPerFprSpillLocation(InstructionSet isa) {
+  switch (isa) {
+    case kArm:
+      // Fall-through.
+    case kThumb2:
+      return 4;
+    case kArm64:
+      return 8;
+    case kX86:
+      return 8;
+    case kX86_64:
+      return 8;
+    case kMips:
+      return 4;
+    case kNone:
+      LOG(FATAL) << "ISA kNone does not have spills.";
+      return 0;
+    default:
+      LOG(FATAL) << "Unknown ISA " << isa;
+      return 0;
+  }
+}
+
 size_t GetInstructionSetAlignment(InstructionSet isa) {
   switch (isa) {
     case kArm:
diff --git a/runtime/instruction_set.h b/runtime/instruction_set.h
index 4bc35a7..bfbbbd6 100644
--- a/runtime/instruction_set.h
+++ b/runtime/instruction_set.h
@@ -41,6 +41,8 @@
 size_t GetInstructionSetPointerSize(InstructionSet isa);
 size_t GetInstructionSetAlignment(InstructionSet isa);
 bool Is64BitInstructionSet(InstructionSet isa);
+size_t GetBytesPerGprSpillLocation(InstructionSet isa);
+size_t GetBytesPerFprSpillLocation(InstructionSet isa);
 
 #if defined(__arm__)
 static constexpr InstructionSet kRuntimeISA = kArm;
diff --git a/runtime/stack.cc b/runtime/stack.cc
index ab3bd85..9c709ae 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -187,7 +187,7 @@
       uint32_t core_spills = m->GetCoreSpillMask();
       uint32_t fp_spills = m->GetFpSpillMask();
       size_t frame_size = m->GetFrameSizeInBytes();
-      int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
+      int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg, kRuntimeISA);
       byte* vreg_addr = reinterpret_cast<byte*>(GetCurrentQuickFrame()) + offset;
       *reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
     }
diff --git a/runtime/stack.h b/runtime/stack.h
index ab903d6..afc4f25 100644
--- a/runtime/stack.h
+++ b/runtime/stack.h
@@ -19,9 +19,10 @@
 
 #include "dex_file.h"
 #include "instrumentation.h"
+#include "arch/context.h"
 #include "base/casts.h"
 #include "base/macros.h"
-#include "arch/context.h"
+#include "instruction_set.h"
 #include "mirror/object.h"
 #include "mirror/object_reference.h"
 #include "verify_object.h"
@@ -577,7 +578,7 @@
   uint32_t* GetVRegAddr(mirror::ArtMethod** cur_quick_frame, const DexFile::CodeItem* code_item,
                         uint32_t core_spills, uint32_t fp_spills, size_t frame_size,
                         uint16_t vreg) const {
-    int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
+    int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg, kRuntimeISA);
     DCHECK_EQ(cur_quick_frame, GetCurrentQuickFrame());
     byte* vreg_addr = reinterpret_cast<byte*>(cur_quick_frame) + offset;
     return reinterpret_cast<uint32_t*>(vreg_addr);
@@ -634,14 +635,15 @@
    */
   static int GetVRegOffset(const DexFile::CodeItem* code_item,
                            uint32_t core_spills, uint32_t fp_spills,
-                           size_t frame_size, int reg) {
+                           size_t frame_size, int reg, InstructionSet isa) {
     DCHECK_EQ(frame_size & (kStackAlignment - 1), 0U);
     DCHECK_NE(reg, static_cast<int>(kVRegInvalid));
-
-    int num_spills = __builtin_popcount(core_spills) + __builtin_popcount(fp_spills) + 1;  // Filler.
+    int spill_size = __builtin_popcount(core_spills) * GetBytesPerGprSpillLocation(isa)
+        + __builtin_popcount(fp_spills) * GetBytesPerFprSpillLocation(isa)
+        + sizeof(uint32_t);  // Filler.
     int num_ins = code_item->ins_size_;
     int num_regs = code_item->registers_size_ - num_ins;
-    int locals_start = frame_size - ((num_spills + num_regs) * sizeof(uint32_t));
+    int locals_start = frame_size - spill_size - num_regs * sizeof(uint32_t);
     if (reg == static_cast<int>(kVRegMethodPtrBaseReg)) {
       // The current method pointer corresponds to special location on stack.
       return 0;
@@ -654,19 +656,20 @@
        * temp is at offset -4 bytes from locals, the second is at -8 bytes from locals,
        * and so on.
        */
-      int relative_offset = (reg + std::abs(static_cast<int>(kVRegNonSpecialTempBaseReg)) - 1) * sizeof(uint32_t);
+      int relative_offset =
+          (reg + std::abs(static_cast<int>(kVRegNonSpecialTempBaseReg)) - 1) * sizeof(uint32_t);
       return locals_start + relative_offset;
     }  else if (reg < num_regs) {
       return locals_start + (reg * sizeof(uint32_t));
     } else {
       // Handle ins.
-      return frame_size + ((reg - num_regs) * sizeof(uint32_t)) + sizeof(StackReference<mirror::ArtMethod>);
+      return frame_size + ((reg - num_regs) * sizeof(uint32_t)) + GetBytesPerGprSpillLocation(isa);
     }
   }
 
-  static int GetOutVROffset(uint16_t out_num) {
+  static int GetOutVROffset(uint16_t out_num, InstructionSet isa) {
     // According to stack model, the first out is above the Method ptr.
-    return sizeof(StackReference<mirror::ArtMethod>) + (out_num * sizeof(uint32_t));
+    return GetBytesPerGprSpillLocation(isa) + (out_num * sizeof(uint32_t));
   }
 
   uintptr_t GetCurrentQuickFramePc() const {