summaryrefslogtreecommitdiff
path: root/compiler/oat_writer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/oat_writer.cc')
-rw-r--r--compiler/oat_writer.cc65
1 files changed, 63 insertions, 2 deletions
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 58b6137c7a..a33081e033 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -335,6 +335,7 @@ OatWriter::OatWriter(bool compiling_boot_image, TimingLogger* timings, ProfileCo
bss_method_entries_(),
bss_type_entries_(),
bss_string_entries_(),
+ map_boot_image_tables_to_bss_(false),
oat_data_offset_(0u),
oat_header_(nullptr),
size_vdex_header_(0),
@@ -771,6 +772,8 @@ class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor {
} else if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) {
StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
writer_->bss_string_entries_.Overwrite(ref, /* placeholder */ 0u);
+ } else if (patch.GetType() == LinkerPatch::Type::kStringInternTable) {
+ writer_->map_boot_image_tables_to_bss_ = true;
}
}
} else {
@@ -1398,6 +1401,14 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
target_offset);
break;
}
+ case LinkerPatch::Type::kStringInternTable: {
+ uint32_t target_offset = GetInternTableEntryOffset(patch);
+ writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_,
+ patch,
+ offset_ + literal_offset,
+ target_offset);
+ break;
+ }
case LinkerPatch::Type::kStringBssEntry: {
StringReference ref(patch.TargetStringDexFile(), patch.TargetStringIndex());
uint32_t target_offset =
@@ -1535,7 +1546,6 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
}
mirror::String* GetTargetString(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) {
- ScopedObjectAccessUnchecked soa(Thread::Current());
ClassLinker* linker = Runtime::Current()->GetClassLinker();
mirror::String* string = linker->LookupString(*patch.TargetStringDexFile(),
patch.TargetStringIndex(),
@@ -1603,6 +1613,28 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
data[2] = (address >> 16) & 0xffu;
data[3] = (address >> 24) & 0xffu;
}
+
+ // Calculate the offset of the InternTable slot (GcRoot<String>) when mmapped to the .bss.
+ uint32_t GetInternTableEntryOffset(const LinkerPatch& patch)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(!writer_->HasBootImage());
+ const uint8_t* string_root = writer_->LookupBootImageInternTableSlot(
+ *patch.TargetStringDexFile(), patch.TargetStringIndex());
+ DCHECK(string_root != nullptr);
+ uint32_t base_offset = writer_->bss_start_;
+ for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
+ const uint8_t* const_tables_begin =
+ space->Begin() + space->GetImageHeader().GetBootImageConstantTablesOffset();
+ size_t offset = static_cast<size_t>(string_root - const_tables_begin);
+ if (offset < space->GetImageHeader().GetBootImageConstantTablesSize()) {
+ DCHECK_LE(base_offset + offset, writer_->bss_start_ + writer_->bss_methods_offset_);
+ return base_offset + offset;
+ }
+ base_offset += space->GetImageHeader().GetBootImageConstantTablesSize();
+ }
+ LOG(FATAL) << "Didn't find boot image string in boot image intern tables!";
+ UNREACHABLE();
+ }
};
class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor {
@@ -1942,16 +1974,24 @@ void OatWriter::InitBssLayout(InstructionSet instruction_set) {
DCHECK_EQ(bss_size_, 0u);
if (HasBootImage()) {
+ DCHECK(!map_boot_image_tables_to_bss_);
DCHECK(bss_string_entries_.empty());
}
- if (bss_method_entries_.empty() &&
+ if (!map_boot_image_tables_to_bss_ &&
+ bss_method_entries_.empty() &&
bss_type_entries_.empty() &&
bss_string_entries_.empty()) {
// Nothing to put to the .bss section.
return;
}
+ // Allocate space for boot image tables in the .bss section.
PointerSize pointer_size = GetInstructionSetPointerSize(instruction_set);
+ if (map_boot_image_tables_to_bss_) {
+ for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) {
+ bss_size_ += space->GetImageHeader().GetBootImageConstantTablesSize();
+ }
+ }
bss_methods_offset_ = bss_size_;
@@ -3500,4 +3540,25 @@ bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream* out) const
return true;
}
+const uint8_t* OatWriter::LookupBootImageInternTableSlot(const DexFile& dex_file,
+ dex::StringIndex string_idx)
+ NO_THREAD_SAFETY_ANALYSIS {
+ // Single-threaded OatWriter can avoid locking.
+ uint32_t utf16_length;
+ const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
+ DCHECK_EQ(utf16_length, CountModifiedUtf8Chars(utf8_data));
+ InternTable::Utf8String string(utf16_length,
+ utf8_data,
+ ComputeUtf16HashFromModifiedUtf8(utf8_data, utf16_length));
+ const InternTable* intern_table = Runtime::Current()->GetClassLinker()->intern_table_;
+ for (const InternTable::Table::UnorderedSet& table : intern_table->strong_interns_.tables_) {
+ auto it = table.Find(string);
+ if (it != table.end()) {
+ return reinterpret_cast<const uint8_t*>(std::addressof(*it));
+ }
+ }
+ LOG(FATAL) << "Did not find boot image string " << utf8_data;
+ UNREACHABLE();
+}
+
} // namespace art