diff options
-rw-r--r-- | compiler/compiled_method.h | 15 | ||||
-rw-r--r-- | compiler/linker/arm64/relative_patcher_arm64.cc | 2 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 47 | ||||
-rw-r--r-- | compiler/oat_writer.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 24 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm_vixl.cc | 19 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_mips.cc | 24 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_mips64.cc | 21 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 19 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 17 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 3 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 6 | ||||
-rw-r--r-- | compiler/optimizing/pc_relative_fixups_mips.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/pc_relative_fixups_x86.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/sharpening.cc | 12 | ||||
-rw-r--r-- | runtime/class_linker.h | 2 | ||||
-rw-r--r-- | runtime/class_table.h | 1 | ||||
-rw-r--r-- | test/552-checker-sharpening/src/Main.java | 12 |
18 files changed, 207 insertions, 21 deletions
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h index c67c523eb3..5ef6cbff78 100644 --- a/compiler/compiled_method.h +++ b/compiler/compiled_method.h @@ -124,6 +124,7 @@ class LinkerPatch { kCall, kCallRelative, // NOTE: Actual patching is instruction_set-dependent. kTypeRelative, // NOTE: Actual patching is instruction_set-dependent. + kTypeClassTable, // NOTE: Actual patching is instruction_set-dependent. kTypeBssEntry, // NOTE: Actual patching is instruction_set-dependent. kStringRelative, // NOTE: Actual patching is instruction_set-dependent. kStringInternTable, // NOTE: Actual patching is instruction_set-dependent. @@ -177,6 +178,16 @@ class LinkerPatch { return patch; } + static LinkerPatch TypeClassTablePatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_type_idx) { + LinkerPatch patch(literal_offset, Type::kTypeClassTable, target_dex_file); + patch.type_idx_ = target_type_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + static LinkerPatch TypeBssEntryPatch(size_t literal_offset, const DexFile* target_dex_file, uint32_t pc_insn_offset, @@ -243,6 +254,7 @@ class LinkerPatch { case Type::kMethodBssEntry: case Type::kCallRelative: case Type::kTypeRelative: + case Type::kTypeClassTable: case Type::kTypeBssEntry: case Type::kStringRelative: case Type::kStringInternTable: @@ -264,12 +276,14 @@ class LinkerPatch { const DexFile* TargetTypeDexFile() const { DCHECK(patch_type_ == Type::kTypeRelative || + patch_type_ == Type::kTypeClassTable || patch_type_ == Type::kTypeBssEntry); return target_dex_file_; } dex::TypeIndex TargetTypeIndex() const { DCHECK(patch_type_ == Type::kTypeRelative || + patch_type_ == Type::kTypeClassTable || patch_type_ == Type::kTypeBssEntry); return dex::TypeIndex(type_idx_); } @@ -292,6 +306,7 @@ class LinkerPatch { DCHECK(patch_type_ == Type::kMethodRelative || patch_type_ == Type::kMethodBssEntry || patch_type_ == Type::kTypeRelative || + patch_type_ == Type::kTypeClassTable || patch_type_ == Type::kTypeBssEntry || patch_type_ == Type::kStringRelative || patch_type_ == Type::kStringInternTable || diff --git a/compiler/linker/arm64/relative_patcher_arm64.cc b/compiler/linker/arm64/relative_patcher_arm64.cc index 0ebabc15aa..4960f4d856 100644 --- a/compiler/linker/arm64/relative_patcher_arm64.cc +++ b/compiler/linker/arm64/relative_patcher_arm64.cc @@ -61,6 +61,7 @@ inline bool IsAdrpPatch(const LinkerPatch& patch) { case LinkerPatch::Type::kMethodRelative: case LinkerPatch::Type::kMethodBssEntry: case LinkerPatch::Type::kTypeRelative: + case LinkerPatch::Type::kTypeClassTable: case LinkerPatch::Type::kTypeBssEntry: case LinkerPatch::Type::kStringRelative: case LinkerPatch::Type::kStringInternTable: @@ -266,6 +267,7 @@ void Arm64RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code, } else { // LDR/STR 32-bit or 64-bit with imm12 == 0 (unset). DCHECK(patch.GetType() == LinkerPatch::Type::kMethodBssEntry || + patch.GetType() == LinkerPatch::Type::kTypeClassTable || patch.GetType() == LinkerPatch::Type::kTypeBssEntry || patch.GetType() == LinkerPatch::Type::kStringInternTable || patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType(); diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index a33081e033..cc8c6dfac0 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -28,6 +28,7 @@ #include "base/stl_util.h" #include "base/unix_file/fd_file.h" #include "class_linker.h" +#include "class_table-inl.h" #include "compiled_method.h" #include "debug/method_debug_info.h" #include "dex/verification_results.h" @@ -772,7 +773,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) { + } else if (patch.GetType() == LinkerPatch::Type::kStringInternTable || + patch.GetType() == LinkerPatch::Type::kTypeClassTable) { writer_->map_boot_image_tables_to_bss_ = true; } } @@ -1427,6 +1429,14 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { target_offset); break; } + case LinkerPatch::Type::kTypeClassTable: { + uint32_t target_offset = GetClassTableEntryOffset(patch); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } case LinkerPatch::Type::kTypeBssEntry: { TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); uint32_t target_offset = writer_->bss_start_ + writer_->bss_type_entries_.Get(ref); @@ -1621,11 +1631,25 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { const uint8_t* string_root = writer_->LookupBootImageInternTableSlot( *patch.TargetStringDexFile(), patch.TargetStringIndex()); DCHECK(string_root != nullptr); + return GetBootImageTableEntryOffset(string_root); + } + + // Calculate the offset of the ClassTable::TableSlot when mmapped to the .bss. + uint32_t GetClassTableEntryOffset(const LinkerPatch& patch) + REQUIRES_SHARED(Locks::mutator_lock_) { + DCHECK(!writer_->HasBootImage()); + const uint8_t* table_slot = + writer_->LookupBootImageClassTableSlot(*patch.TargetTypeDexFile(), patch.TargetTypeIndex()); + DCHECK(table_slot != nullptr); + return GetBootImageTableEntryOffset(table_slot); + } + + uint32_t GetBootImageTableEntryOffset(const uint8_t* raw_root) { 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); + size_t offset = static_cast<size_t>(raw_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; @@ -3542,8 +3566,7 @@ bool OatWriter::OatClass::Write(OatWriter* oat_writer, OutputStream* out) const const uint8_t* OatWriter::LookupBootImageInternTableSlot(const DexFile& dex_file, dex::StringIndex string_idx) - NO_THREAD_SAFETY_ANALYSIS { - // Single-threaded OatWriter can avoid locking. + 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)); @@ -3561,4 +3584,20 @@ const uint8_t* OatWriter::LookupBootImageInternTableSlot(const DexFile& dex_file UNREACHABLE(); } +const uint8_t* OatWriter::LookupBootImageClassTableSlot(const DexFile& dex_file, + dex::TypeIndex type_idx) + NO_THREAD_SAFETY_ANALYSIS { // Single-threaded OatWriter can avoid locking. + const char* descriptor = dex_file.StringByTypeIdx(type_idx); + ClassTable::DescriptorHashPair pair(descriptor, ComputeModifiedUtf8Hash(descriptor)); + ClassTable* table = Runtime::Current()->GetClassLinker()->boot_class_table_.get(); + for (const ClassTable::ClassSet& class_set : table->classes_) { + auto it = class_set.Find(pair); + if (it != class_set.end()) { + return reinterpret_cast<const uint8_t*>(std::addressof(*it)); + } + } + LOG(FATAL) << "Did not find boot image class " << descriptor; + UNREACHABLE(); +} + } // namespace art diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h index 780dee0bac..7f2045f8da 100644 --- a/compiler/oat_writer.h +++ b/compiler/oat_writer.h @@ -336,6 +336,8 @@ class OatWriter { // Find the address of the GcRoot<String> in the InternTable for a boot image string. const uint8_t* LookupBootImageInternTableSlot(const DexFile& dex_file, dex::StringIndex string_idx); + // Find the address of the ClassTable::TableSlot for a boot image class. + const uint8_t* LookupBootImageClassTableSlot(const DexFile& dex_file, dex::TypeIndex type_idx); enum class WriteState { kAddingDexFileSources, diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 1b628688ec..19e5d067a1 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -21,6 +21,7 @@ #include "art_method.h" #include "base/bit_utils.h" #include "base/bit_utils_iterator.h" +#include "class_table.h" #include "code_generator_utils.h" #include "compiled_method.h" #include "entrypoints/quick/quick_entrypoints.h" @@ -4784,7 +4785,8 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patc linker_patches); } else { DCHECK(pc_relative_method_patches_.empty()); - DCHECK(pc_relative_type_patches_.empty()); + EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(pc_relative_type_patches_, + linker_patches); EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(pc_relative_string_patches_, linker_patches); } @@ -4861,6 +4863,7 @@ HLoadClass::LoadKind CodeGeneratorARM64::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kReferrersClass: break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; @@ -4972,6 +4975,25 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address)); break; } + case HLoadClass::LoadKind::kBootImageClassTable: { + DCHECK(!codegen_->GetCompilerOptions().IsBootImage()); + // Add ADRP with its PC-relative type patch. + const DexFile& dex_file = cls->GetDexFile(); + dex::TypeIndex type_index = cls->GetTypeIndex(); + vixl::aarch64::Label* adrp_label = codegen_->NewPcRelativeTypePatch(dex_file, type_index); + codegen_->EmitAdrpPlaceholder(adrp_label, out.X()); + // Add LDR with its PC-relative type patch. + vixl::aarch64::Label* ldr_label = + codegen_->NewPcRelativeTypePatch(dex_file, type_index, adrp_label); + codegen_->EmitLdrOffsetPlaceholder(ldr_label, out.W(), out.X()); + // Extract the reference from the slot data, i.e. clear the hash bits. + int32_t masked_hash = ClassTable::TableSlot::MaskHash( + ComputeModifiedUtf8Hash(dex_file.StringByTypeIdx(type_index))); + if (masked_hash != 0) { + __ Sub(out.W(), out.W(), Operand(masked_hash)); + } + break; + } case HLoadClass::LoadKind::kBssEntry: { // Add ADRP with its PC-relative Class .bss entry patch. const DexFile& dex_file = cls->GetDexFile(); diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 8288141954..8b9495d564 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -21,6 +21,7 @@ #include "art_method.h" #include "base/bit_utils.h" #include "base/bit_utils_iterator.h" +#include "class_table.h" #include "code_generator_utils.h" #include "common_arm.h" #include "compiled_method.h" @@ -7122,6 +7123,7 @@ HLoadClass::LoadKind CodeGeneratorARMVIXL::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kReferrersClass: break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; @@ -7234,6 +7236,20 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_ __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address)); break; } + case HLoadClass::LoadKind::kBootImageClassTable: { + DCHECK(!codegen_->GetCompilerOptions().IsBootImage()); + CodeGeneratorARMVIXL::PcRelativePatchInfo* labels = + codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex()); + codegen_->EmitMovwMovtPlaceholder(labels, out); + __ Ldr(out, MemOperand(out, /* offset */ 0)); + // Extract the reference from the slot data, i.e. clear the hash bits. + int32_t masked_hash = ClassTable::TableSlot::MaskHash( + ComputeModifiedUtf8Hash(cls->GetDexFile().StringByTypeIdx(cls->GetTypeIndex()))); + if (masked_hash != 0) { + __ Sub(out, out, Operand(masked_hash)); + } + break; + } case HLoadClass::LoadKind::kBssEntry: { vixl32::Register temp = (!kUseReadBarrier || kUseBakerReadBarrier) ? RegisterFrom(locations->GetTemp(0)) @@ -9214,7 +9230,8 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_pa linker_patches); } else { DCHECK(pc_relative_method_patches_.empty()); - DCHECK(pc_relative_type_patches_.empty()); + EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(pc_relative_type_patches_, + linker_patches); EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(pc_relative_string_patches_, linker_patches); } diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index ac8f675e2d..f0ef0071b6 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -20,6 +20,7 @@ #include "arch/mips/entrypoints_direct_mips.h" #include "arch/mips/instruction_set_features_mips.h" #include "art_method.h" +#include "class_table.h" #include "code_generator_utils.h" #include "compiled_method.h" #include "entrypoints/quick/quick_entrypoints.h" @@ -1664,7 +1665,8 @@ void CodeGeneratorMIPS::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patch linker_patches); } else { DCHECK(pc_relative_method_patches_.empty()); - DCHECK(pc_relative_type_patches_.empty()); + EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(pc_relative_type_patches_, + linker_patches); EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(pc_relative_string_patches_, linker_patches); } @@ -7413,6 +7415,7 @@ HLoadClass::LoadKind CodeGeneratorMIPS::GetSupportedLoadClassKind( fallback_load = false; break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; @@ -7643,6 +7646,7 @@ void LocationsBuilderMIPS::VisitLoadClass(HLoadClass* cls) { // We need an extra register for PC-relative literals on R2. case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageAddress: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: if (isR6) { break; @@ -7741,6 +7745,24 @@ void InstructionCodeGeneratorMIPS::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAF codegen_->DeduplicateBootImageAddressLiteral(address)); break; } + case HLoadClass::LoadKind::kBootImageClassTable: { + DCHECK(!codegen_->GetCompilerOptions().IsBootImage()); + CodeGeneratorMIPS::PcRelativePatchInfo* info_high = + codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex()); + CodeGeneratorMIPS::PcRelativePatchInfo* info_low = + codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high); + codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high, + out, + base_or_current_method_reg); + __ Lw(out, out, /* placeholder */ 0x5678, &info_low->label); + // Extract the reference from the slot data, i.e. clear the hash bits. + int32_t masked_hash = ClassTable::TableSlot::MaskHash( + ComputeModifiedUtf8Hash(cls->GetDexFile().StringByTypeIdx(cls->GetTypeIndex()))); + if (masked_hash != 0) { + __ Addiu(out, out, -masked_hash); + } + break; + } case HLoadClass::LoadKind::kBssEntry: { bss_info_high = codegen_->NewTypeBssEntryPatch(cls->GetDexFile(), cls->GetTypeIndex()); CodeGeneratorMIPS::PcRelativePatchInfo* info_low = diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index 71c2bfff19..201b1b065f 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -18,6 +18,7 @@ #include "arch/mips64/asm_support_mips64.h" #include "art_method.h" +#include "class_table.h" #include "code_generator_utils.h" #include "compiled_method.h" #include "entrypoints/quick/quick_entrypoints.h" @@ -1573,7 +1574,8 @@ void CodeGeneratorMIPS64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_pat linker_patches); } else { DCHECK(pc_relative_method_patches_.empty()); - DCHECK(pc_relative_type_patches_.empty()); + EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(pc_relative_type_patches_, + linker_patches); EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(pc_relative_string_patches_, linker_patches); } @@ -5767,6 +5769,7 @@ HLoadClass::LoadKind CodeGeneratorMIPS64::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kReferrersClass: break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; @@ -6016,6 +6019,22 @@ void InstructionCodeGeneratorMIPS64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S codegen_->DeduplicateBootImageAddressLiteral(address)); break; } + case HLoadClass::LoadKind::kBootImageClassTable: { + DCHECK(!codegen_->GetCompilerOptions().IsBootImage()); + CodeGeneratorMIPS64::PcRelativePatchInfo* info_high = + codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex()); + CodeGeneratorMIPS64::PcRelativePatchInfo* info_low = + codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high); + codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low); + __ Lwu(out, AT, /* placeholder */ 0x5678); + // Extract the reference from the slot data, i.e. clear the hash bits. + int32_t masked_hash = ClassTable::TableSlot::MaskHash( + ComputeModifiedUtf8Hash(cls->GetDexFile().StringByTypeIdx(cls->GetTypeIndex()))); + if (masked_hash != 0) { + __ Daddiu(out, out, -masked_hash); + } + break; + } case HLoadClass::LoadKind::kBssEntry: { bss_info_high = codegen_->NewTypeBssEntryPatch(cls->GetDexFile(), cls->GetTypeIndex()); CodeGeneratorMIPS64::PcRelativePatchInfo* info_low = diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 512968f01d..e45ad0a9a3 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -17,6 +17,7 @@ #include "code_generator_x86.h" #include "art_method.h" +#include "class_table.h" #include "code_generator_utils.h" #include "compiled_method.h" #include "entrypoints/quick/quick_entrypoints.h" @@ -4702,7 +4703,8 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patche EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(string_patches_, linker_patches); } else { DCHECK(boot_image_method_patches_.empty()); - DCHECK(boot_image_type_patches_.empty()); + EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(boot_image_type_patches_, + linker_patches); EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(string_patches_, linker_patches); } @@ -6038,6 +6040,7 @@ HLoadClass::LoadKind CodeGeneratorX86::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kReferrersClass: break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; @@ -6075,6 +6078,7 @@ void LocationsBuilderX86::VisitLoadClass(HLoadClass* cls) { if (load_kind == HLoadClass::LoadKind::kReferrersClass || load_kind == HLoadClass::LoadKind::kBootImageLinkTimePcRelative || + load_kind == HLoadClass::LoadKind::kBootImageClassTable || load_kind == HLoadClass::LoadKind::kBssEntry) { locations->SetInAt(0, Location::RequiresRegister()); } @@ -6151,6 +6155,19 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE __ movl(out, Immediate(address)); break; } + case HLoadClass::LoadKind::kBootImageClassTable: { + DCHECK(!codegen_->GetCompilerOptions().IsBootImage()); + Register method_address = locations->InAt(0).AsRegister<Register>(); + __ movl(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset)); + codegen_->RecordBootTypePatch(cls); + // Extract the reference from the slot data, i.e. clear the hash bits. + int32_t masked_hash = ClassTable::TableSlot::MaskHash( + ComputeModifiedUtf8Hash(cls->GetDexFile().StringByTypeIdx(cls->GetTypeIndex()))); + if (masked_hash != 0) { + __ subl(out, Immediate(masked_hash)); + } + break; + } case HLoadClass::LoadKind::kBssEntry: { Register method_address = locations->InAt(0).AsRegister<Register>(); Address address(method_address, CodeGeneratorX86::kDummy32BitOffset); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 0c3b2ad742..8c4374d71e 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -17,6 +17,7 @@ #include "code_generator_x86_64.h" #include "art_method.h" +#include "class_table.h" #include "code_generator_utils.h" #include "compiled_method.h" #include "entrypoints/quick/quick_entrypoints.h" @@ -1133,7 +1134,8 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_pat EmitPcRelativeLinkerPatches<LinkerPatch::RelativeStringPatch>(string_patches_, linker_patches); } else { DCHECK(boot_image_method_patches_.empty()); - DCHECK(boot_image_type_patches_.empty()); + EmitPcRelativeLinkerPatches<LinkerPatch::TypeClassTablePatch>(boot_image_type_patches_, + linker_patches); EmitPcRelativeLinkerPatches<LinkerPatch::StringInternTablePatch>(string_patches_, linker_patches); } @@ -5456,6 +5458,7 @@ HLoadClass::LoadKind CodeGeneratorX86_64::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kReferrersClass: break; case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: DCHECK(!Runtime::Current()->UseJitCompilation()); break; @@ -5564,6 +5567,18 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S __ movl(out, Immediate(static_cast<int32_t>(address))); // Zero-extended. break; } + case HLoadClass::LoadKind::kBootImageClassTable: { + DCHECK(!codegen_->GetCompilerOptions().IsBootImage()); + __ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false)); + codegen_->RecordBootTypePatch(cls); + // Extract the reference from the slot data, i.e. clear the hash bits. + int32_t masked_hash = ClassTable::TableSlot::MaskHash( + ComputeModifiedUtf8Hash(cls->GetDexFile().StringByTypeIdx(cls->GetTypeIndex()))); + if (masked_hash != 0) { + __ subl(out, Immediate(masked_hash)); + } + break; + } case HLoadClass::LoadKind::kBssEntry: { Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false); diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index ebbea27e08..2a7017c2cb 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -2736,6 +2736,7 @@ bool HLoadClass::InstructionDataEquals(const HInstruction* other) const { } switch (GetLoadKind()) { case LoadKind::kBootImageAddress: + case LoadKind::kBootImageClassTable: case LoadKind::kJitTableAddress: { ScopedObjectAccess soa(Thread::Current()); return GetClass().Get() == other_load_class->GetClass().Get(); @@ -2769,6 +2770,8 @@ std::ostream& operator<<(std::ostream& os, HLoadClass::LoadKind rhs) { return os << "BootImageLinkTimePcRelative"; case HLoadClass::LoadKind::kBootImageAddress: return os << "BootImageAddress"; + case HLoadClass::LoadKind::kBootImageClassTable: + return os << "BootImageClassTable"; case HLoadClass::LoadKind::kBssEntry: return os << "BssEntry"; case HLoadClass::LoadKind::kJitTableAddress: diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 5e8c77102a..b551f37135 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -5675,6 +5675,10 @@ class HLoadClass FINAL : public HInstruction { // Used for boot image classes referenced by apps in AOT- and JIT-compiled code. kBootImageAddress, + // Use a PC-relative load from a boot image ClassTable mmapped into the .bss + // of the oat file. + kBootImageClassTable, + // Load from an entry in the .bss section using a PC-relative load. // Used for classes outside boot image when .bss is accessible with a PC-relative load. kBssEntry, @@ -5820,6 +5824,7 @@ class HLoadClass FINAL : public HInstruction { static bool HasTypeReference(LoadKind load_kind) { return load_kind == LoadKind::kReferrersClass || load_kind == LoadKind::kBootImageLinkTimePcRelative || + load_kind == LoadKind::kBootImageClassTable || load_kind == LoadKind::kBssEntry || load_kind == LoadKind::kRuntimeCall; } @@ -5853,6 +5858,7 @@ inline void HLoadClass::AddSpecialInput(HInstruction* special_input) { // including literal pool loads, which are PC-relative too. DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative || GetLoadKind() == LoadKind::kBootImageAddress || + GetLoadKind() == LoadKind::kBootImageClassTable || GetLoadKind() == LoadKind::kBssEntry) << GetLoadKind(); DCHECK(special_input_.GetInstruction() == nullptr); special_input_ = HUserRecord<HInstruction*>(special_input); diff --git a/compiler/optimizing/pc_relative_fixups_mips.cc b/compiler/optimizing/pc_relative_fixups_mips.cc index 4cb99f9b5c..e569b78c9d 100644 --- a/compiler/optimizing/pc_relative_fixups_mips.cc +++ b/compiler/optimizing/pc_relative_fixups_mips.cc @@ -75,6 +75,7 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { switch (load_kind) { case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageAddress: + case HLoadClass::LoadKind::kBootImageClassTable: case HLoadClass::LoadKind::kBssEntry: // Add a base register for PC-relative literals on R2. InitializePCRelativeBasePointer(); diff --git a/compiler/optimizing/pc_relative_fixups_x86.cc b/compiler/optimizing/pc_relative_fixups_x86.cc index c463ecdb0a..9877e10474 100644 --- a/compiler/optimizing/pc_relative_fixups_x86.cc +++ b/compiler/optimizing/pc_relative_fixups_x86.cc @@ -83,6 +83,7 @@ class PCRelativeHandlerVisitor : public HGraphVisitor { void VisitLoadClass(HLoadClass* load_class) OVERRIDE { HLoadClass::LoadKind load_kind = load_class->GetLoadKind(); if (load_kind == HLoadClass::LoadKind::kBootImageLinkTimePcRelative || + load_kind == HLoadClass::LoadKind::kBootImageClassTable || load_kind == HLoadClass::LoadKind::kBssEntry) { HX86ComputeBaseMethodAddress* method_address = GetPCRelativeBasePointer(load_class); load_class->AddSpecialInput(method_address); diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc index 1ca63f4f86..e46c9a7081 100644 --- a/compiler/optimizing/sharpening.cc +++ b/compiler/optimizing/sharpening.cc @@ -205,11 +205,15 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind(HLoadClass* load_class, // TODO(ngeoffray): Generate HDeoptimize instead. desired_load_kind = HLoadClass::LoadKind::kRuntimeCall; } - } else if (is_in_boot_image && !codegen->GetCompilerOptions().GetCompilePic()) { - // AOT app compilation. Check if the class is in the boot image. - desired_load_kind = HLoadClass::LoadKind::kBootImageAddress; + } else if (is_in_boot_image) { + // AOT app compilation, boot image class. + if (codegen->GetCompilerOptions().GetCompilePic()) { + desired_load_kind = HLoadClass::LoadKind::kBootImageClassTable; + } else { + desired_load_kind = HLoadClass::LoadKind::kBootImageAddress; + } } else { - // Not JIT and either the klass is not in boot image or we are compiling in PIC mode. + // Not JIT and the klass is not in boot image. desired_load_kind = HLoadClass::LoadKind::kBssEntry; } } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 8c2f0a5064..9727adff44 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -1278,7 +1278,7 @@ class ClassLinker { friend class ImageWriter; // for GetClassRoots friend class JniCompilerTest; // for GetRuntimeQuickGenericJniStub friend class JniInternalTest; // for GetRuntimeQuickGenericJniStub - friend class OatWriter; // for boot image string table slot address lookup. + friend class OatWriter; // for boot image string/class table slot address lookup. friend class VMClassLoader; // for LookupClass and FindClassInBaseDexClassLoader. ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for DexLock, and RegisterDexFileLocked ART_FRIEND_TEST(mirror::DexCacheMethodHandlesTest, Open); // for AllocDexCache diff --git a/runtime/class_table.h b/runtime/class_table.h index a259725399..0ffe93e051 100644 --- a/runtime/class_table.h +++ b/runtime/class_table.h @@ -287,6 +287,7 @@ class ClassTable { std::vector<const OatFile*> oat_files_ GUARDED_BY(lock_); friend class ImageWriter; // for InsertWithoutLocks. + friend class OatWriter; // for boot class TableSlot address lookup. }; } // namespace art diff --git a/test/552-checker-sharpening/src/Main.java b/test/552-checker-sharpening/src/Main.java index 7a60bb5cc0..1f1920ca15 100644 --- a/test/552-checker-sharpening/src/Main.java +++ b/test/552-checker-sharpening/src/Main.java @@ -277,27 +277,27 @@ public class Main { /// CHECK-START-X86: java.lang.Class Main.$noinline$getStringClass() sharpening (after) // Note: load kind depends on PIC/non-PIC - /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String + /// CHECK: LoadClass load_kind:{{BootImageAddress|BootImageClassTable}} class_name:java.lang.String /// CHECK-START-X86_64: java.lang.Class Main.$noinline$getStringClass() sharpening (after) // Note: load kind depends on PIC/non-PIC - /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String + /// CHECK: LoadClass load_kind:{{BootImageAddress|BootImageClassTable}} class_name:java.lang.String /// CHECK-START-ARM: java.lang.Class Main.$noinline$getStringClass() sharpening (after) // Note: load kind depends on PIC/non-PIC - /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String + /// CHECK: LoadClass load_kind:{{BootImageAddress|BootImageClassTable}} class_name:java.lang.String /// CHECK-START-ARM64: java.lang.Class Main.$noinline$getStringClass() sharpening (after) // Note: load kind depends on PIC/non-PIC - /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String + /// CHECK: LoadClass load_kind:{{BootImageAddress|BootImageClassTable}} class_name:java.lang.String /// CHECK-START-MIPS: java.lang.Class Main.$noinline$getStringClass() sharpening (after) // Note: load kind depends on PIC/non-PIC - /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String + /// CHECK: LoadClass load_kind:{{BootImageAddress|BootImageClassTable}} class_name:java.lang.String /// CHECK-START-MIPS64: java.lang.Class Main.$noinline$getStringClass() sharpening (after) // Note: load kind depends on PIC/non-PIC - /// CHECK: LoadClass load_kind:{{BootImageAddress|BssEntry}} class_name:java.lang.String + /// CHECK: LoadClass load_kind:{{BootImageAddress|BootImageClassTable}} class_name:java.lang.String public static Class<?> $noinline$getStringClass() { // Prevent inlining to avoid the string comparison being optimized away. |