summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2014-05-02 14:40:15 +0100
committerVladimir Marko <vmarko@google.com>2014-05-13 11:43:22 +0100
commit7624d25dad2d1ba25969ae704fccf68649103ae5 (patch)
treede72194b76a4e23e0b15ec4085447ae7e4425815
parente1910f1d802dff79bba5ef61e1c4fd0b95f6e5b0 (diff)
downloadart-7624d25dad2d1ba25969ae704fccf68649103ae5.zip
art-7624d25dad2d1ba25969ae704fccf68649103ae5.tar.gz
art-7624d25dad2d1ba25969ae704fccf68649103ae5.tar.bz2
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 8bba84a..8f39212 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 4dfa29a..52490e6 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 b5d3923..66972cb 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 bbc9c3e..39311d9 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 7cdd532..85c9b47 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 3529c27..c2af767 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 c285088..b957d58 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 0e1b25e..6a337b3 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 0000000..8d08190
--- /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 0890fa9..fae44af 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 0000000..cb830ac
--- /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 0950e71..ad28891 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 0000000..2a8bcf0
--- /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 1d05540..5e8edf0 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 c68d76a..8c98d91 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 0000000..b9dc0d8
--- /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 29a7065..810ef94 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 0000000..6183909
--- /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 e3c162b..b2d8b37 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 1218357..b68ab4a 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 97a8367..feb2331 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 858582e..f1da6cd 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 fb9a09a..91753df 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 4275f25..eef60f7 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 71f0210..49d22ab 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 a1f4fd0..cb9334a 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 e9dfae9..7be768c 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 00ae797..97ca6b2 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 56e1f05..7976f6a 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 b358a00..8477723 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 0000000..684d4da
--- /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 0000000..29ddd1d
--- /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 d78be92..48322f0 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 1ee0b1a..07b47c3 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 5e64e59..b984aa6 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 00a66d7..7ed0cb4 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;