summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2014-05-02 14:40:15 +0100
committer Vladimir Marko <vmarko@google.com> 2014-05-13 11:43:22 +0100
commit7624d25dad2d1ba25969ae704fccf68649103ae5 (patch)
treede72194b76a4e23e0b15ec4085447ae7e4425815
parente1910f1d802dff79bba5ef61e1c4fd0b95f6e5b0 (diff)
Move quick frame info to OatQuickMethodHeader.
Rename OatMethodHeader to OatQuickMethodHeader, move frame info from OatMethodOffsets to OatQuickMethodHeader. Retrieve the info from other places for non-quick methods (portable compiled bytecode or jni stub, generic jni, runtime, abstract and proxy). This change has a libcore/ companion CL "Remove ArtMethod's quick fields for frame size and spills." https://android-review.googlesource.com/94164 Bug: 11767815 Change-Id: I0e31a7875d76732e1ec479c86b9b5ca01203507f
-rw-r--r--compiler/common_compiler_test.h45
-rw-r--r--compiler/jni/quick/x86_64/calling_convention_x86_64.cc2
-rw-r--r--compiler/oat_test.cc8
-rw-r--r--compiler/oat_writer.cc98
-rw-r--r--compiler/oat_writer.h2
-rw-r--r--dex2oat/dex2oat.cc3
-rw-r--r--runtime/arch/arch_test.cc12
-rw-r--r--runtime/arch/arm/context_arm.cc20
-rw-r--r--runtime/arch/arm/quick_method_frame_info_arm.h68
-rw-r--r--runtime/arch/arm64/context_arm64.cc21
-rw-r--r--runtime/arch/arm64/quick_method_frame_info_arm64.h89
-rw-r--r--runtime/arch/mips/context_mips.cc20
-rw-r--r--runtime/arch/mips/quick_method_frame_info_mips.h56
-rw-r--r--runtime/arch/stub_test.cc3
-rw-r--r--runtime/arch/x86/context_x86.cc14
-rw-r--r--runtime/arch/x86/quick_method_frame_info_x86.h51
-rw-r--r--runtime/arch/x86_64/context_x86_64.cc20
-rw-r--r--runtime/arch/x86_64/quick_method_frame_info_x86_64.h63
-rw-r--r--runtime/class_linker.cc26
-rw-r--r--runtime/class_linker_test.cc3
-rw-r--r--runtime/exception_test.cc7
-rw-r--r--runtime/gc/space/image_space.cc32
-rw-r--r--runtime/mirror/art_method-inl.h39
-rw-r--r--runtime/mirror/art_method.cc4
-rw-r--r--runtime/mirror/art_method.h44
-rw-r--r--runtime/oat.cc22
-rw-r--r--runtime/oat.h22
-rw-r--r--runtime/oat_file-inl.h28
-rw-r--r--runtime/oat_file.cc16
-rw-r--r--runtime/oat_file.h18
-rw-r--r--runtime/quick/quick_method_frame_info.h61
-rw-r--r--runtime/runtime-inl.h42
-rw-r--r--runtime/runtime.cc155
-rw-r--r--runtime/runtime.h23
-rw-r--r--runtime/stack.cc19
-rw-r--r--runtime/thread.cc12
36 files changed, 723 insertions, 445 deletions
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 8bba84a9c1..8f39212b80 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -134,9 +134,6 @@ class CommonCompilerTest : public CommonRuntimeTest {
public:
// Create an OatMethod based on pointers (for unit tests).
OatFile::OatMethod CreateOatMethod(const void* code,
- const size_t frame_size_in_bytes,
- const uint32_t core_spill_mask,
- const uint32_t fp_spill_mask,
const uint8_t* gc_map) {
CHECK(code != nullptr);
const byte* base;
@@ -154,9 +151,6 @@ class CommonCompilerTest : public CommonRuntimeTest {
}
return OatFile::OatMethod(base,
code_offset,
- frame_size_in_bytes,
- core_spill_mask,
- fp_spill_mask,
gc_map_offset);
}
@@ -179,11 +173,14 @@ class CommonCompilerTest : public CommonRuntimeTest {
CHECK_NE(0u, code_size);
const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable();
uint32_t vmap_table_offset = vmap_table.empty() ? 0u
- : sizeof(OatMethodHeader) + vmap_table.size();
+ : sizeof(OatQuickMethodHeader) + vmap_table.size();
const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable();
uint32_t mapping_table_offset = mapping_table.empty() ? 0u
- : sizeof(OatMethodHeader) + vmap_table.size() + mapping_table.size();
- OatMethodHeader method_header(vmap_table_offset, mapping_table_offset, code_size);
+ : sizeof(OatQuickMethodHeader) + vmap_table.size() + mapping_table.size();
+ OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset,
+ compiled_method->GetFrameSizeInBytes(),
+ compiled_method->GetCoreSpillMask(),
+ compiled_method->GetFpSpillMask(), code_size);
header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
@@ -207,11 +204,7 @@ class CommonCompilerTest : public CommonRuntimeTest {
const void* method_code = CompiledMethod::CodePointer(code_ptr,
compiled_method->GetInstructionSet());
LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
- OatFile::OatMethod oat_method = CreateOatMethod(method_code,
- compiled_method->GetFrameSizeInBytes(),
- compiled_method->GetCoreSpillMask(),
- compiled_method->GetFpSpillMask(),
- nullptr);
+ OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
} else {
@@ -220,28 +213,13 @@ class CommonCompilerTest : public CommonRuntimeTest {
if (!method->IsNative()) {
const void* method_code = kUsePortableCompiler ? GetPortableToInterpreterBridge()
: GetQuickToInterpreterBridge();
- OatFile::OatMethod oat_method = CreateOatMethod(method_code,
- kStackAlignment,
- 0,
- 0,
- nullptr);
+ OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
} else {
const void* method_code = GetQuickGenericJniTrampoline();
- mirror::ArtMethod* callee_save_method = runtime_->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
-
- // Compute Sirt size, as Sirt goes into frame
- MethodHelper mh(method);
- uint32_t sirt_refs = mh.GetNumberOfReferenceArgsWithoutReceiver() + 1;
- uint32_t sirt_size = StackIndirectReferenceTable::SizeOf(sirt_refs);
-
- OatFile::OatMethod oat_method = CreateOatMethod(method_code,
- callee_save_method->GetFrameSizeInBytes() +
- sirt_size,
- callee_save_method->GetCoreSpillMask(),
- callee_save_method->GetFpSpillMask(),
- nullptr);
+
+ OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr);
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
}
@@ -323,11 +301,12 @@ class CommonCompilerTest : public CommonRuntimeTest {
compiler_options_->SetCompilerFilter(CompilerOptions::kInterpretOnly);
#endif
+ runtime_->SetInstructionSet(instruction_set);
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
if (!runtime_->HasCalleeSaveMethod(type)) {
runtime_->SetCalleeSaveMethod(
- runtime_->CreateCalleeSaveMethod(instruction_set, type), type);
+ runtime_->CreateCalleeSaveMethod(type), type);
}
}
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 4dfa29a46f..52490e6e6b 100644
--- a/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
+++ b/compiler/jni/quick/x86_64/calling_convention_x86_64.cc
@@ -133,7 +133,7 @@ X86_64JniCallingConvention::X86_64JniCallingConvention(bool is_static, bool is_s
}
uint32_t X86_64JniCallingConvention::CoreSpillMask() const {
- return 1 << RBX | 1 << RBP | 1 << R12 | 1 << R13 | 1 << R14 | 1 << R15 | 1 << R13 |
+ return 1 << RBX | 1 << RBP | 1 << R12 | 1 << R13 | 1 << R14 | 1 << R15 |
1 << kNumberOfCpuRegisters;
}
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index b5d39232ca..66972cbf69 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -17,11 +17,12 @@
#include "common_compiler_test.h"
#include "compiler/compiler.h"
#include "compiler/oat_writer.h"
+#include "entrypoints/quick/quick_entrypoints.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
-#include "oat_file.h"
+#include "oat_file-inl.h"
#include "vector_output_stream.h"
namespace art {
@@ -176,8 +177,9 @@ TEST_F(OatTest, OatHeaderSizeCheck) {
// If this test is failing and you have to update these constants,
// it is time to update OatHeader::kOatVersion
EXPECT_EQ(80U, sizeof(OatHeader));
- EXPECT_EQ(20U, sizeof(OatMethodOffsets));
- EXPECT_EQ(12U, sizeof(OatMethodHeader));
+ EXPECT_EQ(8U, sizeof(OatMethodOffsets));
+ EXPECT_EQ(24U, sizeof(OatQuickMethodHeader));
+ EXPECT_EQ(320U, sizeof(QuickEntryPoints));
}
TEST_F(OatTest, OatHeaderIsValid) {
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index bbc9c3e325..39311d975b 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -331,9 +331,6 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
if (compiled_method != nullptr) {
// Derived from CompiledMethod.
uint32_t quick_code_offset = 0;
- uint32_t frame_size_in_bytes = kStackAlignment;
- uint32_t core_spill_mask = 0;
- uint32_t fp_spill_mask = 0;
const std::vector<uint8_t>* portable_code = compiled_method->GetPortableCode();
const std::vector<uint8_t>* quick_code = compiled_method->GetQuickCode();
@@ -351,7 +348,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
uint32_t code_size = quick_code->size() * sizeof(uint8_t);
CHECK_NE(code_size, 0U);
uint32_t thumb_offset = compiled_method->CodeDelta();
- quick_code_offset = offset_ + sizeof(OatMethodHeader) + thumb_offset;
+ quick_code_offset = offset_ + sizeof(OatQuickMethodHeader) + thumb_offset;
std::vector<uint8_t>* cfi_info = writer_->compiler_driver_->GetCallFrameInformation();
if (cfi_info != nullptr) {
@@ -374,27 +371,45 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
}
}
- DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
- OatMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
- method_header->code_size_ = code_size;
-
// Deduplicate code arrays.
auto code_iter = dedupe_map_.find(compiled_method);
if (code_iter != dedupe_map_.end()) {
quick_code_offset = code_iter->second;
- FixupMethodHeader(method_header, quick_code_offset - thumb_offset);
} else {
dedupe_map_.Put(compiled_method, quick_code_offset);
- FixupMethodHeader(method_header, quick_code_offset - thumb_offset);
+ }
+
+ // Update quick method header.
+ DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
+ OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
+ uint32_t mapping_table_offset = method_header->mapping_table_offset_;
+ uint32_t vmap_table_offset = method_header->vmap_table_offset_;
+ // The code offset was 0 when the mapping/vmap table offset was set, so it's set
+ // to 0-offset and we need to adjust it by code_offset.
+ uint32_t code_offset = quick_code_offset - thumb_offset;
+ if (mapping_table_offset != 0u) {
+ mapping_table_offset += code_offset;
+ DCHECK_LT(mapping_table_offset, code_offset);
+ }
+ if (vmap_table_offset != 0u) {
+ vmap_table_offset += code_offset;
+ DCHECK_LT(vmap_table_offset, code_offset);
+ }
+ uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+ uint32_t core_spill_mask = compiled_method->GetCoreSpillMask();
+ uint32_t fp_spill_mask = compiled_method->GetFpSpillMask();
+ *method_header = OatQuickMethodHeader(mapping_table_offset, vmap_table_offset,
+ frame_size_in_bytes, core_spill_mask, fp_spill_mask,
+ code_size);
+
+ // Update checksum if this wasn't a duplicate.
+ if (code_iter == dedupe_map_.end()) {
writer_->oat_header_->UpdateChecksum(method_header, sizeof(*method_header));
offset_ += sizeof(*method_header); // Method header is prepended before code.
writer_->oat_header_->UpdateChecksum(&(*quick_code)[0], code_size);
offset_ += code_size;
}
}
- frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
- core_spill_mask = compiled_method->GetCoreSpillMask();
- fp_spill_mask = compiled_method->GetFpSpillMask();
if (kIsDebugBuild) {
// We expect GC maps except when the class hasn't been verified or the method is native.
@@ -421,9 +436,6 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_];
offsets->code_offset_ = quick_code_offset;
- offsets->frame_size_in_bytes_ = frame_size_in_bytes;
- offsets->core_spill_mask_ = core_spill_mask;
- offsets->fp_spill_mask_ = fp_spill_mask;
++method_offsets_index_;
}
@@ -431,19 +443,6 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
}
private:
- static void FixupMethodHeader(OatMethodHeader* method_header, uint32_t code_offset) {
- // The code offset was 0 when the mapping/vmap table offset was set, so it's set
- // to 0-offset and we need to adjust it by code_offset.
- if (method_header->mapping_table_offset_ != 0u) {
- method_header->mapping_table_offset_ += code_offset;
- DCHECK_LT(method_header->mapping_table_offset_, code_offset);
- }
- if (method_header->vmap_table_offset_ != 0u) {
- method_header->vmap_table_offset_ += code_offset;
- DCHECK_LT(method_header->vmap_table_offset_, code_offset);
- }
- }
-
// Deduplication is already done on a pointer basis by the compiler driver,
// so we can simply compare the pointers to find out if things are duplicated.
SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
@@ -501,55 +500,22 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
OatClass* oat_class = writer_->oat_classes_[oat_class_index_];
CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
- OatMethodOffsets offsets(0u, kStackAlignment, 0u, 0u, 0u);
+ OatMethodOffsets offsets(0u, 0u);
if (compiled_method != nullptr) {
DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
offsets = oat_class->method_offsets_[method_offsets_index_];
++method_offsets_index_;
}
- // Derive frame size and spill masks for native methods without code:
- // These are generic JNI methods...
- uint32_t method_idx = it.GetMemberIndex();
- bool is_native = (it.GetMemberAccessFlags() & kAccNative) != 0;
- if (is_native && compiled_method == nullptr) {
- // Compute Sirt size as putting _every_ reference into it, even null ones.
- uint32_t s_len;
- const char* shorty = dex_file_->GetMethodShorty(dex_file_->GetMethodId(method_idx),
- &s_len);
- DCHECK(shorty != nullptr);
- uint32_t refs = 1; // Native method always has "this" or class.
- for (uint32_t i = 1; i < s_len; ++i) {
- if (shorty[i] == 'L') {
- refs++;
- }
- }
- size_t pointer_size = GetInstructionSetPointerSize(
- writer_->compiler_driver_->GetInstructionSet());
- size_t sirt_size = StackIndirectReferenceTable::GetAlignedSirtSizeTarget(pointer_size, refs);
-
- // Get the generic spill masks and base frame size.
- mirror::ArtMethod* callee_save_method =
- Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
-
- offsets.frame_size_in_bytes_ = callee_save_method->GetFrameSizeInBytes() + sirt_size;
- offsets.core_spill_mask_ = callee_save_method->GetCoreSpillMask();
- offsets.fp_spill_mask_ = callee_save_method->GetFpSpillMask();
- DCHECK_EQ(offsets.gc_map_offset_, 0u);
- }
-
ClassLinker* linker = Runtime::Current()->GetClassLinker();
InvokeType invoke_type = it.GetMethodInvokeType(dex_file_->GetClassDef(class_def_index_));
// Unchecked as we hold mutator_lock_ on entry.
ScopedObjectAccessUnchecked soa(Thread::Current());
SirtRef<mirror::DexCache> dex_cache(soa.Self(), linker->FindDexCache(*dex_file_));
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), nullptr);
- mirror::ArtMethod* method = linker->ResolveMethod(*dex_file_, method_idx, dex_cache,
+ mirror::ArtMethod* method = linker->ResolveMethod(*dex_file_, it.GetMemberIndex(), dex_cache,
class_loader, nullptr, invoke_type);
CHECK(method != NULL);
- method->SetFrameSizeInBytes(offsets.frame_size_in_bytes_);
- method->SetCoreSpillMask(offsets.core_spill_mask_);
- method->SetFpSpillMask(offsets.fp_spill_mask_);
// Portable code offsets are set by ElfWriterMclinker::FixupCompiledCodeOffset after linking.
method->SetQuickOatCodeOffset(offsets.code_offset_);
method->SetOatNativeGcMapOffset(offsets.gc_map_offset_);
@@ -601,10 +567,10 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
// Deduplicate code arrays.
const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_];
DCHECK(method_offsets.code_offset_ < offset_ || method_offsets.code_offset_ ==
- offset_ + sizeof(OatMethodHeader) + compiled_method->CodeDelta())
+ offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta())
<< PrettyMethod(it.GetMemberIndex(), *dex_file_);
if (method_offsets.code_offset_ >= offset_) {
- const OatMethodHeader& method_header = oat_class->method_headers_[method_offsets_index_];
+ const OatQuickMethodHeader& method_header = oat_class->method_headers_[method_offsets_index_];
if (!out->WriteFully(&method_header, sizeof(method_header))) {
ReportWriteFailure("method header", it);
return false;
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 7cdd5329bd..85c9b4761a 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -231,7 +231,7 @@ class OatWriter {
// oat_method_offsets_offsets_from_oat_class_ should contain 0
// values in this case).
std::vector<OatMethodOffsets> method_offsets_;
- std::vector<OatMethodHeader> method_headers_;
+ std::vector<OatQuickMethodHeader> method_headers_;
private:
DISALLOW_COPY_AND_ASSIGN(OatClass);
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 3529c27a8b..c2af767157 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -444,10 +444,11 @@ class Dex2Oat {
return false;
}
Runtime* runtime = Runtime::Current();
+ runtime->SetInstructionSet(instruction_set);
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
if (!runtime->HasCalleeSaveMethod(type)) {
- runtime->SetCalleeSaveMethod(runtime->CreateCalleeSaveMethod(instruction_set, type), type);
+ runtime->SetCalleeSaveMethod(runtime->CreateCalleeSaveMethod(type), type);
}
}
runtime->GetClassLinker()->FixupDexCaches(runtime->GetResolutionMethod());
diff --git a/runtime/arch/arch_test.cc b/runtime/arch/arch_test.cc
index c285088fe4..b957d58601 100644
--- a/runtime/arch/arch_test.cc
+++ b/runtime/arch/arch_test.cc
@@ -18,6 +18,7 @@
#include "common_runtime_test.h"
#include "mirror/art_method.h"
+#include "quick/quick_method_frame_info.h"
namespace art {
@@ -30,10 +31,13 @@ class ArchTest : public CommonRuntimeTest {
Thread* t = Thread::Current();
t->TransitionFromSuspendedToRunnable(); // So we can create callee-save methods.
- mirror::ArtMethod* save_method = r->CreateCalleeSaveMethod(isa, type);
- EXPECT_EQ(save_method->GetFrameSizeInBytes(), save_size) << "Expected and real size differs for "
- << type << " core spills=" << std::hex << save_method->GetCoreSpillMask() << " fp spills="
- << save_method->GetFpSpillMask() << std::dec;
+ r->SetInstructionSet(isa);
+ mirror::ArtMethod* save_method = r->CreateCalleeSaveMethod(type);
+ r->SetCalleeSaveMethod(save_method, type);
+ QuickMethodFrameInfo frame_info = save_method->GetQuickFrameInfo();
+ EXPECT_EQ(frame_info.FrameSizeInBytes(), save_size) << "Expected and real size differs for "
+ << type << " core spills=" << std::hex << frame_info.CoreSpillMask() << " fp spills="
+ << frame_info.FpSpillMask() << std::dec;
t->TransitionFromRunnableToSuspended(ThreadState::kNative); // So we can shut down.
}
diff --git a/runtime/arch/arm/context_arm.cc b/runtime/arch/arm/context_arm.cc
index 0e1b25eb85..6a337b3038 100644
--- a/runtime/arch/arm/context_arm.cc
+++ b/runtime/arch/arm/context_arm.cc
@@ -16,8 +16,9 @@
#include "context_arm.h"
-#include "mirror/art_method.h"
+#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
+#include "quick/quick_method_frame_info.h"
#include "stack.h"
#include "thread.h"
@@ -42,17 +43,15 @@ void ArmContext::Reset() {
void ArmContext::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
- uint32_t core_spills = method->GetCoreSpillMask();
- uint32_t fp_core_spills = method->GetFpSpillMask();
- size_t spill_count = POPCOUNT(core_spills);
- size_t fp_spill_count = POPCOUNT(fp_core_spills);
- size_t frame_size = method->GetFrameSizeInBytes();
+ const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
+ size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
+ size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
if (spill_count > 0) {
// Lowest number spill is farthest away, walk registers and fill into context
int j = 1;
for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
- if (((core_spills >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size);
+ if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
+ gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
j++;
}
}
@@ -61,8 +60,9 @@ void ArmContext::FillCalleeSaves(const StackVisitor& fr) {
// Lowest number spill is farthest away, walk registers and fill into context
int j = 1;
for (size_t i = 0; i < kNumberOfSRegisters; i++) {
- if (((fp_core_spills >> i) & 1) != 0) {
- fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j, frame_size);
+ if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
+ fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
+ frame_info.FrameSizeInBytes());
j++;
}
}
diff --git a/runtime/arch/arm/quick_method_frame_info_arm.h b/runtime/arch/arm/quick_method_frame_info_arm.h
new file mode 100644
index 0000000000..8d08190dc7
--- /dev/null
+++ b/runtime/arch/arm/quick_method_frame_info_arm.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_ARM_QUICK_METHOD_FRAME_INFO_ARM_H_
+#define ART_RUNTIME_ARCH_ARM_QUICK_METHOD_FRAME_INFO_ARM_H_
+
+#include "quick/quick_method_frame_info.h"
+#include "registers_arm.h"
+#include "runtime.h" // for Runtime::CalleeSaveType.
+
+namespace art {
+namespace arm {
+
+static constexpr uint32_t kArmCalleeSaveRefSpills =
+ (1 << art::arm::R5) | (1 << art::arm::R6) | (1 << art::arm::R7) | (1 << art::arm::R8) |
+ (1 << art::arm::R10) | (1 << art::arm::R11);
+static constexpr uint32_t kArmCalleeSaveArgSpills =
+ (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3);
+static constexpr uint32_t kArmCalleeSaveAllSpills =
+ (1 << art::arm::R4) | (1 << art::arm::R9);
+static constexpr uint32_t kArmCalleeSaveFpAllSpills =
+ (1 << art::arm::S0) | (1 << art::arm::S1) | (1 << art::arm::S2) | (1 << art::arm::S3) |
+ (1 << art::arm::S4) | (1 << art::arm::S5) | (1 << art::arm::S6) | (1 << art::arm::S7) |
+ (1 << art::arm::S8) | (1 << art::arm::S9) | (1 << art::arm::S10) | (1 << art::arm::S11) |
+ (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) | (1 << art::arm::S15) |
+ (1 << art::arm::S16) | (1 << art::arm::S17) | (1 << art::arm::S18) | (1 << art::arm::S19) |
+ (1 << art::arm::S20) | (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) |
+ (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) | (1 << art::arm::S27) |
+ (1 << art::arm::S28) | (1 << art::arm::S29) | (1 << art::arm::S30) | (1 << art::arm::S31);
+
+constexpr uint32_t ArmCalleeSaveCoreSpills(Runtime::CalleeSaveType type) {
+ return kArmCalleeSaveRefSpills | (type == Runtime::kRefsAndArgs ? kArmCalleeSaveArgSpills : 0) |
+ (type == Runtime::kSaveAll ? kArmCalleeSaveAllSpills : 0) | (1 << art::arm::LR);
+}
+
+constexpr uint32_t ArmCalleeSaveFpSpills(Runtime::CalleeSaveType type) {
+ return type == Runtime::kSaveAll ? kArmCalleeSaveFpAllSpills : 0;
+}
+
+constexpr uint32_t ArmCalleeSaveFrameSize(Runtime::CalleeSaveType type) {
+ return RoundUp((POPCOUNT(ArmCalleeSaveCoreSpills(type)) /* gprs */ +
+ POPCOUNT(ArmCalleeSaveFpSpills(type)) /* fprs */ +
+ 1 /* Method* */) * kArmPointerSize, kStackAlignment);
+}
+
+constexpr QuickMethodFrameInfo ArmCalleeSaveMethodFrameInfo(Runtime::CalleeSaveType type) {
+ return QuickMethodFrameInfo(ArmCalleeSaveFrameSize(type),
+ ArmCalleeSaveCoreSpills(type),
+ ArmCalleeSaveFpSpills(type));
+}
+
+} // namespace arm
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_ARM_QUICK_METHOD_FRAME_INFO_ARM_H_
diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc
index 0890fa9d33..fae44af3ce 100644
--- a/runtime/arch/arm64/context_arm64.cc
+++ b/runtime/arch/arm64/context_arm64.cc
@@ -18,8 +18,9 @@
#include "context_arm64.h"
-#include "mirror/art_method.h"
+#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
+#include "quick/quick_method_frame_info.h"
#include "stack.h"
#include "thread.h"
@@ -45,18 +46,15 @@ void Arm64Context::Reset() {
void Arm64Context::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
- uint32_t core_spills = method->GetCoreSpillMask();
- uint32_t fp_core_spills = method->GetFpSpillMask();
- size_t spill_count = POPCOUNT(core_spills);
- size_t fp_spill_count = POPCOUNT(fp_core_spills);
- size_t frame_size = method->GetFrameSizeInBytes();
-
+ const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
+ size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
+ size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
if (spill_count > 0) {
// Lowest number spill is farthest away, walk registers and fill into context.
int j = 1;
for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
- if (((core_spills >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size);
+ if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
+ gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
j++;
}
}
@@ -66,8 +64,9 @@ void Arm64Context::FillCalleeSaves(const StackVisitor& fr) {
// Lowest number spill is farthest away, walk registers and fill into context.
int j = 1;
for (size_t i = 0; i < kNumberOfDRegisters; i++) {
- if (((fp_core_spills >> i) & 1) != 0) {
- fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j, frame_size);
+ if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
+ fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
+ frame_info.FrameSizeInBytes());
j++;
}
}
diff --git a/runtime/arch/arm64/quick_method_frame_info_arm64.h b/runtime/arch/arm64/quick_method_frame_info_arm64.h
new file mode 100644
index 0000000000..cb830acdea
--- /dev/null
+++ b/runtime/arch/arm64/quick_method_frame_info_arm64.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_ARM64_QUICK_METHOD_FRAME_INFO_ARM64_H_
+#define ART_RUNTIME_ARCH_ARM64_QUICK_METHOD_FRAME_INFO_ARM64_H_
+
+#include "quick/quick_method_frame_info.h"
+#include "registers_arm64.h"
+#include "runtime.h" // for Runtime::CalleeSaveType.
+
+namespace art {
+namespace arm64 {
+
+// Callee saved registers
+static constexpr uint32_t kArm64CalleeSaveRefSpills =
+ (1 << art::arm64::X19) | (1 << art::arm64::X20) | (1 << art::arm64::X21) |
+ (1 << art::arm64::X22) | (1 << art::arm64::X23) | (1 << art::arm64::X24) |
+ (1 << art::arm64::X25) | (1 << art::arm64::X26) | (1 << art::arm64::X27) |
+ (1 << art::arm64::X28);
+// X0 is the method pointer. Not saved.
+static constexpr uint32_t kArm64CalleeSaveArgSpills =
+ (1 << art::arm64::X1) | (1 << art::arm64::X2) | (1 << art::arm64::X3) |
+ (1 << art::arm64::X4) | (1 << art::arm64::X5) | (1 << art::arm64::X6) |
+ (1 << art::arm64::X7);
+// TODO This is conservative. Only ALL should include the thread register.
+// The thread register is not preserved by the aapcs64.
+// LR is always saved.
+static constexpr uint32_t kArm64CalleeSaveAllSpills = 0; // (1 << art::arm64::LR);
+
+// Save callee-saved floating point registers. Rest are scratch/parameters.
+static constexpr uint32_t kArm64CalleeSaveFpArgSpills =
+ (1 << art::arm64::D0) | (1 << art::arm64::D1) | (1 << art::arm64::D2) |
+ (1 << art::arm64::D3) | (1 << art::arm64::D4) | (1 << art::arm64::D5) |
+ (1 << art::arm64::D6) | (1 << art::arm64::D7);
+static constexpr uint32_t kArm64CalleeSaveFpRefSpills =
+ (1 << art::arm64::D8) | (1 << art::arm64::D9) | (1 << art::arm64::D10) |
+ (1 << art::arm64::D11) | (1 << art::arm64::D12) | (1 << art::arm64::D13) |
+ (1 << art::arm64::D14) | (1 << art::arm64::D15);
+static constexpr uint32_t kArm64FpAllSpills =
+ kArm64CalleeSaveFpArgSpills |
+ (1 << art::arm64::D16) | (1 << art::arm64::D17) | (1 << art::arm64::D18) |
+ (1 << art::arm64::D19) | (1 << art::arm64::D20) | (1 << art::arm64::D21) |
+ (1 << art::arm64::D22) | (1 << art::arm64::D23) | (1 << art::arm64::D24) |
+ (1 << art::arm64::D25) | (1 << art::arm64::D26) | (1 << art::arm64::D27) |
+ (1 << art::arm64::D28) | (1 << art::arm64::D29) | (1 << art::arm64::D30) |
+ (1 << art::arm64::D31);
+
+constexpr uint32_t Arm64CalleeSaveCoreSpills(Runtime::CalleeSaveType type) {
+ return kArm64CalleeSaveRefSpills |
+ (type == Runtime::kRefsAndArgs ? kArm64CalleeSaveArgSpills : 0) |
+ (type == Runtime::kSaveAll ? kArm64CalleeSaveAllSpills : 0) | (1 << art::arm64::FP) |
+ (1 << art::arm64::X18) | (1 << art::arm64::LR);
+}
+
+constexpr uint32_t Arm64CalleeSaveFpSpills(Runtime::CalleeSaveType type) {
+ return kArm64CalleeSaveFpRefSpills |
+ (type == Runtime::kRefsAndArgs ? kArm64CalleeSaveFpArgSpills: 0) |
+ (type == Runtime::kSaveAll ? kArm64FpAllSpills : 0);
+}
+
+constexpr uint32_t Arm64CalleeSaveFrameSize(Runtime::CalleeSaveType type) {
+ return RoundUp((POPCOUNT(Arm64CalleeSaveCoreSpills(type)) /* gprs */ +
+ POPCOUNT(Arm64CalleeSaveFpSpills(type)) /* fprs */ +
+ 1 /* Method* */) * kArm64PointerSize, kStackAlignment);
+}
+
+constexpr QuickMethodFrameInfo Arm64CalleeSaveMethodFrameInfo(Runtime::CalleeSaveType type) {
+ return QuickMethodFrameInfo(Arm64CalleeSaveFrameSize(type),
+ Arm64CalleeSaveCoreSpills(type),
+ Arm64CalleeSaveFpSpills(type));
+}
+
+} // namespace arm64
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_ARM64_QUICK_METHOD_FRAME_INFO_ARM64_H_
diff --git a/runtime/arch/mips/context_mips.cc b/runtime/arch/mips/context_mips.cc
index 0950e7122d..ad2889135a 100644
--- a/runtime/arch/mips/context_mips.cc
+++ b/runtime/arch/mips/context_mips.cc
@@ -16,8 +16,9 @@
#include "context_mips.h"
-#include "mirror/art_method.h"
+#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
+#include "quick/quick_method_frame_info.h"
#include "stack.h"
namespace art {
@@ -41,17 +42,15 @@ void MipsContext::Reset() {
void MipsContext::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
- uint32_t core_spills = method->GetCoreSpillMask();
- uint32_t fp_core_spills = method->GetFpSpillMask();
- size_t spill_count = POPCOUNT(core_spills);
- size_t fp_spill_count = POPCOUNT(fp_core_spills);
- size_t frame_size = method->GetFrameSizeInBytes();
+ const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
+ size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
+ size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
if (spill_count > 0) {
// Lowest number spill is farthest away, walk registers and fill into context.
int j = 1;
for (size_t i = 0; i < kNumberOfCoreRegisters; i++) {
- if (((core_spills >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size);
+ if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
+ gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
j++;
}
}
@@ -60,8 +59,9 @@ void MipsContext::FillCalleeSaves(const StackVisitor& fr) {
// Lowest number spill is farthest away, walk registers and fill into context.
int j = 1;
for (size_t i = 0; i < kNumberOfFRegisters; i++) {
- if (((fp_core_spills >> i) & 1) != 0) {
- fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j, frame_size);
+ if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
+ fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
+ frame_info.FrameSizeInBytes());
j++;
}
}
diff --git a/runtime/arch/mips/quick_method_frame_info_mips.h b/runtime/arch/mips/quick_method_frame_info_mips.h
new file mode 100644
index 0000000000..2a8bcf0b37
--- /dev/null
+++ b/runtime/arch/mips/quick_method_frame_info_mips.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_MIPS_QUICK_METHOD_FRAME_INFO_MIPS_H_
+#define ART_RUNTIME_ARCH_MIPS_QUICK_METHOD_FRAME_INFO_MIPS_H_
+
+#include "quick/quick_method_frame_info.h"
+#include "registers_mips.h"
+#include "runtime.h" // for Runtime::CalleeSaveType.
+
+namespace art {
+namespace mips {
+
+static constexpr uint32_t kMipsCalleeSaveRefSpills =
+ (1 << art::mips::S2) | (1 << art::mips::S3) | (1 << art::mips::S4) | (1 << art::mips::S5) |
+ (1 << art::mips::S6) | (1 << art::mips::S7) | (1 << art::mips::GP) | (1 << art::mips::FP);
+static constexpr uint32_t kMipsCalleeSaveArgSpills =
+ (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3);
+static constexpr uint32_t kMipsCalleeSaveAllSpills =
+ (1 << art::mips::S0) | (1 << art::mips::S1);
+
+constexpr uint32_t MipsCalleeSaveCoreSpills(Runtime::CalleeSaveType type) {
+ return kMipsCalleeSaveRefSpills |
+ (type == Runtime::kRefsAndArgs ? kMipsCalleeSaveArgSpills : 0) |
+ (type == Runtime::kSaveAll ? kMipsCalleeSaveAllSpills : 0) | (1 << art::mips::RA);
+}
+
+constexpr uint32_t MipsCalleeSaveFrameSize(Runtime::CalleeSaveType type) {
+ return RoundUp((POPCOUNT(MipsCalleeSaveCoreSpills(type)) /* gprs */ +
+ (type == Runtime::kRefsAndArgs ? 0 : 3) + 1 /* Method* */) *
+ kMipsPointerSize, kStackAlignment);
+}
+
+constexpr QuickMethodFrameInfo MipsCalleeSaveMethodFrameInfo(Runtime::CalleeSaveType type) {
+ return QuickMethodFrameInfo(MipsCalleeSaveFrameSize(type),
+ MipsCalleeSaveCoreSpills(type),
+ 0u);
+}
+
+} // namespace mips
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_MIPS_QUICK_METHOD_FRAME_INFO_MIPS_H_
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 1d055400a1..5e8edf0571 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -33,10 +33,11 @@ class StubTest : public CommonRuntimeTest {
{
// Create callee-save methods
ScopedObjectAccess soa(Thread::Current());
+ runtime_->SetInstructionSet(kRuntimeISA);
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
if (!runtime_->HasCalleeSaveMethod(type)) {
- runtime_->SetCalleeSaveMethod(runtime_->CreateCalleeSaveMethod(kRuntimeISA, type), type);
+ runtime_->SetCalleeSaveMethod(runtime_->CreateCalleeSaveMethod(type), type);
}
}
}
diff --git a/runtime/arch/x86/context_x86.cc b/runtime/arch/x86/context_x86.cc
index c68d76a471..8c98d910c5 100644
--- a/runtime/arch/x86/context_x86.cc
+++ b/runtime/arch/x86/context_x86.cc
@@ -16,8 +16,9 @@
#include "context_x86.h"
-#include "mirror/art_method.h"
+#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
+#include "quick/quick_method_frame_info.h"
#include "stack.h"
namespace art {
@@ -37,16 +38,15 @@ void X86Context::Reset() {
void X86Context::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
- uint32_t core_spills = method->GetCoreSpillMask();
- size_t spill_count = POPCOUNT(core_spills);
- DCHECK_EQ(method->GetFpSpillMask(), 0u);
- size_t frame_size = method->GetFrameSizeInBytes();
+ const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
+ size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
+ DCHECK_EQ(frame_info.FpSpillMask(), 0u);
if (spill_count > 0) {
// Lowest number spill is farthest away, walk registers and fill into context.
int j = 2; // Offset j to skip return address spill.
for (int i = 0; i < kNumberOfCpuRegisters; i++) {
- if (((core_spills >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size);
+ if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
+ gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
j++;
}
}
diff --git a/runtime/arch/x86/quick_method_frame_info_x86.h b/runtime/arch/x86/quick_method_frame_info_x86.h
new file mode 100644
index 0000000000..b9dc0d8b19
--- /dev/null
+++ b/runtime/arch/x86/quick_method_frame_info_x86.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_QUICK_METHOD_FRAME_INFO_X86_H_
+#define ART_RUNTIME_ARCH_X86_QUICK_METHOD_FRAME_INFO_X86_H_
+
+#include "quick/quick_method_frame_info.h"
+#include "registers_x86.h"
+#include "runtime.h" // for Runtime::CalleeSaveType.
+
+namespace art {
+namespace x86 {
+
+static constexpr uint32_t kX86CalleeSaveRefSpills =
+ (1 << art::x86::EBP) | (1 << art::x86::ESI) | (1 << art::x86::EDI);
+static constexpr uint32_t kX86CalleeSaveArgSpills =
+ (1 << art::x86::ECX) | (1 << art::x86::EDX) | (1 << art::x86::EBX);
+
+constexpr uint32_t X86CalleeSaveCoreSpills(Runtime::CalleeSaveType type) {
+ return kX86CalleeSaveRefSpills | (type == Runtime::kRefsAndArgs ? kX86CalleeSaveArgSpills : 0) |
+ (1 << art::x86::kNumberOfCpuRegisters); // fake return address callee save
+}
+
+constexpr uint32_t X86CalleeSaveFrameSize(Runtime::CalleeSaveType type) {
+ return RoundUp((POPCOUNT(X86CalleeSaveCoreSpills(type)) /* gprs */ +
+ 1 /* Method* */) * kX86PointerSize, kStackAlignment);
+}
+
+constexpr QuickMethodFrameInfo X86CalleeSaveMethodFrameInfo(Runtime::CalleeSaveType type) {
+ return QuickMethodFrameInfo(X86CalleeSaveFrameSize(type),
+ X86CalleeSaveCoreSpills(type),
+ 0u);
+}
+
+} // namespace x86
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_X86_QUICK_METHOD_FRAME_INFO_X86_H_
diff --git a/runtime/arch/x86_64/context_x86_64.cc b/runtime/arch/x86_64/context_x86_64.cc
index 29a706593c..810ef9455a 100644
--- a/runtime/arch/x86_64/context_x86_64.cc
+++ b/runtime/arch/x86_64/context_x86_64.cc
@@ -16,8 +16,9 @@
#include "context_x86_64.h"
-#include "mirror/art_method.h"
+#include "mirror/art_method-inl.h"
#include "mirror/object-inl.h"
+#include "quick/quick_method_frame_info.h"
#include "stack.h"
namespace art {
@@ -40,17 +41,15 @@ void X86_64Context::Reset() {
void X86_64Context::FillCalleeSaves(const StackVisitor& fr) {
mirror::ArtMethod* method = fr.GetMethod();
- uint32_t core_spills = method->GetCoreSpillMask();
- uint32_t fp_core_spills = method->GetFpSpillMask();
- size_t spill_count = POPCOUNT(core_spills);
- size_t fp_spill_count = POPCOUNT(fp_core_spills);
- size_t frame_size = method->GetFrameSizeInBytes();
+ const QuickMethodFrameInfo frame_info = method->GetQuickFrameInfo();
+ size_t spill_count = POPCOUNT(frame_info.CoreSpillMask());
+ size_t fp_spill_count = POPCOUNT(frame_info.FpSpillMask());
if (spill_count > 0) {
// Lowest number spill is farthest away, walk registers and fill into context.
size_t j = 2; // Offset j to skip return address spill.
for (size_t i = 0; i < kNumberOfCpuRegisters; ++i) {
- if (((core_spills >> i) & 1) != 0) {
- gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_size);
+ if (((frame_info.CoreSpillMask() >> i) & 1) != 0) {
+ gprs_[i] = fr.CalleeSaveAddress(spill_count - j, frame_info.FrameSizeInBytes());
j++;
}
}
@@ -59,8 +58,9 @@ void X86_64Context::FillCalleeSaves(const StackVisitor& fr) {
// Lowest number spill is farthest away, walk registers and fill into context.
size_t j = 2; // Offset j to skip return address spill.
for (size_t i = 0; i < kNumberOfFloatRegisters; ++i) {
- if (((fp_core_spills >> i) & 1) != 0) {
- fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j, frame_size);
+ if (((frame_info.FpSpillMask() >> i) & 1) != 0) {
+ fprs_[i] = fr.CalleeSaveAddress(spill_count + fp_spill_count - j,
+ frame_info.FrameSizeInBytes());
j++;
}
}
diff --git a/runtime/arch/x86_64/quick_method_frame_info_x86_64.h b/runtime/arch/x86_64/quick_method_frame_info_x86_64.h
new file mode 100644
index 0000000000..618390903b
--- /dev/null
+++ b/runtime/arch/x86_64/quick_method_frame_info_x86_64.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_ARCH_X86_64_QUICK_METHOD_FRAME_INFO_X86_64_H_
+#define ART_RUNTIME_ARCH_X86_64_QUICK_METHOD_FRAME_INFO_X86_64_H_
+
+#include "quick/quick_method_frame_info.h"
+#include "registers_x86_64.h"
+#include "runtime.h" // for Runtime::CalleeSaveType.
+
+namespace art {
+namespace x86_64 {
+
+static constexpr uint32_t kX86_64CalleeSaveRefSpills =
+ (1 << art::x86_64::RBX) | (1 << art::x86_64::RBP) | (1 << art::x86_64::R12) |
+ (1 << art::x86_64::R13) | (1 << art::x86_64::R14) | (1 << art::x86_64::R15);
+static constexpr uint32_t kX86_64CalleeSaveArgSpills =
+ (1 << art::x86_64::RSI) | (1 << art::x86_64::RDX) | (1 << art::x86_64::RCX) |
+ (1 << art::x86_64::R8) | (1 << art::x86_64::R9);
+static constexpr uint32_t kX86_64CalleeSaveFpArgSpills =
+ (1 << art::x86_64::XMM0) | (1 << art::x86_64::XMM1) | (1 << art::x86_64::XMM2) |
+ (1 << art::x86_64::XMM3) | (1 << art::x86_64::XMM4) | (1 << art::x86_64::XMM5) |
+ (1 << art::x86_64::XMM6) | (1 << art::x86_64::XMM7);
+
+constexpr uint32_t X86_64CalleeSaveCoreSpills(Runtime::CalleeSaveType type) {
+ return kX86_64CalleeSaveRefSpills |
+ (type == Runtime::kRefsAndArgs ? kX86_64CalleeSaveArgSpills : 0) |
+ (1 << art::x86_64::kNumberOfCpuRegisters); // fake return address callee save;
+}
+
+constexpr uint32_t X86_64CalleeSaveFpSpills(Runtime::CalleeSaveType type) {
+ return (type == Runtime::kRefsAndArgs ? kX86_64CalleeSaveFpArgSpills : 0);
+}
+
+constexpr uint32_t X86_64CalleeSaveFrameSize(Runtime::CalleeSaveType type) {
+ return RoundUp((POPCOUNT(X86_64CalleeSaveCoreSpills(type)) /* gprs */ +
+ POPCOUNT(X86_64CalleeSaveFpSpills(type)) /* fprs */ +
+ 1 /* Method* */) * kX86_64PointerSize, kStackAlignment);
+}
+
+constexpr QuickMethodFrameInfo X86_64CalleeSaveMethodFrameInfo(Runtime::CalleeSaveType type) {
+ return QuickMethodFrameInfo(X86_64CalleeSaveFrameSize(type),
+ X86_64CalleeSaveCoreSpills(type),
+ X86_64CalleeSaveFpSpills(type));
+}
+
+} // namespace x86_64
+} // namespace art
+
+#endif // ART_RUNTIME_ARCH_X86_64_QUICK_METHOD_FRAME_INFO_X86_64_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e3c162bdef..b2d8b375b6 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1828,27 +1828,6 @@ static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::Oa
DCHECK(method->GetEntryPointFromQuickCompiledCode() ==
GetQuickResolutionTrampoline(runtime->GetClassLinker())
|| method->GetEntryPointFromQuickCompiledCode() == GetQuickGenericJniTrampoline());
-
- DCHECK_EQ(method->GetFrameSizeInBytes<false>(), 0U);
-
- // Fix up method metadata if necessary.
- uint32_t s_len;
- const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(dex_method_index), &s_len);
- uint32_t refs = 1; // Native method always has "this" or class.
- for (uint32_t i = 1; i < s_len; ++i) {
- if (shorty[i] == 'L') {
- refs++;
- }
- }
- size_t sirt_size = StackIndirectReferenceTable::GetAlignedSirtSize(refs);
-
- // Get the generic spill masks and base frame size.
- mirror::ArtMethod* callee_save_method =
- Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
-
- method->SetFrameSizeInBytes(callee_save_method->GetFrameSizeInBytes() + sirt_size);
- method->SetCoreSpillMask(callee_save_method->GetCoreSpillMask());
- method->SetFpSpillMask(callee_save_method->GetFpSpillMask());
}
}
@@ -3027,11 +3006,6 @@ mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self,
// At runtime the method looks like a reference and argument saving method, clone the code
// related parameters from this method.
- mirror::ArtMethod* refs_and_args =
- Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
- method->SetCoreSpillMask(refs_and_args->GetCoreSpillMask());
- method->SetFpSpillMask(refs_and_args->GetFpSpillMask());
- method->SetFrameSizeInBytes(refs_and_args->GetFrameSizeInBytes());
method->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler());
method->SetEntryPointFromPortableCompiledCode(GetPortableProxyInvokeHandler());
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 121835713a..b68ab4a237 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -491,9 +491,6 @@ struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> {
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex"));
offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_core_spill_mask_), "quickCoreSpillMask"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_fp_spill_mask_), "quickFpSpillMask"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_frame_size_in_bytes_), "quickFrameSizeInBytes"));
};
};
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index 97a8367688..feb2331cdc 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -72,9 +72,10 @@ class ExceptionTest : public CommonRuntimeTest {
const std::vector<uint8_t>& fake_vmap_table_data = fake_vmap_table_data_.GetData();
const std::vector<uint8_t>& fake_mapping_data = fake_mapping_data_.GetData();
- uint32_t vmap_table_offset = sizeof(OatMethodHeader) + fake_vmap_table_data.size();
+ uint32_t vmap_table_offset = sizeof(OatQuickMethodHeader) + fake_vmap_table_data.size();
uint32_t mapping_table_offset = vmap_table_offset + fake_mapping_data.size();
- OatMethodHeader method_header(vmap_table_offset, mapping_table_offset, code_size);
+ OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset,
+ 4 * kPointerSize, 0u, 0u, code_size);
fake_header_code_and_maps_.resize(sizeof(method_header));
memcpy(&fake_header_code_and_maps_[0], &method_header, sizeof(method_header));
fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(),
@@ -91,13 +92,11 @@ class ExceptionTest : public CommonRuntimeTest {
method_f_ = my_klass_->FindVirtualMethod("f", "()I");
ASSERT_TRUE(method_f_ != NULL);
- method_f_->SetFrameSizeInBytes(4 * kPointerSize);
method_f_->SetEntryPointFromQuickCompiledCode(code_ptr);
method_f_->SetNativeGcMap(&fake_gc_map_[0]);
method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
ASSERT_TRUE(method_g_ != NULL);
- method_g_->SetFrameSizeInBytes(4 * kPointerSize);
method_g_->SetEntryPointFromQuickCompiledCode(code_ptr);
method_g_->SetNativeGcMap(&fake_gc_map_[0]);
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 858582ee00..f1da6cdb68 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -245,21 +245,6 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat
return nullptr;
}
- Runtime* runtime = Runtime::Current();
- mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
- runtime->SetResolutionMethod(down_cast<mirror::ArtMethod*>(resolution_method));
- mirror::Object* imt_conflict_method = image_header.GetImageRoot(ImageHeader::kImtConflictMethod);
- runtime->SetImtConflictMethod(down_cast<mirror::ArtMethod*>(imt_conflict_method));
- mirror::Object* default_imt = image_header.GetImageRoot(ImageHeader::kDefaultImt);
- runtime->SetDefaultImt(down_cast<mirror::ObjectArray<mirror::ArtMethod>*>(default_imt));
-
- mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod);
- runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kSaveAll);
- callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod);
- runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsOnly);
- callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
- runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsAndArgs);
-
UniquePtr<ImageSpace> space(new ImageSpace(image_filename, image_location,
map.release(), bitmap.release()));
if (kIsDebugBuild) {
@@ -277,6 +262,23 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat
return nullptr;
}
+ Runtime* runtime = Runtime::Current();
+ runtime->SetInstructionSet(space->oat_file_->GetOatHeader().GetInstructionSet());
+
+ mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
+ runtime->SetResolutionMethod(down_cast<mirror::ArtMethod*>(resolution_method));
+ mirror::Object* imt_conflict_method = image_header.GetImageRoot(ImageHeader::kImtConflictMethod);
+ runtime->SetImtConflictMethod(down_cast<mirror::ArtMethod*>(imt_conflict_method));
+ mirror::Object* default_imt = image_header.GetImageRoot(ImageHeader::kDefaultImt);
+ runtime->SetDefaultImt(down_cast<mirror::ObjectArray<mirror::ArtMethod>*>(default_imt));
+
+ mirror::Object* callee_save_method = image_header.GetImageRoot(ImageHeader::kCalleeSaveMethod);
+ runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kSaveAll);
+ callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsOnlySaveMethod);
+ runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsOnly);
+ callee_save_method = image_header.GetImageRoot(ImageHeader::kRefsAndArgsSaveMethod);
+ runtime->SetCalleeSaveMethod(down_cast<mirror::ArtMethod*>(callee_save_method), Runtime::kRefsAndArgs);
+
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
LOG(INFO) << "ImageSpace::Init exiting (" << PrettyDuration(NanoTime() - start_time)
<< ") " << *space.get();
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index fb9a09a95f..91753df7f5 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -23,7 +23,8 @@
#include "entrypoints/entrypoint_utils.h"
#include "object_array.h"
#include "oat.h"
-#include "runtime.h"
+#include "quick/quick_method_frame_info.h"
+#include "runtime-inl.h"
namespace art {
namespace mirror {
@@ -81,7 +82,7 @@ inline uint32_t ArtMethod::GetCodeSize() {
if (code == nullptr) {
return 0u;
}
- return reinterpret_cast<const OatMethodHeader*>(code)[-1].code_size_;
+ return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_;
}
inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
@@ -201,6 +202,40 @@ inline void ArtMethod::SetNativeMethod(const void* native_method) {
OFFSET_OF_OBJECT_MEMBER(ArtMethod, entry_point_from_jni_), native_method);
}
+inline QuickMethodFrameInfo ArtMethod::GetQuickFrameInfo() {
+ if (UNLIKELY(IsPortableCompiled())) {
+ // Portable compiled dex bytecode or jni stub.
+ return QuickMethodFrameInfo(kStackAlignment, 0u, 0u);
+ }
+ Runtime* runtime = Runtime::Current();
+ if (UNLIKELY(IsAbstract()) || UNLIKELY(IsProxyMethod())) {
+ return runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
+ }
+ if (UNLIKELY(IsRuntimeMethod())) {
+ return runtime->GetRuntimeMethodFrameInfo(this);
+ }
+
+ const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this);
+ // On failure, instead of nullptr we get the quick-generic-jni-trampoline for native method
+ // indicating the generic JNI, or the quick-to-interpreter-bridge (but not the trampoline)
+ // for non-native methods. And we really shouldn't see a failure for non-native methods here.
+ DCHECK(entry_point != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker()));
+ CHECK(entry_point != GetQuickToInterpreterBridge());
+
+ if (UNLIKELY(entry_point == GetQuickGenericJniTrampoline())) {
+ // Generic JNI frame.
+ DCHECK(IsNative());
+ uint32_t sirt_refs = MethodHelper(this).GetNumberOfReferenceArgsWithoutReceiver() + 1;
+ size_t sirt_size = StackIndirectReferenceTable::GetAlignedSirtSize(sirt_refs);
+ QuickMethodFrameInfo callee_info = runtime->GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
+ return QuickMethodFrameInfo(callee_info.FrameSizeInBytes() + sirt_size,
+ callee_info.CoreSpillMask(), callee_info.FpSpillMask());
+ }
+
+ const void* code_pointer = EntryPointToCodePointer(entry_point);
+ return reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].frame_info_;
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 4275f25b05..eef60f7b01 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -389,7 +389,7 @@ const uint8_t* ArtMethod::GetMappingTable() {
if (code == nullptr) {
return nullptr;
}
- uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].mapping_table_offset_;
+ uint32_t offset = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].mapping_table_offset_;
if (UNLIKELY(offset == 0u)) {
return nullptr;
}
@@ -401,7 +401,7 @@ const uint8_t* ArtMethod::GetVmapTable() {
if (code == nullptr) {
return nullptr;
}
- uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].vmap_table_offset_;
+ uint32_t offset = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].vmap_table_offset_;
if (UNLIKELY(offset == 0u)) {
return nullptr;
}
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 71f0210486..49d22ab3a3 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -23,6 +23,7 @@
#include "modifiers.h"
#include "object.h"
#include "object_callbacks.h"
+#include "quick/quick_method_frame_info.h"
namespace art {
@@ -318,19 +319,14 @@ class MANAGED ArtMethod : public Object {
template <bool kCheckFrameSize = true>
uint32_t GetFrameSizeInBytes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uint32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_frame_size_in_bytes_));
+ uint32_t result = GetQuickFrameInfo().FrameSizeInBytes();
if (kCheckFrameSize) {
DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
}
return result;
}
- void SetFrameSizeInBytes(size_t new_frame_size_in_bytes)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // Not called within a transaction.
- SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_frame_size_in_bytes_),
- new_frame_size_in_bytes);
- }
+ QuickMethodFrameInfo GetQuickFrameInfo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
size_t GetReturnPcOffsetInBytes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetFrameSizeInBytes() - kPointerSize;
@@ -362,26 +358,6 @@ class MANAGED ArtMethod : public Object {
return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_);
}
- uint32_t GetCoreSpillMask() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_core_spill_mask_));
- }
-
- void SetCoreSpillMask(uint32_t core_spill_mask) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // Computed during compilation.
- // Not called within a transaction.
- SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_core_spill_mask_), core_spill_mask);
- }
-
- uint32_t GetFpSpillMask() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_fp_spill_mask_));
- }
-
- void SetFpSpillMask(uint32_t fp_spill_mask) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // Computed during compilation.
- // Not called within a transaction.
- SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_fp_spill_mask_), fp_spill_mask);
- }
-
// Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
// conventions for a method of managed code. Returns false for Proxy methods.
bool IsRuntimeMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -474,20 +450,6 @@ class MANAGED ArtMethod : public Object {
// ifTable.
uint32_t method_index_;
- // --- Quick compiler meta-data. ---
- // TODO: merge and place in native heap, such as done with the code size.
-
- // Bit map of spilled machine registers.
- uint32_t quick_core_spill_mask_;
-
- // Bit map of spilled floating point machine registers.
- uint32_t quick_fp_spill_mask_;
-
- // Fixed frame size for this method when executed.
- uint32_t quick_frame_size_in_bytes_;
-
- // --- End of quick compiler meta-data. ---
-
static Class* java_lang_reflect_ArtMethod_;
private:
diff --git a/runtime/oat.cc b/runtime/oat.cc
index a1f4fd0275..cb9334a120 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -22,7 +22,7 @@
namespace art {
const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
-const uint8_t OatHeader::kOatVersion[] = { '0', '2', '7', '\0' };
+const uint8_t OatHeader::kOatVersion[] = { '0', '2', '8', '\0' };
OatHeader::OatHeader() {
memset(this, 0, sizeof(*this));
@@ -345,40 +345,34 @@ std::string OatHeader::GetImageFileLocation() const {
OatMethodOffsets::OatMethodOffsets()
: code_offset_(0),
- frame_size_in_bytes_(0),
- core_spill_mask_(0),
- fp_spill_mask_(0),
gc_map_offset_(0)
{}
OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
- uint32_t frame_size_in_bytes,
- uint32_t core_spill_mask,
- uint32_t fp_spill_mask,
uint32_t gc_map_offset
)
: code_offset_(code_offset),
- frame_size_in_bytes_(frame_size_in_bytes),
- core_spill_mask_(core_spill_mask),
- fp_spill_mask_(fp_spill_mask),
gc_map_offset_(gc_map_offset)
{}
OatMethodOffsets::~OatMethodOffsets() {}
-OatMethodHeader::OatMethodHeader()
+OatQuickMethodHeader::OatQuickMethodHeader()
: mapping_table_offset_(0),
vmap_table_offset_(0),
+ frame_info_(0, 0, 0),
code_size_(0)
{}
-OatMethodHeader::OatMethodHeader(uint32_t vmap_table_offset, uint32_t mapping_table_offset,
- uint32_t code_size)
+OatQuickMethodHeader::OatQuickMethodHeader(
+ uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t frame_size_in_bytes,
+ uint32_t core_spill_mask, uint32_t fp_spill_mask, uint32_t code_size)
: mapping_table_offset_(mapping_table_offset),
vmap_table_offset_(vmap_table_offset),
+ frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask),
code_size_(code_size)
{}
-OatMethodHeader::~OatMethodHeader() {}
+OatQuickMethodHeader::~OatQuickMethodHeader() {}
} // namespace art
diff --git a/runtime/oat.h b/runtime/oat.h
index e9dfae993d..7be768c5cb 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -22,6 +22,7 @@
#include "base/macros.h"
#include "dex_file.h"
#include "instruction_set.h"
+#include "quick/quick_method_frame_info.h"
namespace art {
@@ -137,34 +138,31 @@ class PACKED(4) OatMethodOffsets {
OatMethodOffsets();
OatMethodOffsets(uint32_t code_offset,
- uint32_t frame_size_in_bytes,
- uint32_t core_spill_mask,
- uint32_t fp_spill_mask,
uint32_t gc_map_offset);
~OatMethodOffsets();
uint32_t code_offset_;
- uint32_t frame_size_in_bytes_;
- uint32_t core_spill_mask_;
- uint32_t fp_spill_mask_;
uint32_t gc_map_offset_;
};
-// OatMethodHeader precedes the raw code chunk generated by the Quick compiler.
-class PACKED(4) OatMethodHeader {
+// OatQuickMethodHeader precedes the raw code chunk generated by the Quick compiler.
+class PACKED(4) OatQuickMethodHeader {
public:
- OatMethodHeader();
+ OatQuickMethodHeader();
- explicit OatMethodHeader(uint32_t mapping_table_offset, uint32_t vmap_table_offset,
- uint32_t code_size);
+ explicit OatQuickMethodHeader(uint32_t mapping_table_offset, uint32_t vmap_table_offset,
+ uint32_t frame_size_in_bytes, uint32_t core_spill_mask,
+ uint32_t fp_spill_mask, uint32_t code_size);
- ~OatMethodHeader();
+ ~OatQuickMethodHeader();
// The offset in bytes from the start of the mapping table to the end of the header.
uint32_t mapping_table_offset_;
// The offset in bytes from the start of the vmap table to the end of the header.
uint32_t vmap_table_offset_;
+ // The stack frame information.
+ QuickMethodFrameInfo frame_info_;
// The code size in bytes.
uint32_t code_size_;
};
diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h
index 00ae7977b9..97ca6b2b37 100644
--- a/runtime/oat_file-inl.h
+++ b/runtime/oat_file-inl.h
@@ -21,6 +21,30 @@
namespace art {
+inline size_t OatFile::OatMethod::GetFrameSizeInBytes() const {
+ const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+ if (code == nullptr) {
+ return 0u;
+ }
+ return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].frame_info_.FrameSizeInBytes();
+}
+
+inline uint32_t OatFile::OatMethod::GetCoreSpillMask() const {
+ const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+ if (code == nullptr) {
+ return 0u;
+ }
+ return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].frame_info_.CoreSpillMask();
+}
+
+inline uint32_t OatFile::OatMethod::GetFpSpillMask() const {
+ const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+ if (code == nullptr) {
+ return 0u;
+ }
+ return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].frame_info_.FpSpillMask();
+}
+
inline uint32_t OatFile::OatMethod::GetMappingTableOffset() const {
const uint8_t* mapping_table = GetMappingTable();
return static_cast<uint32_t>(mapping_table != nullptr ? mapping_table - begin_ : 0u);
@@ -36,7 +60,7 @@ inline const uint8_t* OatFile::OatMethod::GetMappingTable() const {
if (code == nullptr) {
return nullptr;
}
- uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].mapping_table_offset_;
+ uint32_t offset = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].mapping_table_offset_;
if (UNLIKELY(offset == 0u)) {
return nullptr;
}
@@ -48,7 +72,7 @@ inline const uint8_t* OatFile::OatMethod::GetVmapTable() const {
if (code == nullptr) {
return nullptr;
}
- uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].vmap_table_offset_;
+ uint32_t offset = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].vmap_table_offset_;
if (UNLIKELY(offset == 0u)) {
return nullptr;
}
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 56e1f053cf..7976f6afea 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -464,7 +464,7 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index)
// NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
if (methods_pointer_ == NULL) {
CHECK_EQ(kOatClassNoneCompiled, type_);
- return OatMethod(NULL, 0, 0, 0, 0, 0);
+ return OatMethod(NULL, 0, 0);
}
size_t methods_pointer_index;
if (bitmap_ == NULL) {
@@ -473,7 +473,7 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index)
} else {
CHECK_EQ(kOatClassSomeCompiled, type_);
if (!BitVector::IsBitSet(bitmap_, method_index)) {
- return OatMethod(NULL, 0, 0, 0, 0, 0);
+ return OatMethod(NULL, 0, 0);
}
size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
methods_pointer_index = num_set_bits;
@@ -482,23 +482,14 @@ const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index)
return OatMethod(
oat_file_->Begin(),
oat_method_offsets.code_offset_,
- oat_method_offsets.frame_size_in_bytes_,
- oat_method_offsets.core_spill_mask_,
- oat_method_offsets.fp_spill_mask_,
oat_method_offsets.gc_map_offset_);
}
OatFile::OatMethod::OatMethod(const byte* base,
const uint32_t code_offset,
- const size_t frame_size_in_bytes,
- const uint32_t core_spill_mask,
- const uint32_t fp_spill_mask,
const uint32_t gc_map_offset)
: begin_(base),
code_offset_(code_offset),
- frame_size_in_bytes_(frame_size_in_bytes),
- core_spill_mask_(core_spill_mask),
- fp_spill_mask_(fp_spill_mask),
native_gc_map_offset_(gc_map_offset) {
}
@@ -519,9 +510,6 @@ void OatFile::OatMethod::LinkMethod(mirror::ArtMethod* method) const {
CHECK(method != NULL);
method->SetEntryPointFromPortableCompiledCode(GetPortableCode());
method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
- method->SetFrameSizeInBytes(frame_size_in_bytes_);
- method->SetCoreSpillMask(core_spill_mask_);
- method->SetFpSpillMask(fp_spill_mask_);
method->SetNativeGcMap(GetNativeGcMap()); // Used by native methods in work around JNI mode.
}
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index b358a00e60..8477723f1f 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -78,15 +78,6 @@ class OatFile {
uint32_t GetCodeOffset() const {
return code_offset_;
}
- size_t GetFrameSizeInBytes() const {
- return frame_size_in_bytes_;
- }
- uint32_t GetCoreSpillMask() const {
- return core_spill_mask_;
- }
- uint32_t GetFpSpillMask() const {
- return fp_spill_mask_;
- }
uint32_t GetNativeGcMapOffset() const {
return native_gc_map_offset_;
}
@@ -120,6 +111,9 @@ class OatFile {
return GetOatPointer<const uint8_t*>(native_gc_map_offset_);
}
+ size_t GetFrameSizeInBytes() const;
+ uint32_t GetCoreSpillMask() const;
+ uint32_t GetFpSpillMask() const;
uint32_t GetMappingTableOffset() const;
uint32_t GetVmapTableOffset() const;
const uint8_t* GetMappingTable() const;
@@ -130,9 +124,6 @@ class OatFile {
// Create an OatMethod with offsets relative to the given base address
OatMethod(const byte* base,
const uint32_t code_offset,
- const size_t frame_size_in_bytes,
- const uint32_t core_spill_mask,
- const uint32_t fp_spill_mask,
const uint32_t gc_map_offset);
private:
@@ -147,9 +138,6 @@ class OatFile {
const byte* begin_;
uint32_t code_offset_;
- size_t frame_size_in_bytes_;
- uint32_t core_spill_mask_;
- uint32_t fp_spill_mask_;
uint32_t native_gc_map_offset_;
friend class OatClass;
diff --git a/runtime/quick/quick_method_frame_info.h b/runtime/quick/quick_method_frame_info.h
new file mode 100644
index 0000000000..684d4da30e
--- /dev/null
+++ b/runtime/quick/quick_method_frame_info.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_QUICK_QUICK_METHOD_FRAME_INFO_H_
+#define ART_RUNTIME_QUICK_QUICK_METHOD_FRAME_INFO_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+
+namespace art {
+
+class PACKED(4) QuickMethodFrameInfo {
+ public:
+ constexpr QuickMethodFrameInfo()
+ : frame_size_in_bytes_(0u),
+ core_spill_mask_(0u),
+ fp_spill_mask_(0u) {
+ }
+
+ constexpr QuickMethodFrameInfo(uint32_t frame_size_in_bytes, uint32_t core_spill_mask,
+ uint32_t fp_spill_mask)
+ : frame_size_in_bytes_(frame_size_in_bytes),
+ core_spill_mask_(core_spill_mask),
+ fp_spill_mask_(fp_spill_mask) {
+ }
+
+ uint32_t FrameSizeInBytes() const {
+ return frame_size_in_bytes_;
+ }
+
+ uint32_t CoreSpillMask() const {
+ return core_spill_mask_;
+ }
+
+ uint32_t FpSpillMask() const {
+ return fp_spill_mask_;
+ }
+
+ private:
+ uint32_t frame_size_in_bytes_;
+ uint32_t core_spill_mask_;
+ uint32_t fp_spill_mask_;
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_QUICK_QUICK_METHOD_FRAME_INFO_H_
diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h
new file mode 100644
index 0000000000..29ddd1dc0b
--- /dev/null
+++ b/runtime/runtime-inl.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_RUNTIME_INL_H_
+#define ART_RUNTIME_RUNTIME_INL_H_
+
+#include "runtime.h"
+
+namespace art {
+
+inline QuickMethodFrameInfo Runtime::GetRuntimeMethodFrameInfo(mirror::ArtMethod* method) const {
+ DCHECK(method != nullptr);
+ // Cannot be imt-conflict-method or resolution-method.
+ DCHECK(method != GetImtConflictMethod());
+ DCHECK(method != GetResolutionMethod());
+ // Don't use GetCalleeSaveMethod(), some tests don't set all callee save methods.
+ if (method == callee_save_methods_[Runtime::kRefsAndArgs]) {
+ return GetCalleeSaveMethodFrameInfo(Runtime::kRefsAndArgs);
+ } else if (method == callee_save_methods_[Runtime::kSaveAll]) {
+ return GetCalleeSaveMethodFrameInfo(Runtime::kSaveAll);
+ } else {
+ DCHECK(method == callee_save_methods_[Runtime::kRefsOnly]);
+ return GetCalleeSaveMethodFrameInfo(Runtime::kRefsOnly);
+ }
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_RUNTIME_INL_H_
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index d78be92858..48322f0a16 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -30,10 +30,15 @@
#include <vector>
#include <fcntl.h>
+#include "arch/arm/quick_method_frame_info_arm.h"
#include "arch/arm/registers_arm.h"
+#include "arch/arm64/quick_method_frame_info_arm64.h"
#include "arch/arm64/registers_arm64.h"
+#include "arch/mips/quick_method_frame_info_mips.h"
#include "arch/mips/registers_mips.h"
+#include "arch/x86/quick_method_frame_info_x86.h"
#include "arch/x86/registers_x86.h"
+#include "arch/x86_64/quick_method_frame_info_x86_64.h"
#include "arch/x86_64/registers_x86_64.h"
#include "atomic.h"
#include "class_linker.h"
@@ -55,6 +60,7 @@
#include "monitor.h"
#include "parsed_options.h"
#include "oat_file.h"
+#include "quick/quick_method_frame_info.h"
#include "reflection.h"
#include "ScopedLocalRef.h"
#include "scoped_thread_state_change.h"
@@ -88,6 +94,7 @@ Runtime::Runtime()
resolution_method_(nullptr),
imt_conflict_method_(nullptr),
default_imt_(nullptr),
+ instruction_set_(kNone),
compiler_callbacks_(nullptr),
is_zygote_(false),
is_concurrent_gc_enabled_(true),
@@ -981,8 +988,7 @@ mirror::ArtMethod* Runtime::CreateResolutionMethod() {
return method.get();
}
-mirror::ArtMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set,
- CalleeSaveType type) {
+mirror::ArtMethod* Runtime::CreateCalleeSaveMethod(CalleeSaveType type) {
Thread* self = Thread::Current();
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
@@ -992,118 +998,7 @@ mirror::ArtMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_se
method->SetDexMethodIndex(DexFile::kDexNoIndex);
method->SetEntryPointFromPortableCompiledCode(nullptr);
method->SetEntryPointFromQuickCompiledCode(nullptr);
- if ((instruction_set == kThumb2) || (instruction_set == kArm)) {
- uint32_t ref_spills = (1 << art::arm::R5) | (1 << art::arm::R6) | (1 << art::arm::R7) |
- (1 << art::arm::R8) | (1 << art::arm::R10) | (1 << art::arm::R11);
- uint32_t arg_spills = (1 << art::arm::R1) | (1 << art::arm::R2) | (1 << art::arm::R3);
- uint32_t all_spills = (1 << art::arm::R4) | (1 << art::arm::R9);
- uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
- (type == kSaveAll ? all_spills : 0) | (1 << art::arm::LR);
- uint32_t fp_all_spills = (1 << art::arm::S0) | (1 << art::arm::S1) | (1 << art::arm::S2) |
- (1 << art::arm::S3) | (1 << art::arm::S4) | (1 << art::arm::S5) |
- (1 << art::arm::S6) | (1 << art::arm::S7) | (1 << art::arm::S8) |
- (1 << art::arm::S9) | (1 << art::arm::S10) | (1 << art::arm::S11) |
- (1 << art::arm::S12) | (1 << art::arm::S13) | (1 << art::arm::S14) |
- (1 << art::arm::S15) | (1 << art::arm::S16) | (1 << art::arm::S17) |
- (1 << art::arm::S18) | (1 << art::arm::S19) | (1 << art::arm::S20) |
- (1 << art::arm::S21) | (1 << art::arm::S22) | (1 << art::arm::S23) |
- (1 << art::arm::S24) | (1 << art::arm::S25) | (1 << art::arm::S26) |
- (1 << art::arm::S27) | (1 << art::arm::S28) | (1 << art::arm::S29) |
- (1 << art::arm::S30) | (1 << art::arm::S31);
- uint32_t fp_spills = type == kSaveAll ? fp_all_spills : 0;
- size_t frame_size = RoundUp((POPCOUNT(core_spills) /* gprs */ +
- POPCOUNT(fp_spills) /* fprs */ +
- 1 /* Method* */) * kArmPointerSize, kStackAlignment);
- method->SetFrameSizeInBytes(frame_size);
- method->SetCoreSpillMask(core_spills);
- method->SetFpSpillMask(fp_spills);
- } else if (instruction_set == kMips) {
- uint32_t ref_spills = (1 << art::mips::S2) | (1 << art::mips::S3) | (1 << art::mips::S4) |
- (1 << art::mips::S5) | (1 << art::mips::S6) | (1 << art::mips::S7) |
- (1 << art::mips::GP) | (1 << art::mips::FP);
- uint32_t arg_spills = (1 << art::mips::A1) | (1 << art::mips::A2) | (1 << art::mips::A3);
- uint32_t all_spills = (1 << art::mips::S0) | (1 << art::mips::S1);
- uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
- (type == kSaveAll ? all_spills : 0) | (1 << art::mips::RA);
- size_t frame_size = RoundUp((POPCOUNT(core_spills) /* gprs */ +
- (type == kRefsAndArgs ? 0 : 3) + 1 /* Method* */) *
- kMipsPointerSize, kStackAlignment);
- method->SetFrameSizeInBytes(frame_size);
- method->SetCoreSpillMask(core_spills);
- method->SetFpSpillMask(0);
- } else if (instruction_set == kX86) {
- uint32_t ref_spills = (1 << art::x86::EBP) | (1 << art::x86::ESI) | (1 << art::x86::EDI);
- uint32_t arg_spills = (1 << art::x86::ECX) | (1 << art::x86::EDX) | (1 << art::x86::EBX);
- uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
- (1 << art::x86::kNumberOfCpuRegisters); // fake return address callee save
- size_t frame_size = RoundUp((POPCOUNT(core_spills) /* gprs */ +
- 1 /* Method* */) * kX86PointerSize, kStackAlignment);
- method->SetFrameSizeInBytes(frame_size);
- method->SetCoreSpillMask(core_spills);
- method->SetFpSpillMask(0);
- } else if (instruction_set == kX86_64) {
- uint32_t ref_spills =
- (1 << art::x86_64::RBX) | (1 << art::x86_64::RBP) | (1 << art::x86_64::R12) |
- (1 << art::x86_64::R13) | (1 << art::x86_64::R14) | (1 << art::x86_64::R15);
- uint32_t arg_spills =
- (1 << art::x86_64::RSI) | (1 << art::x86_64::RDX) | (1 << art::x86_64::RCX) |
- (1 << art::x86_64::R8) | (1 << art::x86_64::R9);
- uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
- (1 << art::x86_64::kNumberOfCpuRegisters); // fake return address callee save
- uint32_t fp_arg_spills =
- (1 << art::x86_64::XMM0) | (1 << art::x86_64::XMM1) | (1 << art::x86_64::XMM2) |
- (1 << art::x86_64::XMM3) | (1 << art::x86_64::XMM4) | (1 << art::x86_64::XMM5) |
- (1 << art::x86_64::XMM6) | (1 << art::x86_64::XMM7);
- uint32_t fp_spills = (type == kRefsAndArgs ? fp_arg_spills : 0);
- size_t frame_size = RoundUp((POPCOUNT(core_spills) /* gprs */ +
- POPCOUNT(fp_spills) /* fprs */ +
- 1 /* Method* */) * kX86_64PointerSize, kStackAlignment);
- method->SetFrameSizeInBytes(frame_size);
- method->SetCoreSpillMask(core_spills);
- method->SetFpSpillMask(fp_spills);
- } else if (instruction_set == kArm64) {
- // Callee saved registers
- uint32_t ref_spills = (1 << art::arm64::X19) | (1 << art::arm64::X20) | (1 << art::arm64::X21) |
- (1 << art::arm64::X22) | (1 << art::arm64::X23) | (1 << art::arm64::X24) |
- (1 << art::arm64::X25) | (1 << art::arm64::X26) | (1 << art::arm64::X27) |
- (1 << art::arm64::X28);
- // X0 is the method pointer. Not saved.
- uint32_t arg_spills = (1 << art::arm64::X1) | (1 << art::arm64::X2) | (1 << art::arm64::X3) |
- (1 << art::arm64::X4) | (1 << art::arm64::X5) | (1 << art::arm64::X6) |
- (1 << art::arm64::X7);
- // TODO This is conservative. Only ALL should include the thread register.
- // The thread register is not preserved by the aapcs64.
- // LR is always saved.
- uint32_t all_spills = 0; // (1 << art::arm64::LR);
- uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
- (type == kSaveAll ? all_spills : 0) | (1 << art::arm64::FP)
- | (1 << art::arm64::X18) | (1 << art::arm64::LR);
-
- // Save callee-saved floating point registers. Rest are scratch/parameters.
- uint32_t fp_arg_spills = (1 << art::arm64::D0) | (1 << art::arm64::D1) | (1 << art::arm64::D2) |
- (1 << art::arm64::D3) | (1 << art::arm64::D4) | (1 << art::arm64::D5) |
- (1 << art::arm64::D6) | (1 << art::arm64::D7);
- uint32_t fp_ref_spills = (1 << art::arm64::D8) | (1 << art::arm64::D9) | (1 << art::arm64::D10) |
- (1 << art::arm64::D11) | (1 << art::arm64::D12) | (1 << art::arm64::D13) |
- (1 << art::arm64::D14) | (1 << art::arm64::D15);
- uint32_t fp_all_spills = fp_arg_spills |
- (1 << art::arm64::D16) | (1 << art::arm64::D17) | (1 << art::arm64::D18) |
- (1 << art::arm64::D19) | (1 << art::arm64::D20) | (1 << art::arm64::D21) |
- (1 << art::arm64::D22) | (1 << art::arm64::D23) | (1 << art::arm64::D24) |
- (1 << art::arm64::D25) | (1 << art::arm64::D26) | (1 << art::arm64::D27) |
- (1 << art::arm64::D28) | (1 << art::arm64::D29) | (1 << art::arm64::D30) |
- (1 << art::arm64::D31);
- uint32_t fp_spills = fp_ref_spills | (type == kRefsAndArgs ? fp_arg_spills: 0)
- | (type == kSaveAll ? fp_all_spills : 0);
- size_t frame_size = RoundUp((POPCOUNT(core_spills) /* gprs */ +
- POPCOUNT(fp_spills) /* fprs */ +
- 1 /* Method* */) * kArm64PointerSize, kStackAlignment);
- method->SetFrameSizeInBytes(frame_size);
- method->SetCoreSpillMask(core_spills);
- method->SetFpSpillMask(fp_spills);
- } else {
- UNIMPLEMENTED(FATAL) << instruction_set;
- }
+ DCHECK_NE(instruction_set_, kNone);
return method.get();
}
@@ -1121,6 +1016,38 @@ void Runtime::AllowNewSystemWeaks() {
Dbg::AllowNewObjectRegistryObjects();
}
+void Runtime::SetInstructionSet(InstructionSet instruction_set) {
+ instruction_set_ = instruction_set;
+ if ((instruction_set_ == kThumb2) || (instruction_set_ == kArm)) {
+ for (int i = 0; i != kLastCalleeSaveType; ++i) {
+ CalleeSaveType type = static_cast<CalleeSaveType>(i);
+ callee_save_method_frame_infos_[i] = arm::ArmCalleeSaveMethodFrameInfo(type);
+ }
+ } else if (instruction_set_ == kMips) {
+ for (int i = 0; i != kLastCalleeSaveType; ++i) {
+ CalleeSaveType type = static_cast<CalleeSaveType>(i);
+ callee_save_method_frame_infos_[i] = mips::MipsCalleeSaveMethodFrameInfo(type);
+ }
+ } else if (instruction_set_ == kX86) {
+ for (int i = 0; i != kLastCalleeSaveType; ++i) {
+ CalleeSaveType type = static_cast<CalleeSaveType>(i);
+ callee_save_method_frame_infos_[i] = x86::X86CalleeSaveMethodFrameInfo(type);
+ }
+ } else if (instruction_set_ == kX86_64) {
+ for (int i = 0; i != kLastCalleeSaveType; ++i) {
+ CalleeSaveType type = static_cast<CalleeSaveType>(i);
+ callee_save_method_frame_infos_[i] = x86_64::X86_64CalleeSaveMethodFrameInfo(type);
+ }
+ } else if (instruction_set_ == kArm64) {
+ for (int i = 0; i != kLastCalleeSaveType; ++i) {
+ CalleeSaveType type = static_cast<CalleeSaveType>(i);
+ callee_save_method_frame_infos_[i] = arm64::Arm64CalleeSaveMethodFrameInfo(type);
+ }
+ } else {
+ UNIMPLEMENTED(FATAL) << instruction_set_;
+ }
+}
+
void Runtime::SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type) {
DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastCalleeSaveType));
callee_save_methods_[type] = method;
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 1ee0b1add3..07b47c3619 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -34,6 +34,7 @@
#include "instrumentation.h"
#include "jobject_comparator.h"
#include "object_callbacks.h"
+#include "quick/quick_method_frame_info.h"
#include "runtime_stats.h"
#include "safe_map.h"
#include "fault_handler.h"
@@ -325,20 +326,25 @@ class Runtime {
return callee_save_methods_[type];
}
+ QuickMethodFrameInfo GetCalleeSaveMethodFrameInfo(CalleeSaveType type) const {
+ return callee_save_method_frame_infos_[type];
+ }
+
+ QuickMethodFrameInfo GetRuntimeMethodFrameInfo(mirror::ArtMethod* method) const;
+
static size_t GetCalleeSaveMethodOffset(CalleeSaveType type) {
return OFFSETOF_MEMBER(Runtime, callee_save_methods_[type]);
}
- void SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type);
+ InstructionSet GetInstructionSet() const {
+ return instruction_set_;
+ }
- mirror::ArtMethod* CreateCalleeSaveMethod(InstructionSet instruction_set,
- CalleeSaveType type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetInstructionSet(InstructionSet instruction_set);
- mirror::ArtMethod* CreateRefOnlyCalleeSaveMethod(InstructionSet instruction_set)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void SetCalleeSaveMethod(mirror::ArtMethod* method, CalleeSaveType type);
- mirror::ArtMethod* CreateRefAndArgsCalleeSaveMethod(InstructionSet instruction_set)
+ mirror::ArtMethod* CreateCalleeSaveMethod(CalleeSaveType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
int32_t GetStat(int kind);
@@ -468,6 +474,9 @@ class Runtime {
mirror::ArtMethod* imt_conflict_method_;
mirror::ObjectArray<mirror::ArtMethod>* default_imt_;
+ InstructionSet instruction_set_;
+ QuickMethodFrameInfo callee_save_method_frame_infos_[kLastCalleeSaveType];
+
CompilerCallbacks* compiler_callbacks_;
bool is_zygote_;
bool is_concurrent_gc_enabled_;
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 5e64e597f9..b984aa6032 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -23,6 +23,7 @@
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "object_utils.h"
+#include "quick/quick_method_frame_info.h"
#include "runtime.h"
#include "thread.h"
#include "thread_list.h"
@@ -142,18 +143,17 @@ uint32_t StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kin
DCHECK(m == GetMethod());
const VmapTable vmap_table(m->GetVmapTable());
uint32_t vmap_offset;
+ QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo();
// TODO: IsInContext stops before spotting floating point registers.
if (vmap_table.IsInContext(vreg, kind, &vmap_offset)) {
bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
- uint32_t spill_mask = is_float ? m->GetFpSpillMask()
- : m->GetCoreSpillMask();
+ uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask();
return GetGPR(vmap_table.ComputeRegister(spill_mask, vmap_offset, kind));
} else {
const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions?
- size_t frame_size = m->GetFrameSizeInBytes();
- return *GetVRegAddr(cur_quick_frame_, code_item, m->GetCoreSpillMask(), m->GetFpSpillMask(),
- frame_size, vreg);
+ return *GetVRegAddr(cur_quick_frame_, code_item, frame_info.CoreSpillMask(),
+ frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), vreg);
}
} else {
return cur_shadow_frame_->GetVReg(vreg);
@@ -167,19 +167,18 @@ void StackVisitor::SetVReg(mirror::ArtMethod* m, uint16_t vreg, uint32_t new_val
DCHECK(m == GetMethod());
const VmapTable vmap_table(m->GetVmapTable());
uint32_t vmap_offset;
+ QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo();
// TODO: IsInContext stops before spotting floating point registers.
if (vmap_table.IsInContext(vreg, kind, &vmap_offset)) {
bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
- uint32_t spill_mask = is_float ? m->GetFpSpillMask() : m->GetCoreSpillMask();
+ uint32_t spill_mask = is_float ? frame_info.FpSpillMask() : frame_info.CoreSpillMask();
const uint32_t reg = vmap_table.ComputeRegister(spill_mask, vmap_offset, kReferenceVReg);
SetGPR(reg, new_value);
} else {
const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions?
- 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, kRuntimeISA);
+ int offset = GetVRegOffset(code_item, frame_info.CoreSpillMask(), frame_info.FpSpillMask(),
+ frame_info.FrameSizeInBytes(), vreg, kRuntimeISA);
byte* vreg_addr = reinterpret_cast<byte*>(GetCurrentQuickFrame()) + offset;
*reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
}
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 00a66d7e36..7ed0cb4ea9 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -55,6 +55,7 @@
#include "monitor.h"
#include "object_utils.h"
#include "quick_exception_handler.h"
+#include "quick/quick_method_frame_info.h"
#include "reflection.h"
#include "runtime.h"
#include "scoped_thread_state_change.h"
@@ -2019,9 +2020,7 @@ class ReferenceMapVisitor : public StackVisitor {
const uint8_t* reg_bitmap = map.FindBitMap(GetNativePcOffset());
DCHECK(reg_bitmap != nullptr);
const VmapTable vmap_table(m->GetVmapTable());
- uint32_t core_spills = m->GetCoreSpillMask();
- uint32_t fp_spills = m->GetFpSpillMask();
- size_t frame_size = m->GetFrameSizeInBytes();
+ QuickMethodFrameInfo frame_info = m->GetQuickFrameInfo();
// For all dex registers in the bitmap
mirror::ArtMethod** cur_quick_frame = GetCurrentQuickFrame();
DCHECK(cur_quick_frame != nullptr);
@@ -2030,7 +2029,8 @@ class ReferenceMapVisitor : public StackVisitor {
if (TestBitmap(reg, reg_bitmap)) {
uint32_t vmap_offset;
if (vmap_table.IsInContext(reg, kReferenceVReg, &vmap_offset)) {
- int vmap_reg = vmap_table.ComputeRegister(core_spills, vmap_offset, kReferenceVReg);
+ int vmap_reg = vmap_table.ComputeRegister(frame_info.CoreSpillMask(), vmap_offset,
+ kReferenceVReg);
// This is sound as spilled GPRs will be word sized (ie 32 or 64bit).
mirror::Object** ref_addr = reinterpret_cast<mirror::Object**>(GetGPRAddress(vmap_reg));
if (*ref_addr != nullptr) {
@@ -2039,8 +2039,8 @@ class ReferenceMapVisitor : public StackVisitor {
} else {
StackReference<mirror::Object>* ref_addr =
reinterpret_cast<StackReference<mirror::Object>*>(
- GetVRegAddr(cur_quick_frame, code_item, core_spills, fp_spills, frame_size,
- reg));
+ GetVRegAddr(cur_quick_frame, code_item, frame_info.CoreSpillMask(),
+ frame_info.FpSpillMask(), frame_info.FrameSizeInBytes(), reg));
mirror::Object* ref = ref_addr->AsMirrorPtr();
if (ref != nullptr) {
mirror::Object* new_ref = ref;