ART: Use .bss section for dex cache arrays.
Change-Id: I5fd507973b56f6a662a02a8c1dd9ac4493fb7b36
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 7b410bf..a78a5b3 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 @@
}
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 @@
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 @@
}
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 @@
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 @@
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;