summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/compiled_method.h15
-rw-r--r--compiler/image_writer.cc1
-rw-r--r--compiler/linker/arm64/relative_patcher_arm64.cc2
-rw-r--r--compiler/oat_writer.cc47
-rw-r--r--compiler/oat_writer.h2
-rw-r--r--compiler/optimizing/bounds_check_elimination.cc8
-rw-r--r--compiler/optimizing/code_generator_arm64.cc24
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc19
-rw-r--r--compiler/optimizing/code_generator_mips.cc24
-rw-r--r--compiler/optimizing/code_generator_mips64.cc21
-rw-r--r--compiler/optimizing/code_generator_x86.cc19
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc17
-rw-r--r--compiler/optimizing/instruction_builder.cc1
-rw-r--r--compiler/optimizing/loop_optimization.cc21
-rw-r--r--compiler/optimizing/nodes.cc3
-rw-r--r--compiler/optimizing/nodes.h6
-rw-r--r--compiler/optimizing/pc_relative_fixups_mips.cc1
-rw-r--r--compiler/optimizing/pc_relative_fixups_x86.cc1
-rw-r--r--compiler/optimizing/sharpening.cc12
19 files changed, 218 insertions, 26 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/image_writer.cc b/compiler/image_writer.cc
index fa9f64c9a6..4ffe238cc7 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -73,6 +73,7 @@
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "utils/dex_cache_arrays_layout-inl.h"
+#include "well_known_classes.h"
using ::art::mirror::Class;
using ::art::mirror::DexCache;
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/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index 2f96cfa382..6b832da2bb 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -1143,9 +1143,9 @@ class BCEVisitor : public HGraphVisitor {
ValueBound(nullptr, 1 - right_const),
ValueBound(nullptr, right_const - 1));
- ValueRange* left_range = LookupValueRange(left, left->GetBlock());
+ ValueRange* left_range = LookupValueRange(left, instruction->GetBlock());
if (left_range != nullptr) {
- right_range = left_range->Narrow(right_range);
+ right_range = right_range->Narrow(left_range);
}
AssignRange(instruction->GetBlock(), instruction, right_range);
return;
@@ -1172,9 +1172,9 @@ class BCEVisitor : public HGraphVisitor {
GetGraph()->GetArena(),
lower,
upper);
- ValueRange* left_range = LookupValueRange(left, left->GetBlock());
+ ValueRange* left_range = LookupValueRange(left, instruction->GetBlock());
if (left_range != nullptr) {
- right_range = left_range->Narrow(right_range);
+ right_range = right_range->Narrow(left_range);
}
AssignRange(instruction->GetBlock(), instruction, right_range);
return;
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/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index ca3b191cb0..6532ec123d 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -25,6 +25,7 @@
#include "quicken_info.h"
#include "scoped_thread_state_change-inl.h"
#include "sharpening.h"
+#include "well_known_classes.h"
namespace art {
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index e150b65628..baa045390b 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -34,6 +34,9 @@ static constexpr bool kEnableVectorization = true;
// All current SIMD targets want 16-byte alignment.
static constexpr size_t kAlignedBase = 16;
+// No loop unrolling factor (just one copy of the loop-body).
+static constexpr uint32_t kNoUnrollingFactor = 1;
+
// Remove the instruction from the graph. A bit more elaborate than the usual
// instruction removal, since there may be a cycle in the use structure.
static void RemoveFromCycle(HInstruction* instruction) {
@@ -791,7 +794,7 @@ void HLoopOptimization::Vectorize(LoopNode* node,
vector_index_,
ptc,
graph_->GetIntConstant(1),
- /*unroll*/ 1);
+ kNoUnrollingFactor);
}
// Generate vector loop, possibly further unrolled:
@@ -818,7 +821,7 @@ void HLoopOptimization::Vectorize(LoopNode* node,
vector_index_,
stc,
graph_->GetIntConstant(1),
- /*unroll*/ 1);
+ kNoUnrollingFactor);
}
// Link reductions to their final uses.
@@ -1767,14 +1770,17 @@ static constexpr uint32_t ARM64_SIMD_HEURISTIC_MAX_BODY_SIZE = 50;
uint32_t HLoopOptimization::GetUnrollingFactor(HBasicBlock* block, int64_t trip_count) {
switch (compiler_driver_->GetInstructionSet()) {
case kArm64: {
- DCHECK_NE(vector_length_, 0u);
+ // Don't unroll with insufficient iterations.
// TODO: Unroll loops with unknown trip count.
+ DCHECK_NE(vector_length_, 0u);
if (trip_count < 2 * vector_length_) {
- return 1;
+ return kNoUnrollingFactor;
}
-
+ // Don't unroll for large loop body size.
uint32_t instruction_count = block->GetInstructions().CountSize();
-
+ if (instruction_count >= ARM64_SIMD_HEURISTIC_MAX_BODY_SIZE) {
+ return kNoUnrollingFactor;
+ }
// Find a beneficial unroll factor with the following restrictions:
// - At least one iteration of the transformed loop should be executed.
// - The loop body shouldn't be "too big" (heuristic).
@@ -1783,13 +1789,12 @@ uint32_t HLoopOptimization::GetUnrollingFactor(HBasicBlock* block, int64_t trip_
uint32_t unroll_factor =
TruncToPowerOfTwo(std::min({uf1, uf2, ARM64_SIMD_MAXIMUM_UNROLL_FACTOR}));
DCHECK_GE(unroll_factor, 1u);
-
return unroll_factor;
}
case kX86:
case kX86_64:
default:
- return 1;
+ return kNoUnrollingFactor;
}
}
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 217a8f29a8..9cff6b005b 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2777,6 +2777,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();
@@ -2810,6 +2811,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 6bf53f7147..a6d0da1c96 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -5676,6 +5676,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,
@@ -5821,6 +5825,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;
}
@@ -5854,6 +5859,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;
}
}