diff options
Diffstat (limited to 'compiler/oat_writer.cc')
-rw-r--r-- | compiler/oat_writer.cc | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 7b410bfe37..a78a5b3644 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -31,6 +31,7 @@ #include "dex/verification_results.h" #include "driver/compiler_driver.h" #include "driver/compiler_options.h" +#include "gc/space/image_space.h" #include "gc/space/space.h" #include "image_writer.h" #include "linker/relative_patcher.h" @@ -43,6 +44,7 @@ #include "safe_map.h" #include "scoped_thread_state_change.h" #include "handle_scope-inl.h" +#include "utils/dex_cache_arrays_layout-inl.h" #include "verifier/method_verifier.h" namespace art { @@ -143,6 +145,18 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, } size_ = offset; + if (!HasImage()) { + // Allocate space for app dex cache arrays in the .bss section. + size_t bss_start = RoundUp(size_, kPageSize); + size_t pointer_size = GetInstructionSetPointerSize(instruction_set); + bss_size_ = 0u; + for (const DexFile* dex_file : dex_files) { + dex_cache_arrays_offsets_.Put(dex_file, bss_start + bss_size_); + DexCacheArraysLayout layout(pointer_size, dex_file); + bss_size_ += layout.Size(); + } + } + CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); CHECK_EQ(compiler->IsImage(), image_writer_ != nullptr); CHECK_EQ(compiler->IsImage(), @@ -655,10 +669,10 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { no_thread_suspension_(soa_.Self(), "OatWriter patching"), class_linker_(Runtime::Current()->GetClassLinker()), dex_cache_(nullptr) { - if (writer_->image_writer_ != nullptr) { + patched_code_.reserve(16 * KB); + if (writer_->HasImage()) { // If we're creating the image, the address space must be ready so that we can apply patches. CHECK(writer_->image_writer_->IsImageAddressSpaceReady()); - patched_code_.reserve(16 * KB); } } @@ -841,24 +855,28 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { } uint32_t GetDexCacheOffset(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) { - if (writer_->image_writer_ != nullptr) { + if (writer_->HasImage()) { auto* element = writer_->image_writer_->GetDexCacheArrayElementImageAddress<const uint8_t*>( patch.TargetDexCacheDexFile(), patch.TargetDexCacheElementOffset()); const uint8_t* oat_data = writer_->image_writer_->GetOatFileBegin() + file_offset_; return element - oat_data; } else { - LOG(FATAL) << "Unimplemented."; - UNREACHABLE(); + size_t start = writer_->dex_cache_arrays_offsets_.Get(patch.TargetDexCacheDexFile()); + return start + patch.TargetDexCacheElementOffset(); } } void PatchObjectAddress(std::vector<uint8_t>* code, uint32_t offset, mirror::Object* object) SHARED_REQUIRES(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) { + if (writer_->HasImage()) { object = writer_->image_writer_->GetImageAddress(object); + } else { + // NOTE: We're using linker patches for app->boot references when the image can + // be relocated and therefore we need to emit .oat_patches. We're not using this + // for app->app references, so check that the object is in the image space. + DCHECK(Runtime::Current()->GetHeap()->FindSpaceFromObject(object, false)->IsImageSpace()); } + // Note: We only patch targeting Objects in image which is in the low 4gb. uint32_t address = PointerToLowMemUInt32(object); DCHECK_LE(offset + 4, code->size()); uint8_t* data = &(*code)[offset]; @@ -870,12 +888,17 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { void PatchMethodAddress(std::vector<uint8_t>* code, uint32_t offset, ArtMethod* method) SHARED_REQUIRES(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) { + if (writer_->HasImage()) { method = writer_->image_writer_->GetImageMethodAddress(method); + } else if (kIsDebugBuild) { + // NOTE: We're using linker patches for app->boot references when the image can + // be relocated and therefore we need to emit .oat_patches. We're not using this + // for app->app references, so check that the method is an image method. + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); + size_t method_offset = reinterpret_cast<const uint8_t*>(method) - image_space->Begin(); + CHECK(image_space->GetImageHeader().GetMethodsSection().Contains(method_offset)); } - // Note: We only patch ArtMethods to low 4gb since thats where the image is. + // Note: We only patch targeting ArtMethods in image which is in the low 4gb. uint32_t address = PointerToLowMemUInt32(method); DCHECK_LE(offset + 4, code->size()); uint8_t* data = &(*code)[offset]; @@ -887,9 +910,11 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset) SHARED_REQUIRES(Locks::mutator_lock_) { - uint32_t address = writer_->image_writer_ == nullptr ? target_offset : - PointerToLowMemUInt32(writer_->image_writer_->GetOatFileBegin() + - writer_->oat_data_offset_ + target_offset); + uint32_t address = target_offset; + if (writer_->HasImage()) { + address = PointerToLowMemUInt32(writer_->image_writer_->GetOatFileBegin() + + writer_->oat_data_offset_ + target_offset); + } DCHECK_LE(offset + 4, code->size()); uint8_t* data = &(*code)[offset]; data[0] = address & 0xffu; |