summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/common_compiler_test.cc9
-rw-r--r--compiler/common_compiler_test.h2
-rw-r--r--compiler/image_writer.cc6
-rw-r--r--compiler/oat_test.cc4
-rw-r--r--compiler/oat_writer.cc32
-rw-r--r--oatdump/oatdump.cc22
-rw-r--r--patchoat/patchoat.cc6
-rw-r--r--runtime/asm_support.h4
-rw-r--r--runtime/check_reference_map_visitor.h2
-rw-r--r--runtime/class_linker.cc25
-rw-r--r--runtime/entrypoints/portable/portable_thread_entrypoints.cc2
-rw-r--r--runtime/exception_test.cc9
-rw-r--r--runtime/mirror/art_method-inl.h21
-rw-r--r--runtime/mirror/art_method.h40
-rw-r--r--runtime/oat.cc36
-rw-r--r--runtime/oat.h17
-rw-r--r--runtime/oat_file-inl.h25
-rw-r--r--runtime/oat_file.cc10
-rw-r--r--runtime/oat_file.h21
-rw-r--r--runtime/thread.cc4
20 files changed, 131 insertions, 166 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index 97387a1..a3d9a0b 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -60,14 +60,18 @@ void CommonCompilerTest::MakeExecutable(mirror::ArtMethod* method) {
const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable();
uint32_t mapping_table_offset = mapping_table.empty() ? 0u
: sizeof(OatQuickMethodHeader) + vmap_table.size() + mapping_table.size();
- OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset,
+ const std::vector<uint8_t>& gc_map = *compiled_method->GetGcMap();
+ uint32_t gc_map_offset = gc_map.empty() ? 0u
+ : sizeof(OatQuickMethodHeader) + vmap_table.size() + mapping_table.size() + gc_map.size();
+ OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset, gc_map_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();
- size_t size = sizeof(method_header) + code_size + vmap_table.size() + mapping_table.size();
+ size_t size = sizeof(method_header) + code_size + vmap_table.size() + mapping_table.size() +
+ gc_map.size();
size_t code_offset = compiled_method->AlignCode(size - code_size);
size_t padding = code_offset - (size - code_size);
chunk->reserve(padding + size);
@@ -75,6 +79,7 @@ void CommonCompilerTest::MakeExecutable(mirror::ArtMethod* method) {
memcpy(&(*chunk)[0], &method_header, sizeof(method_header));
chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end());
chunk->insert(chunk->begin(), mapping_table.begin(), mapping_table.end());
+ chunk->insert(chunk->begin(), gc_map.begin(), gc_map.end());
chunk->insert(chunk->begin(), padding, 0);
chunk->insert(chunk->end(), code->begin(), code->end());
CHECK_EQ(padding + size, chunk->size());
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index 20b750c..9cffbc8 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -42,7 +42,7 @@ class CommonCompilerTest : public CommonRuntimeTest {
~CommonCompilerTest();
// Create an OatMethod based on pointers (for unit tests).
- OatFile::OatMethod CreateOatMethod(const void* code, const uint8_t* gc_map);
+ OatFile::OatMethod CreateOatMethod(const void* code);
void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 4f5026d..03899cc 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -1125,7 +1125,6 @@ void ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) {
copy->SetEntryPointFromJniPtrSize<kVerifyNone>(orig->GetEntryPointFromJni(), target_ptr_size_);
copy->SetEntryPointFromQuickCompiledCodePtrSize<kVerifyNone>(
orig->GetEntryPointFromQuickCompiledCode(), target_ptr_size_);
- copy->SetNativeGcMapPtrSize<kVerifyNone>(orig->GetNativeGcMap(), target_ptr_size_);
// The resolution method has a special trampoline to call.
Runtime* runtime = Runtime::Current();
@@ -1186,11 +1185,6 @@ void ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) {
// Note this is not the code_ pointer, that is handled above.
copy->SetEntryPointFromJniPtrSize<kVerifyNone>(GetOatAddress(jni_dlsym_lookup_offset_),
target_ptr_size_);
- } else {
- // Normal (non-abstract non-native) methods have various tables to relocate.
- uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset();
- const uint8_t* native_gc_map = GetOatAddress(native_gc_map_offset);
- copy->SetNativeGcMapPtrSize<kVerifyNone>(native_gc_map, target_ptr_size_);
}
// Interpreter entrypoint:
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index ce4ed6d..9fe98e3 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -190,8 +190,8 @@ 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(84U, sizeof(OatHeader));
- EXPECT_EQ(8U, sizeof(OatMethodOffsets));
- EXPECT_EQ(24U, sizeof(OatQuickMethodHeader));
+ EXPECT_EQ(4U, sizeof(OatMethodOffsets));
+ EXPECT_EQ(28U, sizeof(OatQuickMethodHeader));
EXPECT_EQ(91 * GetInstructionSetPointerSize(kRuntimeISA), sizeof(QuickEntryPoints));
}
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index c6beb36..a57f892 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -510,15 +510,18 @@ struct OatWriter::GcMapDataAccess {
}
static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
- return oat_class->method_offsets_[method_offsets_index].gc_map_offset_;
+ uint32_t offset = oat_class->method_headers_[method_offsets_index].gc_map_offset_;
+ return offset == 0u ? 0u :
+ (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
}
static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
ALWAYS_INLINE {
- oat_class->method_offsets_[method_offsets_index].gc_map_offset_ = offset;
+ oat_class->method_headers_[method_offsets_index].gc_map_offset_ =
+ (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
}
- static const char* Name() ALWAYS_INLINE {
+ static const char* Name() {
return "GC map";
}
};
@@ -540,7 +543,7 @@ struct OatWriter::MappingTableDataAccess {
(oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
}
- static const char* Name() ALWAYS_INLINE {
+ static const char* Name() {
return "mapping table";
}
};
@@ -562,7 +565,7 @@ struct OatWriter::VmapTableDataAccess {
(oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
}
- static const char* Name() ALWAYS_INLINE {
+ static const char* Name() {
return "vmap table";
}
};
@@ -764,6 +767,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
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_;
+ uint32_t gc_map_offset = method_header->gc_map_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;
@@ -775,12 +779,16 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor {
vmap_table_offset += code_offset;
DCHECK_LT(vmap_table_offset, code_offset);
}
+ if (gc_map_offset != 0u) {
+ gc_map_offset += code_offset;
+ DCHECK_LT(gc_map_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);
+ gc_map_offset, frame_size_in_bytes, core_spill_mask,
+ fp_spill_mask, code_size);
if (!deduped) {
// Update offsets. (Checksum is updated when writing.)
@@ -909,7 +917,7 @@ 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, 0u);
+ OatMethodOffsets offsets(0u);
if (compiled_method != nullptr) {
DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
offsets = oat_class->method_offsets_[method_offsets_index_];
@@ -920,7 +928,7 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
InvokeType invoke_type = it.GetMethodInvokeType(dex_file_->GetClassDef(class_def_index_));
// Unchecked as we hold mutator_lock_ on entry.
ScopedObjectAccessUnchecked soa(Thread::Current());
- StackHandleScope<2> hs(soa.Self());
+ StackHandleScope<1> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file_)));
mirror::ArtMethod* method = linker->ResolveMethod(*dex_file_, it.GetMemberIndex(), dex_cache,
NullHandle<mirror::ClassLoader>(),
@@ -936,7 +944,6 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
}
// Portable code offsets are set by ElfWriterMclinker::FixupCompiledCodeOffset after linking.
method->SetQuickOatCodeOffset(offsets.code_offset_);
- method->SetOatNativeGcMapOffset(offsets.gc_map_offset_);
return true;
}
@@ -1157,7 +1164,7 @@ template <typename DataAccess>
class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
public:
WriteMapMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset,
- size_t relative_offset)
+ size_t relative_offset)
: OatDexMethodVisitor(writer, relative_offset),
out_(out),
file_offset_(file_offset) {
@@ -1179,7 +1186,8 @@ class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
size_t map_size = map == nullptr ? 0 : map->size() * sizeof((*map)[0]);
DCHECK((map_size == 0u && map_offset == 0u) ||
(map_size != 0u && map_offset != 0u && map_offset <= offset_))
- << PrettyMethod(it.GetMemberIndex(), *dex_file_);
+ << map_size << " " << map_offset << " " << offset_ << " "
+ << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " for " << DataAccess::Name();
if (map_size != 0u && map_offset == offset_) {
if (UNLIKELY(!out->WriteFully(&(*map)[0], map_size))) {
ReportWriteFailure(it);
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 08352de..d28b626 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -605,7 +605,7 @@ class OatDumper {
offsets_.insert(code_offset);
offsets_.insert(oat_method.GetMappingTableOffset());
offsets_.insert(oat_method.GetVmapTableOffset());
- offsets_.insert(oat_method.GetNativeGcMapOffset());
+ offsets_.insert(oat_method.GetGcMapOffset());
}
bool DumpOatDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
@@ -755,9 +755,9 @@ class OatDumper {
*indent2_os << "gc_map: ";
if (options_->absolute_addresses_) {
- *indent2_os << StringPrintf("%p ", oat_method.GetNativeGcMap());
+ *indent2_os << StringPrintf("%p ", oat_method.GetGcMap());
}
- uint32_t gc_map_offset = oat_method.GetNativeGcMapOffset();
+ uint32_t gc_map_offset = oat_method.GetGcMapOffset();
*indent2_os << StringPrintf("(offset=0x%08x)\n", gc_map_offset);
if (gc_map_offset > oat_file_.Size()) {
*indent2_os << StringPrintf("WARNING: "
@@ -935,7 +935,7 @@ class OatDumper {
// If the native GC map is null, then this method has been compiled with the
// optimizing compiler. The optimizing compiler currently outputs its stack map
// in the vmap table, and the code below does not work with such a stack map.
- if (oat_method.GetNativeGcMap() == nullptr) {
+ if (oat_method.GetGcMap() == nullptr) {
return;
}
const uint8_t* raw_table = oat_method.GetVmapTable();
@@ -1050,7 +1050,7 @@ class OatDumper {
}
void DumpGcMap(std::ostream& os, const OatFile::OatMethod& oat_method,
const DexFile::CodeItem* code_item) {
- const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
+ const uint8_t* gc_map_raw = oat_method.GetGcMap();
if (gc_map_raw == nullptr) {
return; // No GC map.
}
@@ -1128,7 +1128,7 @@ class OatDumper {
void DumpGcMapAtNativePcOffset(std::ostream& os, const OatFile::OatMethod& oat_method,
const DexFile::CodeItem* code_item, size_t native_pc_offset) {
- const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
+ const uint8_t* gc_map_raw = oat_method.GetGcMap();
if (gc_map_raw != nullptr) {
NativePcOffsetToReferenceMap map(gc_map_raw);
if (map.HasEntry(native_pc_offset)) {
@@ -1634,8 +1634,7 @@ class ImageDumper {
mirror::ArtMethod* method = obj->AsArtMethod();
if (method->IsNative()) {
// TODO: portable dumping.
- DCHECK(method->GetNativeGcMapPtrSize(image_pointer_size) == nullptr)
- << PrettyMethod(method);
+ DCHECK(method->GetNativeGcMap(image_pointer_size) == nullptr) << PrettyMethod(method);
DCHECK(method->GetMappingTable(image_pointer_size) == nullptr) << PrettyMethod(method);
bool first_occurrence;
const void* quick_oat_code = state->GetQuickOatCodeBegin(method);
@@ -1651,8 +1650,7 @@ class ImageDumper {
} else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
method->IsResolutionMethod() || method->IsImtConflictMethod() ||
method->IsImtUnimplementedMethod() || method->IsClassInitializer()) {
- DCHECK(method->GetNativeGcMapPtrSize(image_pointer_size) == nullptr)
- << PrettyMethod(method);
+ DCHECK(method->GetNativeGcMap(image_pointer_size) == nullptr) << PrettyMethod(method);
DCHECK(method->GetMappingTable(image_pointer_size) == nullptr) << PrettyMethod(method);
} else {
const DexFile::CodeItem* code_item = method->GetCodeItem();
@@ -1660,8 +1658,8 @@ class ImageDumper {
state->stats_.dex_instruction_bytes += dex_instruction_bytes;
bool first_occurrence;
- size_t gc_map_bytes = state->ComputeOatSize(
- method->GetNativeGcMapPtrSize(image_pointer_size), &first_occurrence);
+ size_t gc_map_bytes =
+ state->ComputeOatSize(method->GetNativeGcMap(image_pointer_size), &first_occurrence);
if (first_occurrence) {
state->stats_.gc_map_bytes += gc_map_bytes;
}
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index b15c712..68fd15b 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -565,12 +565,6 @@ void PatchOat::FixupMethod(mirror::ArtMethod* object, mirror::ArtMethod* copy) {
copy->SetEntryPointFromJniPtrSize(reinterpret_cast<void*>(native_method + delta_),
pointer_size);
}
-
- uintptr_t native_gc_map = reinterpret_cast<uintptr_t>(
- object->GetNativeGcMapPtrSize(pointer_size));
- if (native_gc_map != 0) {
- copy->SetNativeGcMapPtrSize(reinterpret_cast<uint8_t*>(native_gc_map + delta_), pointer_size);
- }
}
bool PatchOat::Patch(File* input_oat, off_t delta, File* output_oat, TimingLogger* timings,
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 4b4c885..c737ec9 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -148,7 +148,7 @@ ADD_TEST_EQ(MIRROR_STRING_OFFSET_OFFSET, art::mirror::String::OffsetOffset().Int
ADD_TEST_EQ(MIRROR_ART_METHOD_DEX_CACHE_METHODS_OFFSET,
art::mirror::ArtMethod::DexCacheResolvedMethodsOffset().Int32Value())
-#define MIRROR_ART_METHOD_PORTABLE_CODE_OFFSET_32 (48 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_ART_METHOD_PORTABLE_CODE_OFFSET_32 (44 + MIRROR_OBJECT_HEADER_SIZE)
ADD_TEST_EQ(MIRROR_ART_METHOD_PORTABLE_CODE_OFFSET_32,
art::mirror::ArtMethod::EntryPointFromPortableCompiledCodeOffset(4).Int32Value())
@@ -156,7 +156,7 @@ ADD_TEST_EQ(MIRROR_ART_METHOD_PORTABLE_CODE_OFFSET_32,
ADD_TEST_EQ(MIRROR_ART_METHOD_QUICK_CODE_OFFSET_32,
art::mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(4).Int32Value())
-#define MIRROR_ART_METHOD_PORTABLE_CODE_OFFSET_64 (64 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_ART_METHOD_PORTABLE_CODE_OFFSET_64 (56 + MIRROR_OBJECT_HEADER_SIZE)
ADD_TEST_EQ(MIRROR_ART_METHOD_PORTABLE_CODE_OFFSET_64,
art::mirror::ArtMethod::EntryPointFromPortableCompiledCodeOffset(8).Int32Value())
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index 821d613..4fe3852 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -98,7 +98,7 @@ class CheckReferenceMapVisitor : public StackVisitor {
void CheckQuickMethod(int* registers, int number_of_references, uint32_t native_pc_offset)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* m = GetMethod();
- NativePcOffsetToReferenceMap map(m->GetNativeGcMap());
+ NativePcOffsetToReferenceMap map(m->GetNativeGcMap(sizeof(void*)));
const uint8_t* ref_bitmap = map.FindBitMap(native_pc_offset);
CHECK(ref_bitmap);
for (int i = 0; i < number_of_references; ++i) {
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e1b79c9..677fdc9 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -5737,24 +5737,13 @@ void ClassLinker::DumpAllClasses(int flags) {
}
}
-static OatFile::OatMethod CreateOatMethod(const void* code, const uint8_t* gc_map,
- bool is_portable) {
+static OatFile::OatMethod CreateOatMethod(const void* code, bool is_portable) {
CHECK_EQ(kUsePortableCompiler, is_portable);
CHECK(code != nullptr);
- const uint8_t* base;
- uint32_t code_offset, gc_map_offset;
- if (gc_map == nullptr) {
- base = reinterpret_cast<const uint8_t*>(code); // Base of data points at code.
- base -= sizeof(void*); // Move backward so that code_offset != 0.
- code_offset = sizeof(void*);
- gc_map_offset = 0;
- } else {
- // TODO: 64bit support.
- base = nullptr; // Base of data in oat file, ie 0.
- code_offset = PointerToLowMemUInt32(code);
- gc_map_offset = PointerToLowMemUInt32(gc_map);
- }
- return OatFile::OatMethod(base, code_offset, gc_map_offset);
+ const uint8_t* base = reinterpret_cast<const uint8_t*>(code); // Base of data points at code.
+ base -= sizeof(void*); // Move backward so that code_offset != 0.
+ const uint32_t code_offset = sizeof(void*);
+ return OatFile::OatMethod(base, code_offset);
}
bool ClassLinker::IsPortableResolutionStub(const void* entry_point) const {
@@ -5788,7 +5777,7 @@ const void* ClassLinker::GetRuntimeQuickGenericJniStub() const {
void ClassLinker::SetEntryPointsToCompiledCode(mirror::ArtMethod* method, const void* method_code,
bool is_portable) const {
- OatFile::OatMethod oat_method = CreateOatMethod(method_code, nullptr, is_portable);
+ OatFile::OatMethod oat_method = CreateOatMethod(method_code, is_portable);
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
// Create bridges to transition between different kinds of compiled bridge.
@@ -5808,7 +5797,7 @@ void ClassLinker::SetEntryPointsToInterpreter(mirror::ArtMethod* method) const {
method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
} else {
const void* quick_method_code = GetQuickGenericJniStub();
- OatFile::OatMethod oat_method = CreateOatMethod(quick_method_code, nullptr, false);
+ OatFile::OatMethod oat_method = CreateOatMethod(quick_method_code, false);
oat_method.LinkMethod(method);
method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
method->SetEntryPointFromPortableCompiledCode(GetPortableToQuickBridge());
diff --git a/runtime/entrypoints/portable/portable_thread_entrypoints.cc b/runtime/entrypoints/portable/portable_thread_entrypoints.cc
index ecbc65e..95ac66c 100644
--- a/runtime/entrypoints/portable/portable_thread_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_thread_entrypoints.cc
@@ -34,7 +34,7 @@ class ShadowFrameCopyVisitor : public StackVisitor {
uint32_t dex_pc = cur_frame->GetDexPC();
ShadowFrame* new_frame = ShadowFrame::Create(num_regs, NULL, method, dex_pc);
- const uint8_t* gc_map = method->GetNativeGcMap();
+ const uint8_t* gc_map = method->GetNativeGcMap(sizeof(void*));
verifier::DexPcToReferenceMap dex_gc_map(gc_map);
const uint8_t* reg_bitmap = dex_gc_map.FindBitMap(dex_pc);
for (size_t reg = 0; reg < num_regs; ++reg) {
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index ee9b221..580b541 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -76,7 +76,8 @@ class ExceptionTest : public CommonRuntimeTest {
const std::vector<uint8_t>& fake_mapping_data = fake_mapping_data_.GetData();
uint32_t vmap_table_offset = sizeof(OatQuickMethodHeader) + fake_vmap_table_data.size();
uint32_t mapping_table_offset = vmap_table_offset + fake_mapping_data.size();
- OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset,
+ uint32_t gc_map_offset = mapping_table_offset + fake_gc_map_.size();
+ OatQuickMethodHeader method_header(mapping_table_offset, vmap_table_offset, gc_map_offset,
4 * sizeof(void*), 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));
@@ -84,23 +85,23 @@ class ExceptionTest : public CommonRuntimeTest {
fake_vmap_table_data.begin(), fake_vmap_table_data.end());
fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(),
fake_mapping_data.begin(), fake_mapping_data.end());
+ fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(),
+ fake_gc_map_.begin(), fake_gc_map_.end());
fake_header_code_and_maps_.insert(fake_header_code_and_maps_.end(),
fake_code_.begin(), fake_code_.end());
// NOTE: Don't align the code (it will not be executed) but check that the Thumb2
// adjustment will be a NOP, see ArtMethod::EntryPointToCodePointer().
CHECK_EQ(mapping_table_offset & 1u, 0u);
- const uint8_t* code_ptr = &fake_header_code_and_maps_[mapping_table_offset];
+ const uint8_t* code_ptr = &fake_header_code_and_maps_[gc_map_offset];
method_f_ = my_klass_->FindVirtualMethod("f", "()I");
ASSERT_TRUE(method_f_ != nullptr);
method_f_->SetEntryPointFromQuickCompiledCode(code_ptr);
- method_f_->SetNativeGcMap(&fake_gc_map_[0]);
method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
ASSERT_TRUE(method_g_ != nullptr);
method_g_->SetEntryPointFromQuickCompiledCode(code_ptr);
- method_g_->SetNativeGcMap(&fake_gc_map_[0]);
}
const DexFile* dex_;
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index b936511..62ef6f8 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -252,14 +252,23 @@ inline CodeInfo ArtMethod::GetOptimizedCodeInfo() {
return CodeInfo(data);
}
-inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) {
- DCHECK(!Runtime::Current()->IsStarted());
- SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset));
+inline const uint8_t* ArtMethod::GetNativeGcMap(size_t pointer_size) {
+ const void* code_pointer = GetQuickOatCodePointer(pointer_size);
+ if (code_pointer == nullptr) {
+ return nullptr;
+ }
+ return GetNativeGcMap(code_pointer, pointer_size);
}
-inline uint32_t ArtMethod::GetOatNativeGcMapOffset() {
- DCHECK(!Runtime::Current()->IsStarted());
- return PointerToLowMemUInt32(GetNativeGcMap());
+inline const uint8_t* ArtMethod::GetNativeGcMap(const void* code_pointer, size_t pointer_size) {
+ DCHECK(code_pointer != nullptr);
+ DCHECK_EQ(code_pointer, GetQuickOatCodePointer(pointer_size));
+ uint32_t offset =
+ reinterpret_cast<const OatQuickMethodHeader*>(code_pointer)[-1].gc_map_offset_;
+ if (UNLIKELY(offset == 0u)) {
+ return nullptr;
+ }
+ return reinterpret_cast<const uint8_t*>(code_pointer) - offset;
}
inline bool ArtMethod::IsRuntimeMethod() {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index d292552..f5c1454 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -152,7 +152,7 @@ class MANAGED ArtMethod FINAL : public Object {
// (as in stack_map.h).
return GetEntryPointFromQuickCompiledCodePtrSize(pointer_size) != nullptr
&& GetQuickOatCodePointer(pointer_size) != nullptr
- && GetNativeGcMapPtrSize(pointer_size) == nullptr;
+ && GetNativeGcMap(pointer_size) == nullptr;
}
bool IsPortableCompiled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -405,29 +405,11 @@ class MANAGED ArtMethod FINAL : public Object {
StackMap GetStackMap(uint32_t native_pc_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
CodeInfo GetOptimizedCodeInfo() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const uint8_t* GetNativeGcMap() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CheckObjectSizeEqualsMirrorSize();
- return GetNativeGcMapPtrSize(sizeof(void*));
- }
- ALWAYS_INLINE const uint8_t* GetNativeGcMapPtrSize(size_t pointer_size)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetFieldPtrWithSize<uint8_t*>(GcMapOffset(pointer_size), pointer_size);
- }
- template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- void SetNativeGcMap(const uint8_t* data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CheckObjectSizeEqualsMirrorSize();
- SetNativeGcMapPtrSize(data, sizeof(void*));
- }
- template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE void SetNativeGcMapPtrSize(const uint8_t* data, size_t pointer_size)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- SetFieldPtrWithSize<false, true, kVerifyFlags>(GcMapOffset(pointer_size), data,
- pointer_size);
- }
-
- // When building the oat need a convenient place to stuff the offset of the native GC map.
- void SetOatNativeGcMapOffset(uint32_t gc_map_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint32_t GetOatNativeGcMapOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Callers should wrap the uint8_t* in a GcMap instance for convenient access.
+ const uint8_t* GetNativeGcMap(size_t pointer_size)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ const uint8_t* GetNativeGcMap(const void* code_pointer, size_t pointer_size)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
template <bool kCheckFrameSize = true>
uint32_t GetFrameSizeInBytes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -477,11 +459,6 @@ class MANAGED ArtMethod FINAL : public Object {
PtrSizedFields, entry_point_from_quick_compiled_code_) / sizeof(void*) * pointer_size);
}
- static MemberOffset GcMapOffset(size_t pointer_size) {
- return MemberOffset(PtrSizedFieldsOffset() + OFFSETOF_MEMBER(
- PtrSizedFields, gc_map_) / sizeof(void*) * pointer_size);
- }
-
void* GetEntryPointFromJni() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
CheckObjectSizeEqualsMirrorSize();
return GetEntryPointFromJniPtrSize(sizeof(void*));
@@ -660,11 +637,6 @@ class MANAGED ArtMethod FINAL : public Object {
// portable compiled code or the interpreter.
void* entry_point_from_quick_compiled_code_;
- // Pointer to a data structure created by the compiler and used by the garbage collector to
- // determine which registers hold live references to objects within the heap. Keyed by native PC
- // offsets for the quick compiler and dex PCs for the portable.
- void* gc_map_;
-
// Method dispatch from portable compiled code invokes this pointer which may cause bridging
// into quick compiled code or the interpreter. Last to simplify entrypoint logic.
void* entry_point_from_portable_compiled_code_;
diff --git a/runtime/oat.cc b/runtime/oat.cc
index bfb27dd..6455783 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -25,7 +25,7 @@
namespace art {
const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
-const uint8_t OatHeader::kOatVersion[] = { '0', '4', '8', '\0' };
+const uint8_t OatHeader::kOatVersion[] = { '0', '4', '9', '\0' };
static size_t ComputeOatHeaderSize(const SafeMap<std::string, std::string>* variable_data) {
size_t estimate = 0U;
@@ -493,35 +493,19 @@ void OatHeader::Flatten(const SafeMap<std::string, std::string>* key_value_store
key_value_store_size_ = data_ptr - reinterpret_cast<char*>(&key_value_store_);
}
-OatMethodOffsets::OatMethodOffsets()
- : code_offset_(0),
- gc_map_offset_(0)
-{}
-
-OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
- uint32_t gc_map_offset
- )
- : code_offset_(code_offset),
- gc_map_offset_(gc_map_offset)
-{}
+OatMethodOffsets::OatMethodOffsets(uint32_t code_offset) : code_offset_(code_offset) {
+}
OatMethodOffsets::~OatMethodOffsets() {}
-OatQuickMethodHeader::OatQuickMethodHeader()
- : mapping_table_offset_(0),
- vmap_table_offset_(0),
- frame_info_(0, 0, 0),
- code_size_(0)
-{}
-
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)
-{}
+ uint32_t mapping_table_offset, uint32_t vmap_table_offset, uint32_t gc_map_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),
+ gc_map_offset_(gc_map_offset),
+ frame_info_(frame_size_in_bytes, core_spill_mask, fp_spill_mask), code_size_(code_size) {
+}
OatQuickMethodHeader::~OatQuickMethodHeader() {}
diff --git a/runtime/oat.h b/runtime/oat.h
index 8fb02b8..11ed4fb 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -164,25 +164,20 @@ std::ostream& operator<<(std::ostream& os, const OatClassType& rhs);
class PACKED(4) OatMethodOffsets {
public:
- OatMethodOffsets();
-
- OatMethodOffsets(uint32_t code_offset,
- uint32_t gc_map_offset);
+ OatMethodOffsets(uint32_t code_offset = 0);
~OatMethodOffsets();
uint32_t code_offset_;
- uint32_t gc_map_offset_;
};
// OatQuickMethodHeader precedes the raw code chunk generated by the Quick compiler.
class PACKED(4) OatQuickMethodHeader {
public:
- OatQuickMethodHeader();
-
- 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);
+ OatQuickMethodHeader(uint32_t mapping_table_offset = 0U, uint32_t vmap_table_offset = 0U,
+ uint32_t gc_map_offset = 0U, uint32_t frame_size_in_bytes = 0U,
+ uint32_t core_spill_mask = 0U, uint32_t fp_spill_mask = 0U,
+ uint32_t code_size = 0U);
~OatQuickMethodHeader();
@@ -190,6 +185,8 @@ class PACKED(4) OatQuickMethodHeader {
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 offset in bytes from the start of the gc map to the end of the header.
+ uint32_t gc_map_offset_;
// The stack frame information.
QuickMethodFrameInfo frame_info_;
// The code size in bytes.
diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h
index 6237767..a429c87 100644
--- a/runtime/oat_file-inl.h
+++ b/runtime/oat_file-inl.h
@@ -78,6 +78,31 @@ inline uint32_t OatFile::OatMethod::GetFpSpillMask() const {
return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].frame_info_.FpSpillMask();
}
+const uint8_t* OatFile::OatMethod::GetGcMap() const {
+ const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+ if (code == nullptr) {
+ return nullptr;
+ }
+ uint32_t offset = reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].gc_map_offset_;
+ if (UNLIKELY(offset == 0u)) {
+ return nullptr;
+ }
+ return reinterpret_cast<const uint8_t*>(code) - offset;
+}
+
+uint32_t OatFile::OatMethod::GetGcMapOffset() const {
+ const uint8_t* gc_map = GetGcMap();
+ return static_cast<uint32_t>(gc_map != nullptr ? gc_map - begin_ : 0u);
+}
+
+uint32_t OatFile::OatMethod::GetGcMapOffsetOffset() const {
+ const OatQuickMethodHeader* method_header = GetOatQuickMethodHeader();
+ if (method_header == nullptr) {
+ return 0u;
+ }
+ return reinterpret_cast<const uint8_t*>(&method_header->gc_map_offset_) - begin_;
+}
+
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);
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 54f5eab..91e571b 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -577,18 +577,15 @@ const OatMethodOffsets* OatFile::OatClass::GetOatMethodOffsets(uint32_t method_i
const OatFile::OatMethod OatFile::OatClass::GetOatMethod(uint32_t method_index) const {
const OatMethodOffsets* oat_method_offsets = GetOatMethodOffsets(method_index);
if (oat_method_offsets == nullptr) {
- return OatMethod(nullptr, 0, 0);
+ return OatMethod(nullptr, 0);
}
if (oat_file_->IsExecutable() ||
Runtime::Current() == nullptr || // This case applies for oatdump.
Runtime::Current()->IsCompiler()) {
- return OatMethod(
- oat_file_->Begin(),
- oat_method_offsets->code_offset_,
- oat_method_offsets->gc_map_offset_);
+ return OatMethod(oat_file_->Begin(), oat_method_offsets->code_offset_);
} else {
// We aren't allowed to use the compiled code. We just force it down the interpreted version.
- return OatMethod(oat_file_->Begin(), 0, 0);
+ return OatMethod(oat_file_->Begin(), 0);
}
}
@@ -596,7 +593,6 @@ void OatFile::OatMethod::LinkMethod(mirror::ArtMethod* method) const {
CHECK(method != NULL);
method->SetEntryPointFromPortableCompiledCode(GetPortableCode());
method->SetEntryPointFromQuickCompiledCode(GetQuickCode());
- method->SetNativeGcMap(GetNativeGcMap()); // Used by native methods in work around JNI mode.
}
bool OatFile::IsPic() const {
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 2b94249..a335c94 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -96,9 +96,6 @@ class OatFile {
uint32_t GetCodeOffset() const {
return code_offset_;
}
- uint32_t GetNativeGcMapOffset() const {
- return native_gc_map_offset_;
- }
const void* GetPortableCode() const {
// TODO: encode whether code is portable/quick in flags within OatMethod.
@@ -134,10 +131,6 @@ class OatFile {
const OatQuickMethodHeader* GetOatQuickMethodHeader() const;
uint32_t GetOatQuickMethodHeaderOffset() const;
- const uint8_t* GetNativeGcMap() const {
- return GetOatPointer<const uint8_t*>(native_gc_map_offset_);
- }
-
size_t GetFrameSizeInBytes() const;
uint32_t GetCoreSpillMask() const;
uint32_t GetFpSpillMask() const;
@@ -150,18 +143,20 @@ class OatFile {
uint32_t GetVmapTableOffset() const;
uint32_t GetVmapTableOffsetOffset() const;
+ const uint8_t* GetGcMap() const;
+ uint32_t GetGcMapOffset() const;
+ uint32_t GetGcMapOffsetOffset() const;
+
// Create an OatMethod with offsets relative to the given base address
- OatMethod(const uint8_t* base, const uint32_t code_offset, const uint32_t gc_map_offset)
- : begin_(base),
- code_offset_(code_offset),
- native_gc_map_offset_(gc_map_offset) {
+ OatMethod(const uint8_t* base, const uint32_t code_offset)
+ : begin_(base), code_offset_(code_offset) {
}
~OatMethod() {}
// A representation of an invalid OatMethod, used when an OatMethod or OatClass can't be found.
// See ClassLinker::FindOatMethodFor.
static const OatMethod Invalid() {
- return OatMethod(nullptr, -1, -1);
+ return OatMethod(nullptr, -1);
}
private:
@@ -174,9 +169,7 @@ class OatFile {
}
const uint8_t* const begin_;
-
const uint32_t code_offset_;
- const uint32_t native_gc_map_offset_;
friend class OatClass;
};
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 163c11d..f7c7106 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2102,7 +2102,7 @@ class ReferenceMapVisitor : public StackVisitor {
} else {
// Java method.
// Portable path use DexGcMap and store in Method.native_gc_map_.
- const uint8_t* gc_map = m->GetNativeGcMap();
+ const uint8_t* gc_map = m->GetNativeGcMap(sizeof(void*));
CHECK(gc_map != nullptr) << PrettyMethod(m);
verifier::DexPcToReferenceMap dex_gc_map(gc_map);
uint32_t dex_pc = shadow_frame->GetDexPC();
@@ -2157,7 +2157,7 @@ class ReferenceMapVisitor : public StackVisitor {
}
}
} else {
- const uint8_t* native_gc_map = m->GetNativeGcMap();
+ const uint8_t* native_gc_map = m->GetNativeGcMap(sizeof(void*));
CHECK(native_gc_map != nullptr) << PrettyMethod(m);
const DexFile::CodeItem* code_item = m->GetCodeItem();
// Can't be nullptr or how would we compile its instructions?