diff options
Diffstat (limited to 'compiler/oat_writer.cc')
-rw-r--r-- | compiler/oat_writer.cc | 97 |
1 files changed, 63 insertions, 34 deletions
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index cc8c6dfac0..ce1b755a9d 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -33,6 +33,7 @@ #include "debug/method_debug_info.h" #include "dex/verification_results.h" #include "dex_file-inl.h" +#include "dex_file_types.h" #include "dexlayout.h" #include "driver/compiler_driver-inl.h" #include "driver/compiler_options.h" @@ -667,11 +668,11 @@ class OatWriter::DexMethodVisitor { : writer_(writer), offset_(offset), dex_file_(nullptr), - class_def_index_(DexFile::kDexNoIndex) {} + class_def_index_(dex::kDexNoIndex) {} virtual bool StartClass(const DexFile* dex_file, size_t class_def_index) { DCHECK(dex_file_ == nullptr); - DCHECK_EQ(class_def_index_, DexFile::kDexNoIndex); + DCHECK_EQ(class_def_index_, dex::kDexNoIndex); dex_file_ = dex_file; class_def_index_ = class_def_index; return true; @@ -682,7 +683,7 @@ class OatWriter::DexMethodVisitor { virtual bool EndClass() { if (kIsDebugBuild) { dex_file_ = nullptr; - class_def_index_ = DexFile::kDexNoIndex; + class_def_index_ = dex::kDexNoIndex; } return true; } @@ -765,7 +766,7 @@ class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor { Allocator::GetMallocAllocator())); refs_it->second.ClearAllBits(); } - refs_it->second.SetBit(target_method.dex_method_index); + refs_it->second.SetBit(target_method.index); writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u); } else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) { TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); @@ -867,16 +868,19 @@ class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor { class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { public: InitCodeMethodVisitor(OatWriter* writer, size_t offset) - : OatDexMethodVisitor(writer, offset), - debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()) { - writer_->absolute_patch_locations_.reserve( - writer_->compiler_driver_->GetNonRelativeLinkerPatchCount()); - } + : InitCodeMethodVisitor(writer, offset, writer->GetCompilerDriver()->GetCompilerOptions()) {} bool EndClass() OVERRIDE { OatDexMethodVisitor::EndClass(); if (oat_class_index_ == writer_->oat_classes_.size()) { - offset_ = writer_->relative_patcher_->ReserveSpaceEnd(offset_); + offset_ = relative_patcher_->ReserveSpaceEnd(offset_); + if (generate_debug_info_) { + std::vector<debug::MethodDebugInfo> thunk_infos = + relative_patcher_->GenerateThunkDebugInfo(executable_offset_); + writer_->method_info_.insert(writer_->method_info_.end(), + std::make_move_iterator(thunk_infos.begin()), + std::make_move_iterator(thunk_infos.end())); + } } return true; } @@ -898,7 +902,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { bool deduped = true; MethodReference method_ref(dex_file_, it.GetMemberIndex()); if (debuggable_) { - quick_code_offset = writer_->relative_patcher_->GetOffset(method_ref); + quick_code_offset = relative_patcher_->GetOffset(method_ref); if (quick_code_offset != 0u) { // Duplicate methods, we want the same code for both of them so that the oat writer puts // the same code in both ArtMethods so that we do not get different oat code at runtime. @@ -916,14 +920,14 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { } if (code_size != 0) { - if (writer_->relative_patcher_->GetOffset(method_ref) != 0u) { + if (relative_patcher_->GetOffset(method_ref) != 0u) { // TODO: Should this be a hard failure? LOG(WARNING) << "Multiple definitions of " - << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index) - << " offsets " << writer_->relative_patcher_->GetOffset(method_ref) + << method_ref.PrettyMethod() + << " offsets " << relative_patcher_->GetOffset(method_ref) << " " << quick_code_offset; } else { - writer_->relative_patcher_->SetOffset(method_ref, quick_code_offset); + relative_patcher_->SetOffset(method_ref, quick_code_offset); } } @@ -977,13 +981,12 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { } } - const CompilerOptions& compiler_options = writer_->compiler_driver_->GetCompilerOptions(); // Exclude quickened dex methods (code_size == 0) since they have no native code. - if (compiler_options.GenerateAnyDebugInfo() && code_size != 0) { + if (generate_debug_info_ && code_size != 0) { bool has_code_info = method_header->IsOptimized(); // Record debug information for this function if we are doing that. - debug::MethodDebugInfo info = debug::MethodDebugInfo(); - info.trampoline_name = nullptr; + debug::MethodDebugInfo info = {}; + DCHECK(info.trampoline_name.empty()); info.dex_file = dex_file_; info.class_def_index = class_def_index_; info.dex_method_index = it.GetMemberIndex(); @@ -991,10 +994,10 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { info.code_item = it.GetMethodCodeItem(); info.isa = compiled_method->GetInstructionSet(); info.deduped = deduped; - info.is_native_debuggable = compiler_options.GetNativeDebuggable(); + info.is_native_debuggable = native_debuggable_; info.is_optimized = method_header->IsOptimized(); info.is_code_address_text_relative = true; - info.code_address = code_offset - writer_->oat_header_->GetExecutableOffset(); + info.code_address = code_offset - executable_offset_; info.code_size = code_size; info.frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); info.code_info = has_code_info ? compiled_method->GetVmapTable().data() : nullptr; @@ -1012,6 +1015,17 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { } private: + InitCodeMethodVisitor(OatWriter* writer, size_t offset, const CompilerOptions& compiler_options) + : OatDexMethodVisitor(writer, offset), + relative_patcher_(writer->relative_patcher_), + executable_offset_(writer->oat_header_->GetExecutableOffset()), + debuggable_(compiler_options.GetDebuggable()), + native_debuggable_(compiler_options.GetNativeDebuggable()), + generate_debug_info_(compiler_options.GenerateAnyDebugInfo()) { + writer->absolute_patch_locations_.reserve( + writer->GetCompilerDriver()->GetNonRelativeLinkerPatchCount()); + } + struct CodeOffsetsKeyComparator { bool operator()(const CompiledMethod* lhs, const CompiledMethod* rhs) const { // Code is deduplicated by CompilerDriver, compare only data pointers. @@ -1035,7 +1049,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { uint32_t NewQuickCodeOffset(CompiledMethod* compiled_method, const ClassDataItemIterator& it, uint32_t thumb_offset) { - offset_ = writer_->relative_patcher_->ReserveSpace( + offset_ = relative_patcher_->ReserveSpace( offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex())); offset_ += CodeAlignmentSize(offset_, *compiled_method); DCHECK_ALIGNED_PARAM(offset_ + sizeof(OatQuickMethodHeader), @@ -1047,8 +1061,12 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { // so we can simply compare the pointers to find out if things are duplicated. SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_; - // Cache of compiler's --debuggable option. + // Cache writer_'s members and compiler options. + linker::MultiOatRelativePatcher* relative_patcher_; + uint32_t executable_offset_; const bool debuggable_; + const bool native_debuggable_; + const bool generate_debug_info_; }; class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor { @@ -1509,8 +1527,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { ObjPtr<mirror::DexCache> dex_cache = (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache( Thread::Current(), *ref.dex_file); - ArtMethod* method = - class_linker_->LookupResolvedMethod(ref.dex_method_index, dex_cache, class_loader_); + ArtMethod* method = class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_); CHECK(method != nullptr); return method; } @@ -1935,19 +1952,33 @@ size_t OatWriter::InitOatDexFiles(size_t offset) { size_t OatWriter::InitOatCode(size_t offset) { // calculate the offsets within OatHeader to executable code size_t old_offset = offset; - size_t adjusted_offset = offset; // required to be on a new page boundary offset = RoundUp(offset, kPageSize); oat_header_->SetExecutableOffset(offset); size_executable_offset_alignment_ = offset - old_offset; + // TODO: Remove unused trampoline offsets from the OatHeader (requires oat version change). + oat_header_->SetInterpreterToInterpreterBridgeOffset(0); + oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0); if (compiler_driver_->GetCompilerOptions().IsBootImage()) { InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); - - #define DO_TRAMPOLINE(field, fn_name) \ - offset = CompiledCode::AlignCode(offset, instruction_set); \ - adjusted_offset = offset + CompiledCode::CodeDelta(instruction_set); \ - oat_header_->Set ## fn_name ## Offset(adjusted_offset); \ - (field) = compiler_driver_->Create ## fn_name(); \ + const bool generate_debug_info = compiler_driver_->GetCompilerOptions().GenerateAnyDebugInfo(); + size_t adjusted_offset = offset; + + #define DO_TRAMPOLINE(field, fn_name) \ + offset = CompiledCode::AlignCode(offset, instruction_set); \ + adjusted_offset = offset + CompiledCode::CodeDelta(instruction_set); \ + oat_header_->Set ## fn_name ## Offset(adjusted_offset); \ + (field) = compiler_driver_->Create ## fn_name(); \ + if (generate_debug_info) { \ + debug::MethodDebugInfo info = {}; \ + info.trampoline_name = #fn_name; \ + info.isa = instruction_set; \ + info.is_code_address_text_relative = true; \ + /* Use the code offset rather than the `adjusted_offset`. */ \ + info.code_address = offset - oat_header_->GetExecutableOffset(); \ + info.code_size = (field)->size(); \ + method_info_.push_back(std::move(info)); \ + } \ offset += (field)->size(); DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup); @@ -1958,8 +1989,6 @@ size_t OatWriter::InitOatCode(size_t offset) { #undef DO_TRAMPOLINE } else { - oat_header_->SetInterpreterToInterpreterBridgeOffset(0); - oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0); oat_header_->SetJniDlsymLookupOffset(0); oat_header_->SetQuickGenericJniTrampolineOffset(0); oat_header_->SetQuickImtConflictTrampolineOffset(0); |