Calling convention support for cross 64/32 compilation.

Add REX support for x86-64 operands.

Change-Id: I093ae26fb8c111d54b8c72166f054984564c04c6
diff --git a/compiler/jni/quick/arm/calling_convention_arm.cc b/compiler/jni/quick/arm/calling_convention_arm.cc
index 28b438e..ab39d6b 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.cc
+++ b/compiler/jni/quick/arm/calling_convention_arm.cc
@@ -79,9 +79,9 @@
 FrameOffset ArmManagedRuntimeCallingConvention::CurrentParamStackOffset() {
   CHECK(IsCurrentParamOnStack());
   FrameOffset result =
-      FrameOffset(displacement_.Int32Value() +   // displacement
-                  kPointerSize +                 // Method*
-                  (itr_slots_ * kPointerSize));  // offset into in args
+      FrameOffset(displacement_.Int32Value() +        // displacement
+                  kFramePointerSize +                 // Method*
+                  (itr_slots_ * kFramePointerSize));  // offset into in args
   return result;
 }
 
@@ -106,7 +106,7 @@
 
 ArmJniCallingConvention::ArmJniCallingConvention(bool is_static, bool is_synchronized,
                                                  const char* shorty)
-    : JniCallingConvention(is_static, is_synchronized, shorty) {
+    : JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
   // Compute padding to ensure longs and doubles are not split in AAPCS. Ignore the 'this' jobject
   // or jclass for static methods and the JNIEnv. We start at the aligned register r2.
   size_t padding = 0;
@@ -143,15 +143,15 @@
 
 size_t ArmJniCallingConvention::FrameSize() {
   // Method*, LR and callee save area size, local reference segment state
-  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kPointerSize;
+  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus 2 words for SIRT header
-  size_t sirt_size = (ReferenceCount() + 2) * kPointerSize;
+  size_t sirt_size = (ReferenceCount() + 2) * sirt_pointer_size_;
   // Plus return value spill area size
   return RoundUp(frame_data_size + sirt_size + SizeOfReturnValue(), kStackAlignment);
 }
 
 size_t ArmJniCallingConvention::OutArgSize() {
-  return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize + padding_,
+  return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize + padding_,
                  kStackAlignment);
 }
 
@@ -195,7 +195,7 @@
 
 FrameOffset ArmJniCallingConvention::CurrentParamStackOffset() {
   CHECK_GE(itr_slots_, 4u);
-  size_t offset = displacement_.Int32Value() - OutArgSize() + ((itr_slots_ - 4) * kPointerSize);
+  size_t offset = displacement_.Int32Value() - OutArgSize() + ((itr_slots_ - 4) * kFramePointerSize);
   CHECK_LT(offset, OutArgSize());
   return FrameOffset(offset);
 }
diff --git a/compiler/jni/quick/arm/calling_convention_arm.h b/compiler/jni/quick/arm/calling_convention_arm.h
index 96bbb7e..00a239b 100644
--- a/compiler/jni/quick/arm/calling_convention_arm.h
+++ b/compiler/jni/quick/arm/calling_convention_arm.h
@@ -22,10 +22,12 @@
 namespace art {
 namespace arm {
 
+constexpr size_t kFramePointerSize = 4;
+
 class ArmManagedRuntimeCallingConvention FINAL : public ManagedRuntimeCallingConvention {
  public:
   ArmManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
-      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty) {}
+      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {}
   ~ArmManagedRuntimeCallingConvention() OVERRIDE {}
   // Calling convention
   ManagedRegister ReturnRegister() OVERRIDE;
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.cc b/compiler/jni/quick/arm64/calling_convention_arm64.cc
index ff899b7..c408fa9 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.cc
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.cc
@@ -79,9 +79,9 @@
 FrameOffset Arm64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
   CHECK(IsCurrentParamOnStack());
   FrameOffset result =
-      FrameOffset(displacement_.Int32Value() +   // displacement
-                  kPointerSize +                 // Method*
-                  (itr_slots_ * kPointerSize));  // offset into in args
+      FrameOffset(displacement_.Int32Value() +         // displacement
+                  kFramePointerSize +                 // Method*
+                  (itr_slots_ * kFramePointerSize));  // offset into in args
   return result;
 }
 
@@ -119,8 +119,8 @@
 // JNI calling convention
 
 Arm64JniCallingConvention::Arm64JniCallingConvention(bool is_static, bool is_synchronized,
-                                                 const char* shorty)
-    : JniCallingConvention(is_static, is_synchronized, shorty) {
+                                                     const char* shorty)
+    : JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
   // TODO This needs to be converted to 64bit.
   // Compute padding to ensure longs and doubles are not split in AAPCS. Ignore the 'this' jobject
   // or jclass for static methods and the JNIEnv. We start at the aligned register r2.
@@ -135,7 +135,7 @@
 //    }
 //    cur_reg++;  // bump the iterator for every argument
 //  }
-//  padding_ =0;
+  padding_ =0;
 
   callee_save_regs_.push_back(Arm64ManagedRegister::FromCoreRegister(X19));
   callee_save_regs_.push_back(Arm64ManagedRegister::FromCoreRegister(X20));
@@ -173,15 +173,15 @@
 
 size_t Arm64JniCallingConvention::FrameSize() {
   // Method*, LR and callee save area size, local reference segment state
-  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kPointerSize;
+  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus 2 words for SIRT header
-  size_t sirt_size = (ReferenceCount() + 2) * kPointerSize;
+  size_t sirt_size = (ReferenceCount() + 2) * sirt_pointer_size_;
   // Plus return value spill area size
   return RoundUp(frame_data_size + sirt_size + SizeOfReturnValue(), kStackAlignment);
 }
 
 size_t Arm64JniCallingConvention::OutArgSize() {
-  return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize + padding_,
+  return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize + padding_,
                  kStackAlignment);
 }
 
@@ -228,7 +228,7 @@
 
 FrameOffset Arm64JniCallingConvention::CurrentParamStackOffset() {
   CHECK_GE(itr_slots_, 4u);
-  size_t offset = displacement_.Int32Value() - OutArgSize() + ((itr_slots_ - 4) * kPointerSize);
+  size_t offset = displacement_.Int32Value() - OutArgSize() + ((itr_slots_ - 4) * kFramePointerSize);
   CHECK_LT(offset, OutArgSize());
   return FrameOffset(offset);
 }
diff --git a/compiler/jni/quick/arm64/calling_convention_arm64.h b/compiler/jni/quick/arm64/calling_convention_arm64.h
index 7e33830..c18cd2b 100644
--- a/compiler/jni/quick/arm64/calling_convention_arm64.h
+++ b/compiler/jni/quick/arm64/calling_convention_arm64.h
@@ -22,10 +22,12 @@
 namespace art {
 namespace arm64 {
 
+constexpr size_t kFramePointerSize = 8;
+
 class Arm64ManagedRuntimeCallingConvention FINAL : public ManagedRuntimeCallingConvention {
  public:
   Arm64ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
-      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty) {}
+      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {}
   ~Arm64ManagedRuntimeCallingConvention() OVERRIDE {}
   // Calling convention
   ManagedRegister ReturnRegister() OVERRIDE;
diff --git a/compiler/jni/quick/calling_convention.cc b/compiler/jni/quick/calling_convention.cc
index 043bcea..8efdcda 100644
--- a/compiler/jni/quick/calling_convention.cc
+++ b/compiler/jni/quick/calling_convention.cc
@@ -26,11 +26,6 @@
 
 namespace art {
 
-// Offset of Method within the frame
-FrameOffset CallingConvention::MethodStackOffset() {
-  return displacement_;
-}
-
 // Managed runtime calling convention
 
 ManagedRuntimeCallingConvention* ManagedRuntimeCallingConvention::Create(
@@ -123,7 +118,7 @@
 }
 
 FrameOffset JniCallingConvention::SavedLocalReferenceCookieOffset() const {
-  size_t references_size = kSirtPointerSize * ReferenceCount();  // size excluding header
+  size_t references_size = sirt_pointer_size_ * ReferenceCount();  // size excluding header
   return FrameOffset(SirtReferencesOffset().Int32Value() + references_size);
 }
 
@@ -191,14 +186,14 @@
 FrameOffset JniCallingConvention::CurrentParamSirtEntryOffset() {
   CHECK(IsCurrentParamAReference());
   CHECK_LT(SirtLinkOffset(), SirtNumRefsOffset());
-  int result = SirtReferencesOffset().Int32Value() + itr_refs_ * kSirtPointerSize;
+  int result = SirtReferencesOffset().Int32Value() + itr_refs_ * sirt_pointer_size_;
   CHECK_GT(result, SirtNumRefsOffset().Int32Value());
   return FrameOffset(result);
 }
 
 size_t JniCallingConvention::CurrentParamSize() {
   if (itr_args_ <= kObjectOrClass) {
-    return kPointerSize;  // JNIEnv or jobject/jclass
+    return frame_pointer_size_;  // JNIEnv or jobject/jclass
   } else {
     int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni();
     return ParamSize(arg_pos);
diff --git a/compiler/jni/quick/calling_convention.h b/compiler/jni/quick/calling_convention.h
index 4950905..7e1cf63 100644
--- a/compiler/jni/quick/calling_convention.h
+++ b/compiler/jni/quick/calling_convention.h
@@ -24,7 +24,7 @@
 
 namespace art {
 
-// Top-level abstraction for different calling conventions
+// Top-level abstraction for different calling conventions.
 class CallingConvention {
  public:
   bool IsReturnAReference() const { return shorty_[0] == 'L'; }
@@ -46,8 +46,10 @@
   // Register reserved for scratch usage during procedure calls.
   virtual ManagedRegister InterproceduralScratchRegister() = 0;
 
-  // Offset of Method within the frame
-  FrameOffset MethodStackOffset();
+  // Offset of Method within the frame.
+  FrameOffset MethodStackOffset() {
+    return displacement_;
+  }
 
   // Iterator interface
 
@@ -66,8 +68,13 @@
   virtual ~CallingConvention() {}
 
  protected:
-  CallingConvention(bool is_static, bool is_synchronized, const char* shorty)
-      : displacement_(0), kSirtPointerSize(sizeof(StackReference<mirror::Object>)), is_static_(is_static), is_synchronized_(is_synchronized),
+  CallingConvention(bool is_static, bool is_synchronized, const char* shorty,
+                    size_t frame_pointer_size)
+      : itr_slots_(0), itr_refs_(0), itr_args_(0), itr_longs_and_doubles_(0),
+        itr_float_and_doubles_(0), displacement_(0),
+        frame_pointer_size_(frame_pointer_size),
+        sirt_pointer_size_(sizeof(StackReference<mirror::Object>)),
+        is_static_(is_static), is_synchronized_(is_synchronized),
         shorty_(shorty) {
     num_args_ = (is_static ? 0 : 1) + strlen(shorty) - 1;
     num_ref_args_ = is_static ? 0 : 1;  // The implicit this pointer.
@@ -145,7 +152,7 @@
     if (IsStatic()) {
       param++;  // 0th argument must skip return value at start of the shorty
     } else if (param == 0) {
-      return kPointerSize;  // this argument
+      return frame_pointer_size_;  // this argument
     }
     size_t result = Primitive::ComponentSize(Primitive::GetType(shorty_[param]));
     if (result >= 1 && result < 4) {
@@ -160,17 +167,20 @@
   // Note that each slot is 32-bit. When the current argument is bigger
   // than 32 bits, return the first slot number for this argument.
   unsigned int itr_slots_;
-  // The number of references iterated past
+  // The number of references iterated past.
   unsigned int itr_refs_;
-  // The argument number along argument list for current argument
+  // The argument number along argument list for current argument.
   unsigned int itr_args_;
-  // Number of longs and doubles seen along argument list
+  // Number of longs and doubles seen along argument list.
   unsigned int itr_longs_and_doubles_;
-  // Number of float and doubles seen along argument list
+  // Number of float and doubles seen along argument list.
   unsigned int itr_float_and_doubles_;
-  // Space for frames below this on the stack
+  // Space for frames below this on the stack.
   FrameOffset displacement_;
-  size_t kSirtPointerSize;
+  // The size of a reference.
+  const size_t frame_pointer_size_;
+  // The size of a reference entry within the SIRT.
+  const size_t sirt_pointer_size_;
 
  private:
   const bool is_static_;
@@ -218,8 +228,9 @@
   virtual const ManagedRegisterEntrySpills& EntrySpills() = 0;
 
  protected:
-  ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
-      : CallingConvention(is_static, is_synchronized, shorty) {}
+  ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty,
+                                  size_t frame_pointer_size)
+      : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {}
 };
 
 // Abstraction for JNI calling conventions
@@ -283,8 +294,7 @@
 
   // Position of SIRT and interior fields
   FrameOffset SirtOffset() const {
-    return FrameOffset(displacement_.Int32Value() +
-                       kPointerSize);  // above Method*
+    return FrameOffset(this->displacement_.Int32Value() + frame_pointer_size_);  // above Method*
   }
 
   FrameOffset SirtLinkOffset() const {
@@ -311,8 +321,9 @@
     kObjectOrClass = 1
   };
 
-  explicit JniCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
-      : CallingConvention(is_static, is_synchronized, shorty) {}
+  explicit JniCallingConvention(bool is_static, bool is_synchronized, const char* shorty,
+                                size_t frame_pointer_size)
+      : CallingConvention(is_static, is_synchronized, shorty, frame_pointer_size) {}
 
   // Number of stack slots for outgoing arguments, above which the SIRT is
   // located
diff --git a/compiler/jni/quick/mips/calling_convention_mips.cc b/compiler/jni/quick/mips/calling_convention_mips.cc
index ea39d60..51a3f54 100644
--- a/compiler/jni/quick/mips/calling_convention_mips.cc
+++ b/compiler/jni/quick/mips/calling_convention_mips.cc
@@ -79,9 +79,9 @@
 FrameOffset MipsManagedRuntimeCallingConvention::CurrentParamStackOffset() {
   CHECK(IsCurrentParamOnStack());
   FrameOffset result =
-      FrameOffset(displacement_.Int32Value() +   // displacement
-                  kPointerSize +                 // Method*
-                  (itr_slots_ * kPointerSize));  // offset into in args
+      FrameOffset(displacement_.Int32Value() +        // displacement
+                  kFramePointerSize +                 // Method*
+                  (itr_slots_ * kFramePointerSize));  // offset into in args
   return result;
 }
 
@@ -105,8 +105,8 @@
 // JNI calling convention
 
 MipsJniCallingConvention::MipsJniCallingConvention(bool is_static, bool is_synchronized,
-                                                 const char* shorty)
-    : JniCallingConvention(is_static, is_synchronized, shorty) {
+                                                   const char* shorty)
+    : JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
   // Compute padding to ensure longs and doubles are not split in AAPCS. Ignore the 'this' jobject
   // or jclass for static methods and the JNIEnv. We start at the aligned register A2.
   size_t padding = 0;
@@ -147,16 +147,15 @@
 
 size_t MipsJniCallingConvention::FrameSize() {
   // Method*, LR and callee save area size, local reference segment state
-  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kPointerSize;
+  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus 2 words for SIRT header
-  size_t sirt_size = (ReferenceCount() + 2) * kPointerSize;
+  size_t sirt_size = (ReferenceCount() + 2) * sirt_pointer_size_;
   // Plus return value spill area size
   return RoundUp(frame_data_size + sirt_size + SizeOfReturnValue(), kStackAlignment);
 }
 
 size_t MipsJniCallingConvention::OutArgSize() {
-  return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize + padding_,
-                 kStackAlignment);
+  return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize + padding_, kStackAlignment);
 }
 
 // JniCallingConvention ABI follows AAPCS where longs and doubles must occur
@@ -199,7 +198,7 @@
 
 FrameOffset MipsJniCallingConvention::CurrentParamStackOffset() {
   CHECK_GE(itr_slots_, 4u);
-  size_t offset = displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kPointerSize);
+  size_t offset = displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kFramePointerSize);
   CHECK_LT(offset, OutArgSize());
   return FrameOffset(offset);
 }
diff --git a/compiler/jni/quick/mips/calling_convention_mips.h b/compiler/jni/quick/mips/calling_convention_mips.h
index 1a9053a..e33fbad 100644
--- a/compiler/jni/quick/mips/calling_convention_mips.h
+++ b/compiler/jni/quick/mips/calling_convention_mips.h
@@ -21,10 +21,13 @@
 
 namespace art {
 namespace mips {
+
+constexpr size_t kFramePointerSize = 4;
+
 class MipsManagedRuntimeCallingConvention FINAL : public ManagedRuntimeCallingConvention {
  public:
   MipsManagedRuntimeCallingConvention(bool is_static, bool is_synchronized, const char* shorty)
-      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty) {}
+      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {}
   ~MipsManagedRuntimeCallingConvention() OVERRIDE {}
   // Calling convention
   ManagedRegister ReturnRegister() OVERRIDE;
diff --git a/compiler/jni/quick/x86/calling_convention_x86.cc b/compiler/jni/quick/x86/calling_convention_x86.cc
index 8d22fe6..8b440ed 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.cc
+++ b/compiler/jni/quick/x86/calling_convention_x86.cc
@@ -86,8 +86,8 @@
 
 FrameOffset X86ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
   return FrameOffset(displacement_.Int32Value() +   // displacement
-                     kPointerSize +                 // Method*
-                     (itr_slots_ * kPointerSize));  // offset into in args
+                     kFramePointerSize +                 // Method*
+                     (itr_slots_ * kFramePointerSize));  // offset into in args
 }
 
 const ManagedRegisterEntrySpills& X86ManagedRuntimeCallingConvention::EntrySpills() {
@@ -112,7 +112,7 @@
 
 X86JniCallingConvention::X86JniCallingConvention(bool is_static, bool is_synchronized,
                                                  const char* shorty)
-    : JniCallingConvention(is_static, is_synchronized, shorty) {
+    : JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
   callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EBP));
   callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(ESI));
   callee_save_regs_.push_back(X86ManagedRegister::FromCpuRegister(EDI));
@@ -124,15 +124,15 @@
 
 size_t X86JniCallingConvention::FrameSize() {
   // Method*, return address and callee save area size, local reference segment state
-  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kPointerSize;
+  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus 2 words for SIRT header
-  size_t sirt_size = (ReferenceCount() + 2) * kPointerSize;
+  size_t sirt_size = (ReferenceCount() + 2) * sirt_pointer_size_;
   // Plus return value spill area size
   return RoundUp(frame_data_size + sirt_size + SizeOfReturnValue(), kStackAlignment);
 }
 
 size_t X86JniCallingConvention::OutArgSize() {
-  return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, kStackAlignment);
+  return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize, kStackAlignment);
 }
 
 bool X86JniCallingConvention::IsCurrentParamInRegister() {
@@ -149,7 +149,7 @@
 }
 
 FrameOffset X86JniCallingConvention::CurrentParamStackOffset() {
-  return FrameOffset(displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kPointerSize));
+  return FrameOffset(displacement_.Int32Value() - OutArgSize() + (itr_slots_ * kFramePointerSize));
 }
 
 size_t X86JniCallingConvention::NumberOfOutgoingStackArgs() {
diff --git a/compiler/jni/quick/x86/calling_convention_x86.h b/compiler/jni/quick/x86/calling_convention_x86.h
index 2dab059..5b9069c 100644
--- a/compiler/jni/quick/x86/calling_convention_x86.h
+++ b/compiler/jni/quick/x86/calling_convention_x86.h
@@ -22,11 +22,13 @@
 namespace art {
 namespace x86 {
 
+constexpr size_t kFramePointerSize = 4;
+
 class X86ManagedRuntimeCallingConvention FINAL : public ManagedRuntimeCallingConvention {
  public:
   explicit X86ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized,
                                               const char* shorty)
-      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty) {}
+      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {}
   ~X86ManagedRuntimeCallingConvention() OVERRIDE {}
   // Calling convention
   ManagedRegister ReturnRegister() OVERRIDE;
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
index 24298d2..21e0bd7 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -96,7 +96,7 @@
 
 FrameOffset X86_64ManagedRuntimeCallingConvention::CurrentParamStackOffset() {
   return FrameOffset(displacement_.Int32Value() +   // displacement
-                     kPointerSize +                 // Method*
+                     kFramePointerSize +                 // Method*
                      (itr_slots_ * sizeof(uint32_t)));  // offset into in args
 }
 
@@ -122,8 +122,8 @@
 // JNI calling convention
 
 X86_64JniCallingConvention::X86_64JniCallingConvention(bool is_static, bool is_synchronized,
-                                                 const char* shorty)
-    : JniCallingConvention(is_static, is_synchronized, shorty) {
+                                                       const char* shorty)
+    : JniCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {
   callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(RBX));
   callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(RBP));
   callee_save_regs_.push_back(X86_64ManagedRegister::FromCpuRegister(R12));
@@ -133,20 +133,21 @@
 }
 
 uint32_t X86_64JniCallingConvention::CoreSpillMask() const {
-  return 1 << RBX | 1 << RBP | 1 << R12 | 1 << R13 | 1 << R14 | 1 << R15 | 1 << R13 | 1 << kNumberOfCpuRegisters;
+  return 1 << RBX | 1 << RBP | 1 << R12 | 1 << R13 | 1 << R14 | 1 << R15 | 1 << R13 |
+      1 << kNumberOfCpuRegisters;
 }
 
 size_t X86_64JniCallingConvention::FrameSize() {
   // Method*, return address and callee save area size, local reference segment state
-  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kPointerSize;
+  size_t frame_data_size = (3 + CalleeSaveRegisters().size()) * kFramePointerSize;
   // References plus link_ (pointer) and number_of_references_ (uint32_t) for SIRT header
-  size_t sirt_size = kPointerSize + sizeof(uint32_t) + ReferenceCount()*kSirtPointerSize;
+  size_t sirt_size = kFramePointerSize + sizeof(uint32_t) + (ReferenceCount() * sirt_pointer_size_);
   // Plus return value spill area size
   return RoundUp(frame_data_size + sirt_size + SizeOfReturnValue(), kStackAlignment);
 }
 
 size_t X86_64JniCallingConvention::OutArgSize() {
-  return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, kStackAlignment);
+  return RoundUp(NumberOfOutgoingStackArgs() * kFramePointerSize, kStackAlignment);
 }
 
 bool X86_64JniCallingConvention::IsCurrentParamInRegister() {
@@ -180,7 +181,7 @@
   size_t offset = itr_args_
       - std::min(8U, itr_float_and_doubles_)               // Float arguments passed through Xmm0..Xmm7
       - std::min(6U, itr_args_ - itr_float_and_doubles_);  // Integer arguments passed through GPR
-  return FrameOffset(displacement_.Int32Value() - OutArgSize() + (offset * kPointerSize));
+  return FrameOffset(displacement_.Int32Value() - OutArgSize() + (offset * kFramePointerSize));
 }
 
 size_t X86_64JniCallingConvention::NumberOfOutgoingStackArgs() {
diff --git a/compiler/jni/quick/x86_64/calling_convention_x86_64.h b/compiler/jni/quick/x86_64/calling_convention_x86_64.h
index d7f7762..d545774 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.h
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.h
@@ -22,11 +22,13 @@
 namespace art {
 namespace x86_64 {
 
+constexpr size_t kFramePointerSize = 8;
+
 class X86_64ManagedRuntimeCallingConvention FINAL : public ManagedRuntimeCallingConvention {
  public:
   explicit X86_64ManagedRuntimeCallingConvention(bool is_static, bool is_synchronized,
                                               const char* shorty)
-      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty) {}
+      : ManagedRuntimeCallingConvention(is_static, is_synchronized, shorty, kFramePointerSize) {}
   ~X86_64ManagedRuntimeCallingConvention() OVERRIDE {}
   // Calling convention
   ManagedRegister ReturnRegister() OVERRIDE;
diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc
index 59eb98e..effc38e 100644
--- a/compiler/utils/arm/assembler_arm.cc
+++ b/compiler/utils/arm/assembler_arm.cc
@@ -1436,6 +1436,8 @@
   mov(rd, ShifterOperand(rm, ROR, 0), cond);
 }
 
+constexpr size_t kFramePointerSize = 4;
+
 void ArmAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
                               const std::vector<ManagedRegister>& callee_save_regs,
                               const ManagedRegisterEntrySpills& entry_spills) {
@@ -1453,8 +1455,8 @@
   PushList(push_list);
 
   // Increase frame to required size.
-  CHECK_GT(frame_size, pushed_values * kPointerSize);  // Must be at least space to push Method*
-  size_t adjust = frame_size - (pushed_values * kPointerSize);
+  CHECK_GT(frame_size, pushed_values * kFramePointerSize);  // Must at least have space for Method*.
+  size_t adjust = frame_size - (pushed_values * kFramePointerSize);
   IncreaseFrameSize(adjust);
 
   // Write out Method*.
@@ -1463,7 +1465,7 @@
   // Write out entry spills.
   for (size_t i = 0; i < entry_spills.size(); ++i) {
     Register reg = entry_spills.at(i).AsArm().AsCoreRegister();
-    StoreToOffset(kStoreWord, reg, SP, frame_size + kPointerSize + (i * kPointerSize));
+    StoreToOffset(kStoreWord, reg, SP, frame_size + kFramePointerSize + (i * kFramePointerSize));
   }
 }
 
@@ -1480,8 +1482,8 @@
   }
 
   // Decrease frame to start of callee saves
-  CHECK_GT(frame_size, pop_values * kPointerSize);
-  size_t adjust = frame_size - (pop_values * kPointerSize);
+  CHECK_GT(frame_size, pop_values * kFramePointerSize);
+  size_t adjust = frame_size - (pop_values * kFramePointerSize);
   DecreaseFrameSize(adjust);
 
   // Pop callee saves and PC
diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc
index 5b2c8ba..a11c2da 100644
--- a/compiler/utils/arm64/assembler_arm64.cc
+++ b/compiler/utils/arm64/assembler_arm64.cc
@@ -575,6 +575,8 @@
   ___ Brk();
 }
 
+constexpr size_t kFramePointerSize = 8;
+
 void Arm64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
                         const std::vector<ManagedRegister>& callee_save_regs,
                         const ManagedRegisterEntrySpills& entry_spills) {
@@ -589,8 +591,8 @@
   ___ PushCalleeSavedRegisters();
 
   // Increate frame to required size - must be at least space to push Method*.
-  CHECK_GT(frame_size, kCalleeSavedRegsSize * kPointerSize);
-  size_t adjust = frame_size - (kCalleeSavedRegsSize * kPointerSize);
+  CHECK_GT(frame_size, kCalleeSavedRegsSize * kFramePointerSize);
+  size_t adjust = frame_size - (kCalleeSavedRegsSize * kFramePointerSize);
   IncreaseFrameSize(adjust);
 
   // Write Method*.
@@ -600,7 +602,7 @@
   // TODO: we can implement a %2 STRP variant of StoreToOffset.
   for (size_t i = 0; i < entry_spills.size(); ++i) {
     Register reg = entry_spills.at(i).AsArm64().AsCoreRegister();
-    StoreToOffset(reg, SP, frame_size + kPointerSize + (i * kPointerSize));
+    StoreToOffset(reg, SP, frame_size + kFramePointerSize + (i * kFramePointerSize));
   }
 }
 
@@ -610,10 +612,10 @@
   // For now we only check that the size of the frame is greater than the
   // no of APCS callee saved regs [X19, X30] [D8, D15].
   CHECK_EQ(callee_save_regs.size(), kCalleeSavedRegsSize);
-  CHECK_GT(frame_size, kCalleeSavedRegsSize * kPointerSize);
+  CHECK_GT(frame_size, kCalleeSavedRegsSize * kFramePointerSize);
 
   // Decrease frame size to start of callee saved regs.
-  size_t adjust = frame_size - (kCalleeSavedRegsSize * kPointerSize);
+  size_t adjust = frame_size - (kCalleeSavedRegsSize * kFramePointerSize);
   DecreaseFrameSize(adjust);
 
   // Pop callee saved and return to LR.
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index 99c29f1..45d3a97 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -536,6 +536,8 @@
   Sdc1(reg, base, offset);
 }
 
+constexpr size_t kFramePointerSize = 4;
+
 void MipsAssembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
                                const std::vector<ManagedRegister>& callee_save_regs,
                                const ManagedRegisterEntrySpills& entry_spills) {
@@ -545,10 +547,10 @@
   IncreaseFrameSize(frame_size);
 
   // Push callee saves and return address
-  int stack_offset = frame_size - kPointerSize;
+  int stack_offset = frame_size - kFramePointerSize;
   StoreToOffset(kStoreWord, RA, SP, stack_offset);
   for (int i = callee_save_regs.size() - 1; i >= 0; --i) {
-    stack_offset -= kPointerSize;
+    stack_offset -= kFramePointerSize;
     Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
     StoreToOffset(kStoreWord, reg, SP, stack_offset);
   }
@@ -559,7 +561,7 @@
   // Write out entry spills.
   for (size_t i = 0; i < entry_spills.size(); ++i) {
     Register reg = entry_spills.at(i).AsMips().AsCoreRegister();
-    StoreToOffset(kStoreWord, reg, SP, frame_size + kPointerSize + (i * kPointerSize));
+    StoreToOffset(kStoreWord, reg, SP, frame_size + kFramePointerSize + (i * kFramePointerSize));
   }
 }
 
@@ -568,11 +570,11 @@
   CHECK_ALIGNED(frame_size, kStackAlignment);
 
   // Pop callee saves and return address
-  int stack_offset = frame_size - (callee_save_regs.size() * kPointerSize) - kPointerSize;
+  int stack_offset = frame_size - (callee_save_regs.size() * kFramePointerSize) - kFramePointerSize;
   for (size_t i = 0; i < callee_save_regs.size(); ++i) {
     Register reg = callee_save_regs.at(i).AsMips().AsCoreRegister();
     LoadFromOffset(kLoadWord, reg, SP, stack_offset);
-    stack_offset += kPointerSize;
+    stack_offset += kFramePointerSize;
   }
   LoadFromOffset(kLoadWord, RA, SP, stack_offset);
 
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index aac8b01..6043c17 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -1396,6 +1396,8 @@
   EmitOperand(reg_or_opcode, Operand(operand));
 }
 
+constexpr size_t kFramePointerSize = 4;
+
 void X86Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
                               const std::vector<ManagedRegister>& spill_regs,
                               const ManagedRegisterEntrySpills& entry_spills) {
@@ -1404,11 +1406,11 @@
     pushl(spill_regs.at(i).AsX86().AsCpuRegister());
   }
   // return address then method on stack
-  addl(ESP, Immediate(-frame_size + (spill_regs.size() * kPointerSize) +
-                      kPointerSize /*method*/ + kPointerSize /*return address*/));
+  addl(ESP, Immediate(-frame_size + (spill_regs.size() * kFramePointerSize) +
+                      kFramePointerSize /*method*/ + kFramePointerSize /*return address*/));
   pushl(method_reg.AsX86().AsCpuRegister());
   for (size_t i = 0; i < entry_spills.size(); ++i) {
-    movl(Address(ESP, frame_size + kPointerSize + (i * kPointerSize)),
+    movl(Address(ESP, frame_size + kFramePointerSize + (i * kFramePointerSize)),
          entry_spills.at(i).AsX86().AsCpuRegister());
   }
 }
@@ -1416,7 +1418,7 @@
 void X86Assembler::RemoveFrame(size_t frame_size,
                             const std::vector<ManagedRegister>& spill_regs) {
   CHECK_ALIGNED(frame_size, kStackAlignment);
-  addl(ESP, Immediate(frame_size - (spill_regs.size() * kPointerSize) - kPointerSize));
+  addl(ESP, Immediate(frame_size - (spill_regs.size() * kFramePointerSize) - kFramePointerSize));
   for (size_t i = 0; i < spill_regs.size(); ++i) {
     popl(spill_regs.at(i).AsX86().AsCpuRegister());
   }
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 52b9382..7d02c7c 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -1513,15 +1513,30 @@
 }
 
 void X86_64Assembler::EmitOptionalRex32(const Operand& operand) {
-  UNIMPLEMENTED(FATAL);
+  uint8_t rex = operand.rex();
+  if (rex != 0) {
+    EmitUint8(rex);
+  }
 }
 
 void X86_64Assembler::EmitOptionalRex32(CpuRegister dst, const Operand& operand) {
-  UNIMPLEMENTED(FATAL);
+  uint8_t rex = operand.rex();
+  if (dst.NeedsRex()) {
+    rex |= 0x44;  // REX.0R00
+  }
+  if (rex != 0) {
+    EmitUint8(rex);
+  }
 }
 
 void X86_64Assembler::EmitOptionalRex32(XmmRegister dst, const Operand& operand) {
-  UNIMPLEMENTED(FATAL);
+  uint8_t rex = operand.rex();
+  if (dst.NeedsRex()) {
+    rex |= 0x44;  // REX.0R00
+  }
+  if (rex != 0) {
+    EmitUint8(rex);
+  }
 }
 
 void X86_64Assembler::EmitRex64(CpuRegister reg) {
@@ -1532,7 +1547,13 @@
 }
 
 void X86_64Assembler::EmitRex64(CpuRegister dst, const Operand& operand) {
-  UNIMPLEMENTED(FATAL);
+  uint8_t rex = 0x48 | operand.rex();  // REX.W000
+  if (dst.NeedsRex()) {
+    rex |= 0x44;  // REX.0R00
+  }
+  if (rex != 0) {
+    EmitUint8(rex);
+  }
 }
 
 void X86_64Assembler::EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src) {
@@ -1540,19 +1561,27 @@
 }
 
 void X86_64Assembler::EmitOptionalByteRegNormalizingRex32(CpuRegister dst, const Operand& operand) {
-  UNIMPLEMENTED(FATAL);
+  uint8_t rex = 0x40 | operand.rex();  // REX.0000
+  if (dst.NeedsRex()) {
+    rex |= 0x44;  // REX.0R00
+  }
+  if (rex != 0) {
+    EmitUint8(rex);
+  }
 }
 
+constexpr size_t kFramePointerSize = 8;
+
 void X86_64Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
-                              const std::vector<ManagedRegister>& spill_regs,
-                              const ManagedRegisterEntrySpills& entry_spills) {
+                                 const std::vector<ManagedRegister>& spill_regs,
+                                 const ManagedRegisterEntrySpills& entry_spills) {
   CHECK_ALIGNED(frame_size, kStackAlignment);
   for (int i = spill_regs.size() - 1; i >= 0; --i) {
     pushq(spill_regs.at(i).AsX86_64().AsCpuRegister());
   }
   // return address then method on stack
-  addq(CpuRegister(RSP), Immediate(-frame_size + (spill_regs.size() * kPointerSize) +
-                                   kPointerSize /*method*/ + kPointerSize /*return address*/));
+  addq(CpuRegister(RSP), Immediate(-frame_size + (spill_regs.size() * kFramePointerSize) +
+                                   kFramePointerSize /*method*/ + kFramePointerSize /*return address*/));
   pushq(method_reg.AsX86_64().AsCpuRegister());
 
   for (size_t i = 0; i < entry_spills.size(); ++i) {
@@ -1579,7 +1608,7 @@
 void X86_64Assembler::RemoveFrame(size_t frame_size,
                             const std::vector<ManagedRegister>& spill_regs) {
   CHECK_ALIGNED(frame_size, kStackAlignment);
-  addq(CpuRegister(RSP), Immediate(frame_size - (spill_regs.size() * kPointerSize) - kPointerSize));
+  addq(CpuRegister(RSP), Immediate(frame_size - (spill_regs.size() * kFramePointerSize) - kFramePointerSize));
   for (size_t i = 0; i < spill_regs.size(); ++i) {
     popq(spill_regs.at(i).AsX86_64().AsCpuRegister());
   }
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 1d42d89..4738dcb 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -68,6 +68,10 @@
     return static_cast<Register>(encoding_at(1) & 7);
   }
 
+  uint8_t rex() const {
+    return rex_;
+  }
+
   int8_t disp8() const {
     CHECK_GE(length_, 2);
     return static_cast<int8_t>(encoding_[length_ - 1]);
@@ -81,27 +85,33 @@
   }
 
   bool IsRegister(CpuRegister reg) const {
-    CHECK(!reg.NeedsRex()) << "TODO: rex support:" << reg;
     return ((encoding_[0] & 0xF8) == 0xC0)  // Addressing mode is register only.
-        && ((encoding_[0] & 0x07) == reg.LowBits());  // Register codes match.
+        && ((encoding_[0] & 0x07) == reg.LowBits())  // Register codes match.
+        && (reg.NeedsRex() == ((rex_ & 1) != 0));  // REX.000B bits match.
   }
 
  protected:
   // Operand can be sub classed (e.g: Address).
-  Operand() : length_(0) { }
+  Operand() : rex_(0), length_(0) { }
 
-  void SetModRM(int mod, CpuRegister rm) {
+  void SetModRM(uint8_t mod, CpuRegister rm) {
     CHECK_EQ(mod & ~3, 0);
-    CHECK(!rm.NeedsRex());
-    encoding_[0] = (mod << 6) | static_cast<uint8_t>(rm.AsRegister());
+    if (rm.NeedsRex()) {
+      rex_ |= 0x41;  // REX.000B
+    }
+    encoding_[0] = (mod << 6) | rm.LowBits();
     length_ = 1;
   }
 
   void SetSIB(ScaleFactor scale, CpuRegister index, CpuRegister base) {
-    CHECK(!index.NeedsRex()) << "TODO: rex support: " << index;
-    CHECK(!base.NeedsRex()) << "TODO: rex support: " << base;
     CHECK_EQ(length_, 1);
     CHECK_EQ(scale & ~3, 0);
+    if (base.NeedsRex()) {
+      rex_ |= 0x41;  // REX.000B
+    }
+    if (index.NeedsRex()) {
+      rex_ |= 0x42;  // REX.00X0
+    }
     encoding_[1] = (scale << 6) | (static_cast<uint8_t>(index.AsRegister()) << 3) |
         static_cast<uint8_t>(base.AsRegister());
     length_ = 2;
@@ -120,8 +130,9 @@
   }
 
  private:
-  byte length_;
-  byte encoding_[6];
+  uint8_t rex_;
+  uint8_t length_;
+  uint8_t encoding_[6];
 
   explicit Operand(CpuRegister reg) { SetModRM(3, reg); }