From 957ca1cd025104fccb0b08928f955f9bdb4ab91c Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Fri, 21 Nov 2014 16:51:29 -0800 Subject: Delete ArtMethod gc_map_ field Moved the gc_map field from OatMethod to OatQuickMethodHeader. Deleted the ArtMethod gc_map_ field. Bug: 17643507 Change-Id: Ifa0470c3e4c2f8a319744464d94c6838b76b3d48 (cherry picked from commit 807140048f82a2b87ee5bcf337f23b6a3d1d5269) --- compiler/common_compiler_test.cc | 9 +++-- compiler/common_compiler_test.h | 2 +- compiler/image_writer.cc | 6 ---- compiler/oat_test.cc | 4 +-- compiler/oat_writer.cc | 32 ++++++++++------- oatdump/oatdump.cc | 22 ++++++------ patchoat/patchoat.cc | 6 ---- runtime/asm_support.h | 4 +-- runtime/check_reference_map_visitor.h | 2 +- runtime/class_linker.cc | 25 ++++---------- .../portable/portable_thread_entrypoints.cc | 2 +- runtime/exception_test.cc | 9 ++--- runtime/mirror/art_method-inl.h | 21 ++++++++---- runtime/mirror/art_method.h | 40 ++++------------------ runtime/oat.cc | 36 ++++++------------- runtime/oat.h | 17 ++++----- runtime/oat_file-inl.h | 25 ++++++++++++++ runtime/oat_file.cc | 10 ++---- runtime/oat_file.h | 21 ++++-------- runtime/thread.cc | 4 +-- 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& 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& 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()); std::vector* 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(orig->GetEntryPointFromJni(), target_ptr_size_); copy->SetEntryPointFromQuickCompiledCodePtrSize( orig->GetEntryPointFromQuickCompiledCode(), target_ptr_size_); - copy->SetNativeGcMapPtrSize(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(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(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 dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file_))); mirror::ArtMethod* method = linker->ResolveMethod(*dex_file_, it.GetMemberIndex(), dex_cache, NullHandle(), @@ -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 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(native_method + delta_), pointer_size); } - - uintptr_t native_gc_map = reinterpret_cast( - object->GetNativeGcMapPtrSize(pointer_size)); - if (native_gc_map != 0) { - copy->SetNativeGcMapPtrSize(reinterpret_cast(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(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(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& 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(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(code_pointer)[-1].gc_map_offset_; + if (UNLIKELY(offset == 0u)) { + return nullptr; + } + return reinterpret_cast(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(GcMapOffset(pointer_size), pointer_size); - } - template - void SetNativeGcMap(const uint8_t* data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CheckObjectSizeEqualsMirrorSize(); - SetNativeGcMapPtrSize(data, sizeof(void*)); - } - template - ALWAYS_INLINE void SetNativeGcMapPtrSize(const uint8_t* data, size_t pointer_size) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - SetFieldPtrWithSize(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 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* variable_data) { size_t estimate = 0U; @@ -493,35 +493,19 @@ void OatHeader::Flatten(const SafeMap* key_value_store key_value_store_size_ = data_ptr - reinterpret_cast(&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(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(code)[-1].gc_map_offset_; + if (UNLIKELY(offset == 0u)) { + return nullptr; + } + return reinterpret_cast(code) - offset; +} + +uint32_t OatFile::OatMethod::GetGcMapOffset() const { + const uint8_t* gc_map = GetGcMap(); + return static_cast(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(&method_header->gc_map_offset_) - begin_; +} + inline uint32_t OatFile::OatMethod::GetMappingTableOffset() const { const uint8_t* mapping_table = GetMappingTable(); return static_cast(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(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? -- cgit v1.1