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); }