summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-04-22 11:03:52 +0000
committerNicolas Geoffray <ngeoffray@google.com>2014-05-02 10:44:52 +0100
commit42fcd9838a87abaf7a2ef86853a5287f86dbe391 (patch)
treed8ffcfcb9c1997c06c6ef93b551abaa900ebcf8e /runtime
parent608168b380b741e2c7e1a2b0b568c0738986166b (diff)
downloadart-42fcd9838a87abaf7a2ef86853a5287f86dbe391.zip
art-42fcd9838a87abaf7a2ef86853a5287f86dbe391.tar.gz
art-42fcd9838a87abaf7a2ef86853a5287f86dbe391.tar.bz2
Revert "Revert "64bit changes to the stack walker for the Quick ABI.""
This reverts commit 8d5ead52a92675c258113d3dfa71bf8fceba5d9f. Change-Id: I6b4774a9bd180de33551975e106322ba1192e6ab
Diffstat (limited to 'runtime')
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc46
-rw-r--r--runtime/instruction_set.cc46
-rw-r--r--runtime/instruction_set.h2
-rw-r--r--runtime/stack.cc2
-rw-r--r--runtime/stack.h23
5 files changed, 80 insertions, 39 deletions
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 @@ namespace art {
// 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 @@ class QuickArgumentVisitor {
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 @@ class QuickArgumentVisitor {
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 @@ class QuickArgumentVisitor {
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 @@ class QuickArgumentVisitor {
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 @@ class QuickArgumentVisitor {
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 @@ class QuickArgumentVisitor {
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 @@ class QuickArgumentVisitor {
}
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 @@ class QuickArgumentVisitor {
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 @@ class QuickArgumentVisitor {
}
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 @@ class QuickArgumentVisitor {
}
}
} 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 @@ class QuickArgumentVisitor {
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 GetInstructionSetPointerSize(InstructionSet isa) {
}
}
+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 @@ InstructionSet GetInstructionSetFromString(const char* instruction_set);
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 @@ void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val
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 @@ class StackVisitor {
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 @@ class StackVisitor {
*/
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 @@ class StackVisitor {
* 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 {