diff options
-rw-r--r-- | compiler/compiled_method.cc | 20 | ||||
-rw-r--r-- | compiler/compiled_method.h | 2 | ||||
-rw-r--r-- | compiler/dex/dex_to_dex_compiler.cc | 72 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 14 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 13 | ||||
-rw-r--r-- | compiler/elf_writer_debug.cc | 8 | ||||
-rw-r--r-- | compiler/image_writer.h | 2 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 190 | ||||
-rw-r--r-- | runtime/class_linker.cc | 1 | ||||
-rw-r--r-- | runtime/oat_file-inl.h | 30 | ||||
-rw-r--r-- | runtime/oat_file.cc | 1 | ||||
-rw-r--r-- | runtime/oat_file.h | 8 |
12 files changed, 211 insertions, 150 deletions
diff --git a/compiler/compiled_method.cc b/compiler/compiled_method.cc index d1acada6dd..74ef35e740 100644 --- a/compiler/compiled_method.cc +++ b/compiler/compiled_method.cc @@ -23,20 +23,12 @@ CompiledCode::CompiledCode(CompilerDriver* compiler_driver, InstructionSet instr const ArrayRef<const uint8_t>& quick_code, bool owns_code_array) : compiler_driver_(compiler_driver), instruction_set_(instruction_set), owns_code_array_(owns_code_array), quick_code_(nullptr) { - SetCode(&quick_code); -} - -void CompiledCode::SetCode(const ArrayRef<const uint8_t>* quick_code) { - if (quick_code != nullptr) { - CHECK(!quick_code->empty()); - if (owns_code_array_) { - // If we are supposed to own the code, don't deduplicate it. - CHECK(quick_code_ == nullptr); - quick_code_ = new SwapVector<uint8_t>(quick_code->begin(), quick_code->end(), - compiler_driver_->GetSwapSpaceAllocator()); - } else { - quick_code_ = compiler_driver_->DeduplicateCode(*quick_code); - } + if (owns_code_array_) { + // If we are supposed to own the code, don't deduplicate it. + quick_code_ = new SwapVector<uint8_t>(quick_code.begin(), quick_code.end(), + compiler_driver_->GetSwapSpaceAllocator()); + } else { + quick_code_ = compiler_driver_->DeduplicateCode(quick_code); } } diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h index 45a62bc6c7..a4d2387030 100644 --- a/compiler/compiled_method.h +++ b/compiler/compiled_method.h @@ -47,8 +47,6 @@ class CompiledCode { return quick_code_; } - void SetCode(const ArrayRef<const uint8_t>* quick_code); - bool operator==(const CompiledCode& rhs) const; // To align an offset from a page-aligned value to make it suitable diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc index bd590467e3..4b56b69a11 100644 --- a/compiler/dex/dex_to_dex_compiler.cc +++ b/compiler/dex/dex_to_dex_compiler.cc @@ -18,6 +18,7 @@ #include "art_method-inl.h" #include "base/logging.h" #include "base/mutex.h" +#include "compiled_method.h" #include "dex_file-inl.h" #include "dex_instruction-inl.h" #include "driver/compiler_driver.h" @@ -34,6 +35,13 @@ const bool kEnableQuickening = true; // Control check-cast elision. const bool kEnableCheckCastEllision = true; +struct QuickenedInfo { + QuickenedInfo(uint32_t pc, uint16_t index) : dex_pc(pc), dex_member_index(index) {} + + uint32_t dex_pc; + uint16_t dex_member_index; +}; + class DexCompiler { public: DexCompiler(art::CompilerDriver& compiler, @@ -47,6 +55,10 @@ class DexCompiler { void Compile(); + const std::vector<QuickenedInfo>& GetQuickenedInfo() const { + return quickened_info_; + } + private: const DexFile& GetDexFile() const { return *unit_.GetDexFile(); @@ -87,6 +99,11 @@ class DexCompiler { const DexCompilationUnit& unit_; const DexToDexCompilationLevel dex_to_dex_compilation_level_; + // Filled by the compiler when quickening, in order to encode that information + // in the .oat file. The runtime will use that information to get to the original + // opcodes. + std::vector<QuickenedInfo> quickened_info_; + DISALLOW_COPY_AND_ASSIGN(DexCompiler); }; @@ -248,6 +265,7 @@ void DexCompiler::CompileInstanceFieldAccess(Instruction* inst, inst->SetOpcode(new_opcode); // Replace field index by field offset. inst->SetVRegC_22c(static_cast<uint16_t>(field_offset.Int32Value())); + quickened_info_.push_back(QuickenedInfo(dex_pc, field_idx)); } } @@ -287,24 +305,60 @@ void DexCompiler::CompileInvokeVirtual(Instruction* inst, uint32_t dex_pc, } else { inst->SetVRegB_35c(static_cast<uint16_t>(vtable_idx)); } + quickened_info_.push_back(QuickenedInfo(dex_pc, method_idx)); } } } -} // namespace optimizer -} // namespace art - -extern "C" void ArtCompileDEX(art::CompilerDriver& driver, const art::DexFile::CodeItem* code_item, - uint32_t access_flags, art::InvokeType invoke_type, - uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, - const art::DexFile& dex_file, - art::DexToDexCompilationLevel dex_to_dex_compilation_level) { - UNUSED(invoke_type); +extern "C" CompiledMethod* ArtCompileDEX( + art::CompilerDriver& driver, + const art::DexFile::CodeItem* code_item, + uint32_t access_flags, + art::InvokeType invoke_type ATTRIBUTE_UNUSED, + uint16_t class_def_idx, + uint32_t method_idx, + jobject class_loader, + const art::DexFile& dex_file, + art::DexToDexCompilationLevel dex_to_dex_compilation_level) { if (dex_to_dex_compilation_level != art::kDontDexToDexCompile) { art::DexCompilationUnit unit(nullptr, class_loader, art::Runtime::Current()->GetClassLinker(), dex_file, code_item, class_def_idx, method_idx, access_flags, driver.GetVerifiedMethod(&dex_file, method_idx)); art::optimizer::DexCompiler dex_compiler(driver, unit, dex_to_dex_compilation_level); dex_compiler.Compile(); + if (dex_compiler.GetQuickenedInfo().empty()) { + // No need to create a CompiledMethod if there are no quickened opcodes. + return nullptr; + } + + // Create a `CompiledMethod`, with the quickened information in the vmap table. + Leb128EncodingVector builder; + for (QuickenedInfo info : dex_compiler.GetQuickenedInfo()) { + builder.PushBackUnsigned(info.dex_pc); + builder.PushBackUnsigned(info.dex_member_index); + } + InstructionSet instruction_set = driver.GetInstructionSet(); + if (instruction_set == kThumb2) { + // Don't use the thumb2 instruction set to avoid the one off code delta. + instruction_set = kArm; + } + return CompiledMethod::SwapAllocCompiledMethod( + &driver, + instruction_set, + ArrayRef<const uint8_t>(), // no code + 0, + 0, + 0, + nullptr, // src_mapping_table + ArrayRef<const uint8_t>(), // mapping_table + ArrayRef<const uint8_t>(builder.GetData()), // vmap_table + ArrayRef<const uint8_t>(), // gc_map + ArrayRef<const uint8_t>(), // cfi data + ArrayRef<const LinkerPatch>()); } + return nullptr; } + +} // namespace optimizer + +} // namespace art diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 7890108f41..a52bfaeb5b 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -2291,10 +2291,16 @@ void CompilerDriver::CompileMethod(Thread* self, const DexFile::CodeItem* code_i // TODO: add a command-line option to disable DEX-to-DEX compilation ? // Do not optimize if a VerifiedMethod is missing. SafeCast elision, for example, relies on // it. - (*dex_to_dex_compiler_)(*this, code_item, access_flags, - invoke_type, class_def_idx, - method_idx, class_loader, dex_file, - has_verified_method ? dex_to_dex_compilation_level : kRequired); + compiled_method = (*dex_to_dex_compiler_)( + *this, + code_item, + access_flags, + invoke_type, + class_def_idx, + method_idx, + class_loader, + dex_file, + has_verified_method ? dex_to_dex_compilation_level : kRequired); } } if (kTimeCompileMethod) { diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 2d7ceaeea1..5cf4044fd4 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -675,12 +675,13 @@ class CompilerDriver { typedef void (*CompilerCallbackFn)(CompilerDriver& driver); typedef MutexLock* (*CompilerMutexLockFn)(CompilerDriver& driver); - typedef void (*DexToDexCompilerFn)(CompilerDriver& driver, - const DexFile::CodeItem* code_item, - uint32_t access_flags, InvokeType invoke_type, - uint32_t class_dex_idx, uint32_t method_idx, - jobject class_loader, const DexFile& dex_file, - DexToDexCompilationLevel dex_to_dex_compilation_level); + typedef CompiledMethod* (*DexToDexCompilerFn)( + CompilerDriver& driver, + const DexFile::CodeItem* code_item, + uint32_t access_flags, InvokeType invoke_type, + uint32_t class_dex_idx, uint32_t method_idx, + jobject class_loader, const DexFile& dex_file, + DexToDexCompilationLevel dex_to_dex_compilation_level); DexToDexCompilerFn dex_to_dex_compiler_; void* compiler_context_; diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc index c68bbc0655..c10ffebbbc 100644 --- a/compiler/elf_writer_debug.cc +++ b/compiler/elf_writer_debug.cc @@ -249,16 +249,16 @@ void WriteDebugSections(const CompilerDriver* compiler, // Find all addresses (low_pc) which contain deduped methods. // The first instance of method is not marked deduped_, but the rest is. std::unordered_set<uint32_t> deduped_addresses; - for (auto it = method_infos.begin(); it != method_infos.end(); ++it) { - if (it->deduped_) { - deduped_addresses.insert(it->low_pc_); + for (const OatWriter::DebugInfo& mi : method_infos) { + if (mi.deduped_) { + deduped_addresses.insert(mi.low_pc_); } } // Group the methods into compilation units based on source file. std::vector<std::vector<const OatWriter::DebugInfo*>> compilation_units; const char* last_source_file = nullptr; - for (const auto& mi : method_infos) { + for (const OatWriter::DebugInfo& mi : method_infos) { // Attribute given instruction range only to single method. // Otherwise the debugger might get really confused. if (!mi.deduped_) { diff --git a/compiler/image_writer.h b/compiler/image_writer.h index 9d45ce2bd4..62d8a691af 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -199,7 +199,7 @@ class ImageWriter FINAL { const uint8_t* GetOatAddress(uint32_t offset) const { // With Quick, code is within the OatFile, as there are all in one // .o ELF object. - DCHECK_LT(offset, oat_file_->Size()); + DCHECK_LE(offset, oat_file_->Size()); DCHECK(oat_data_begin_ != nullptr); return offset == 0u ? nullptr : oat_data_begin_ + offset; } diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index a98a3046e5..4318ea5b6c 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -374,9 +374,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { uint32_t quick_code_offset = 0; const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode(); - CHECK(quick_code != nullptr); uint32_t code_size = quick_code->size() * sizeof(uint8_t); - CHECK_NE(code_size, 0U); uint32_t thumb_offset = compiled_method->CodeDelta(); // Deduplicate code arrays if we are not producing debuggable code. @@ -394,16 +392,18 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { } } - MethodReference method_ref(dex_file_, it.GetMemberIndex()); - auto method_lb = writer_->method_offset_map_.map.lower_bound(method_ref); - if (method_lb != writer_->method_offset_map_.map.end() && - !writer_->method_offset_map_.map.key_comp()(method_ref, method_lb->first)) { - // TODO: Should this be a hard failure? - LOG(WARNING) << "Multiple definitions of " - << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file) - << ((method_lb->second != quick_code_offset) ? "; OFFSET MISMATCH" : ""); - } else { - writer_->method_offset_map_.map.PutBefore(method_lb, method_ref, quick_code_offset); + if (code_size != 0) { + MethodReference method_ref(dex_file_, it.GetMemberIndex()); + auto method_lb = writer_->method_offset_map_.map.lower_bound(method_ref); + if (method_lb != writer_->method_offset_map_.map.end() && + !writer_->method_offset_map_.map.key_comp()(method_ref, method_lb->first)) { + // TODO: Should this be a hard failure? + LOG(WARNING) << "Multiple definitions of " + << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file) + << ((method_lb->second != quick_code_offset) ? "; OFFSET MISMATCH" : ""); + } else { + writer_->method_offset_map_.map.PutBefore(method_lb, method_ref, quick_code_offset); + } } // Update quick method header. @@ -411,21 +411,24 @@ 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_; + // If we don't have quick code, then we must have a vmap, as that is how the dex2dex + // compiler records its transformations. + DCHECK(quick_code != nullptr || vmap_table_offset != 0); 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; - if (mapping_table_offset != 0u) { + if (mapping_table_offset != 0u && code_offset != 0u) { mapping_table_offset += code_offset; - DCHECK_LT(mapping_table_offset, code_offset); + DCHECK_LT(mapping_table_offset, code_offset) << "Overflow in oat offsets"; } - if (vmap_table_offset != 0u) { + if (vmap_table_offset != 0u && code_offset != 0u) { vmap_table_offset += code_offset; - DCHECK_LT(vmap_table_offset, code_offset); + DCHECK_LT(vmap_table_offset, code_offset) << "Overflow in oat offsets"; } - if (gc_map_offset != 0u) { + if (gc_map_offset != 0u && code_offset != 0u) { gc_map_offset += code_offset; - DCHECK_LT(gc_map_offset, code_offset); + DCHECK_LT(gc_map_offset, code_offset) << "Overflow in oat offsets"; } uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); uint32_t core_spill_mask = compiled_method->GetCoreSpillMask(); @@ -534,7 +537,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { const ClassDataItemIterator& it, uint32_t thumb_offset) { offset_ = writer_->relative_patcher_->ReserveSpace( - offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex())); + offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex())); offset_ = compiled_method->AlignCode(offset_); DCHECK_ALIGNED_PARAM(offset_, GetInstructionSetAlignment(compiled_method->GetInstructionSet())); @@ -619,15 +622,19 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { *dex_file_, it.GetMemberIndex(), dex_cache, NullHandle<mirror::ClassLoader>(), nullptr, invoke_type); if (method == nullptr) { - LOG(ERROR) << "Unexpected failure to resolve a method: " - << PrettyMethod(it.GetMemberIndex(), *dex_file_, true); + LOG(INTERNAL_FATAL) << "Unexpected failure to resolve a method: " + << PrettyMethod(it.GetMemberIndex(), *dex_file_, true); soa.Self()->AssertPendingException(); mirror::Throwable* exc = soa.Self()->GetException(); std::string dump = exc->Dump(); LOG(FATAL) << dump; + UNREACHABLE(); + } + + if (compiled_method != nullptr && compiled_method->GetQuickCode()->size() != 0) { + method->SetEntryPointFromQuickCompiledCodePtrSize( + reinterpret_cast<void*>(offsets.code_offset_), pointer_size_); } - method->SetEntryPointFromQuickCompiledCodePtrSize(reinterpret_cast<void*>(offsets.code_offset_), - pointer_size_); return true; } @@ -689,85 +696,82 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { OutputStream* out = out_; const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode(); - if (quick_code != nullptr) { - // Need a wrapper if we create a copy for patching. - ArrayRef<const uint8_t> wrapped(*quick_code); - uint32_t code_size = quick_code->size() * sizeof(uint8_t); - CHECK_NE(code_size, 0U); - - // Deduplicate code arrays. - const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_]; - if (method_offsets.code_offset_ >= offset_) { - offset_ = writer_->relative_patcher_->WriteThunks(out, offset_); - if (offset_ == 0u) { - ReportWriteFailure("relative call thunk", it); - return false; - } - uint32_t aligned_offset = compiled_method->AlignCode(offset_); - uint32_t aligned_code_delta = aligned_offset - offset_; - if (aligned_code_delta != 0) { - if (!writer_->WriteCodeAlignment(out, aligned_code_delta)) { - ReportWriteFailure("code alignment padding", it); - return false; - } - offset_ += aligned_code_delta; - DCHECK_OFFSET_(); - } - DCHECK_ALIGNED_PARAM(offset_, - GetInstructionSetAlignment(compiled_method->GetInstructionSet())); - DCHECK_EQ(method_offsets.code_offset_, - offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta()) - << PrettyMethod(it.GetMemberIndex(), *dex_file_); - const OatQuickMethodHeader& method_header = - oat_class->method_headers_[method_offsets_index_]; - writer_->oat_header_->UpdateChecksum(&method_header, sizeof(method_header)); - if (!out->WriteFully(&method_header, sizeof(method_header))) { - ReportWriteFailure("method header", it); + // Need a wrapper if we create a copy for patching. + ArrayRef<const uint8_t> wrapped(*quick_code); + uint32_t code_size = quick_code->size() * sizeof(uint8_t); + + // Deduplicate code arrays. + const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_]; + if (method_offsets.code_offset_ > offset_) { + offset_ = writer_->relative_patcher_->WriteThunks(out, offset_); + if (offset_ == 0u) { + ReportWriteFailure("relative call thunk", it); + return false; + } + uint32_t aligned_offset = compiled_method->AlignCode(offset_); + uint32_t aligned_code_delta = aligned_offset - offset_; + if (aligned_code_delta != 0) { + if (!writer_->WriteCodeAlignment(out, aligned_code_delta)) { + ReportWriteFailure("code alignment padding", it); return false; } - writer_->size_method_header_ += sizeof(method_header); - offset_ += sizeof(method_header); + offset_ += aligned_code_delta; DCHECK_OFFSET_(); + } + DCHECK_ALIGNED_PARAM(offset_, + GetInstructionSetAlignment(compiled_method->GetInstructionSet())); + DCHECK_EQ(method_offsets.code_offset_, + offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta()) + << PrettyMethod(it.GetMemberIndex(), *dex_file_); + const OatQuickMethodHeader& method_header = + oat_class->method_headers_[method_offsets_index_]; + writer_->oat_header_->UpdateChecksum(&method_header, sizeof(method_header)); + if (!out->WriteFully(&method_header, sizeof(method_header))) { + ReportWriteFailure("method header", it); + return false; + } + writer_->size_method_header_ += sizeof(method_header); + offset_ += sizeof(method_header); + DCHECK_OFFSET_(); - if (!compiled_method->GetPatches().empty()) { - patched_code_.assign(quick_code->begin(), quick_code->end()); - wrapped = ArrayRef<const uint8_t>(patched_code_); - for (const LinkerPatch& patch : compiled_method->GetPatches()) { - if (patch.Type() == kLinkerPatchCallRelative) { - // NOTE: Relative calls across oat files are not supported. - uint32_t target_offset = GetTargetOffset(patch); - uint32_t literal_offset = patch.LiteralOffset(); - writer_->relative_patcher_->PatchCall(&patched_code_, literal_offset, - offset_ + literal_offset, target_offset); - } else if (patch.Type() == kLinkerPatchDexCacheArray) { - uint32_t target_offset = GetDexCacheOffset(patch); - uint32_t literal_offset = patch.LiteralOffset(); - writer_->relative_patcher_->PatchDexCacheReference(&patched_code_, patch, - offset_ + literal_offset, - target_offset); - } else if (patch.Type() == kLinkerPatchCall) { - uint32_t target_offset = GetTargetOffset(patch); - PatchCodeAddress(&patched_code_, patch.LiteralOffset(), target_offset); - } else if (patch.Type() == kLinkerPatchMethod) { - ArtMethod* method = GetTargetMethod(patch); - PatchMethodAddress(&patched_code_, patch.LiteralOffset(), method); - } else if (patch.Type() == kLinkerPatchType) { - mirror::Class* type = GetTargetType(patch); - PatchObjectAddress(&patched_code_, patch.LiteralOffset(), type); - } + if (!compiled_method->GetPatches().empty()) { + patched_code_.assign(quick_code->begin(), quick_code->end()); + wrapped = ArrayRef<const uint8_t>(patched_code_); + for (const LinkerPatch& patch : compiled_method->GetPatches()) { + if (patch.Type() == kLinkerPatchCallRelative) { + // NOTE: Relative calls across oat files are not supported. + uint32_t target_offset = GetTargetOffset(patch); + uint32_t literal_offset = patch.LiteralOffset(); + writer_->relative_patcher_->PatchCall(&patched_code_, literal_offset, + offset_ + literal_offset, target_offset); + } else if (patch.Type() == kLinkerPatchDexCacheArray) { + uint32_t target_offset = GetDexCacheOffset(patch); + uint32_t literal_offset = patch.LiteralOffset(); + writer_->relative_patcher_->PatchDexCacheReference(&patched_code_, patch, + offset_ + literal_offset, + target_offset); + } else if (patch.Type() == kLinkerPatchCall) { + uint32_t target_offset = GetTargetOffset(patch); + PatchCodeAddress(&patched_code_, patch.LiteralOffset(), target_offset); + } else if (patch.Type() == kLinkerPatchMethod) { + ArtMethod* method = GetTargetMethod(patch); + PatchMethodAddress(&patched_code_, patch.LiteralOffset(), method); + } else if (patch.Type() == kLinkerPatchType) { + mirror::Class* type = GetTargetType(patch); + PatchObjectAddress(&patched_code_, patch.LiteralOffset(), type); } } + } - writer_->oat_header_->UpdateChecksum(wrapped.data(), code_size); - if (!out->WriteFully(wrapped.data(), code_size)) { - ReportWriteFailure("method code", it); - return false; - } - writer_->size_code_ += code_size; - offset_ += code_size; + writer_->oat_header_->UpdateChecksum(wrapped.data(), code_size); + if (!out->WriteFully(wrapped.data(), code_size)) { + ReportWriteFailure("method code", it); + return false; } - DCHECK_OFFSET_(); + writer_->size_code_ += code_size; + offset_ += code_size; } + DCHECK_OFFSET_(); ++method_offsets_index_; } diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 06942275c6..1ec02aa44b 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -55,6 +55,7 @@ #include "linear_alloc.h" #include "oat.h" #include "oat_file.h" +#include "oat_file-inl.h" #include "oat_file_assistant.h" #include "object_lock.h" #include "mirror/class.h" diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h index 6b3b66643c..37d025a438 100644 --- a/runtime/oat_file-inl.h +++ b/runtime/oat_file-inl.h @@ -38,14 +38,6 @@ inline uint32_t OatFile::OatMethod::GetOatQuickMethodHeaderOffset() const { return reinterpret_cast<const uint8_t*>(method_header) - begin_; } -inline uint32_t OatFile::OatMethod::GetQuickCodeSize() const { - const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode()); - if (code == nullptr) { - return 0u; - } - return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_; -} - inline uint32_t OatFile::OatMethod::GetQuickCodeSizeOffset() const { const OatQuickMethodHeader* method_header = GetOatQuickMethodHeader(); if (method_header == nullptr) { @@ -78,7 +70,7 @@ inline uint32_t OatFile::OatMethod::GetFpSpillMask() const { return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].frame_info_.FpSpillMask(); } -const uint8_t* OatFile::OatMethod::GetGcMap() const { +inline const uint8_t* OatFile::OatMethod::GetGcMap() const { const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode()); if (code == nullptr) { return nullptr; @@ -90,12 +82,12 @@ const uint8_t* OatFile::OatMethod::GetGcMap() const { return reinterpret_cast<const uint8_t*>(code) - offset; } -uint32_t OatFile::OatMethod::GetGcMapOffset() const { +inline 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 { +inline uint32_t OatFile::OatMethod::GetGcMapOffsetOffset() const { const OatQuickMethodHeader* method_header = GetOatQuickMethodHeader(); if (method_header == nullptr) { return 0u; @@ -153,6 +145,22 @@ inline const uint8_t* OatFile::OatMethod::GetVmapTable() const { return reinterpret_cast<const uint8_t*>(code) - offset; } +inline uint32_t OatFile::OatMethod::GetQuickCodeSize() const { + const void* code = ArtMethod::EntryPointToCodePointer(GetOatPointer<const void*>(code_offset_)); + if (code == nullptr) { + return 0u; + } + return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_; +} + +inline uint32_t OatFile::OatMethod::GetCodeOffset() const { + return (GetQuickCodeSize() == 0) ? 0 : code_offset_; +} + +inline const void* OatFile::OatMethod::GetQuickCode() const { + return GetOatPointer<const void*>(GetCodeOffset()); +} + } // namespace art #endif // ART_RUNTIME_OAT_FILE_INL_H_ diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index ad5741e475..098fe619aa 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -41,6 +41,7 @@ #include "mem_map.h" #include "mirror/class.h" #include "mirror/object-inl.h" +#include "oat_file-inl.h" #include "os.h" #include "runtime.h" #include "utils.h" diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 1a782deb82..7c4ef8be88 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -100,13 +100,9 @@ class OatFile FINAL { public: void LinkMethod(ArtMethod* method) const; - uint32_t GetCodeOffset() const { - return code_offset_; - } + uint32_t GetCodeOffset() const; - const void* GetQuickCode() const { - return GetOatPointer<const void*>(code_offset_); - } + const void* GetQuickCode() const; // Returns size of quick code. uint32_t GetQuickCodeSize() const; |