diff options
Diffstat (limited to 'compiler/oat_writer.cc')
| -rw-r--r-- | compiler/oat_writer.cc | 37 |
1 files changed, 27 insertions, 10 deletions
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 15b4017816..633bf64171 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -19,6 +19,7 @@ #include <zlib.h> #include "arch/arm64/instruction_set_features_arm64.h" +#include "art_method-inl.h" #include "base/allocator.h" #include "base/bit_vector.h" #include "base/stl_util.h" @@ -33,7 +34,6 @@ #include "gc/space/space.h" #include "image_writer.h" #include "linker/relative_patcher.h" -#include "mirror/art_method-inl.h" #include "mirror/array.h" #include "mirror/class_loader.h" #include "mirror/dex_cache-inl.h" @@ -620,10 +620,9 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { ScopedObjectAccessUnchecked soa(Thread::Current()); 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>(), - NullHandle<mirror::ArtMethod>(), - invoke_type); + ArtMethod* method = linker->ResolveMethod( + *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); @@ -755,8 +754,8 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { uint32_t target_offset = GetTargetOffset(patch); PatchCodeAddress(&patched_code_, patch.LiteralOffset(), target_offset); } else if (patch.Type() == kLinkerPatchMethod) { - mirror::ArtMethod* method = GetTargetMethod(patch); - PatchObjectAddress(&patched_code_, patch.LiteralOffset(), method); + 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); @@ -794,12 +793,13 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation(); } - mirror::ArtMethod* GetTargetMethod(const LinkerPatch& patch) + ArtMethod* GetTargetMethod(const LinkerPatch& patch) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { MethodReference ref = patch.TargetMethod(); mirror::DexCache* dex_cache = (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(*ref.dex_file); - mirror::ArtMethod* method = dex_cache->GetResolvedMethod(ref.dex_method_index); + ArtMethod* method = dex_cache->GetResolvedMethod( + ref.dex_method_index, class_linker_->GetImagePointerSize()); CHECK(method != nullptr); return method; } @@ -810,7 +810,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { (target_it != writer_->method_offset_map_.map.end()) ? target_it->second : 0u; // If there's no compiled code, point to the correct trampoline. if (UNLIKELY(target_offset == 0)) { - mirror::ArtMethod* target = GetTargetMethod(patch); + ArtMethod* target = GetTargetMethod(patch); DCHECK(target != nullptr); size_t size = GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet()); const void* oat_code_offset = target->GetEntryPointFromQuickCompiledCodePtrSize(size); @@ -865,6 +865,23 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { data[3] = (address >> 24) & 0xffu; } + void PatchMethodAddress(std::vector<uint8_t>* code, uint32_t offset, ArtMethod* method) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // NOTE: Direct method pointers across oat files don't use linker patches. However, direct + // type pointers across oat files do. (TODO: Investigate why.) + if (writer_->image_writer_ != nullptr) { + method = writer_->image_writer_->GetImageMethodAddress(method); + } + // Note: We only patch ArtMethods to low 4gb since thats where the image is. + uint32_t address = PointerToLowMemUInt32(method); + DCHECK_LE(offset + 4, code->size()); + uint8_t* data = &(*code)[offset]; + data[0] = address & 0xffu; + data[1] = (address >> 8) & 0xffu; + data[2] = (address >> 16) & 0xffu; + data[3] = (address >> 24) & 0xffu; + } + void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { uint32_t address = writer_->image_writer_ == nullptr ? target_offset : |