summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/code_generator_arm64.cc64
-rw-r--r--compiler/optimizing/code_generator_arm64.h1
-rw-r--r--compiler/optimizing/code_generator_arm_vixl.cc45
-rw-r--r--compiler/optimizing/code_generator_mips.cc78
-rw-r--r--compiler/optimizing/code_generator_mips64.cc54
-rw-r--r--compiler/optimizing/code_generator_x86.cc42
-rw-r--r--compiler/optimizing/code_generator_x86_64.cc42
-rw-r--r--compiler/optimizing/instruction_builder.cc274
-rw-r--r--compiler/optimizing/instruction_builder.h15
-rw-r--r--compiler/optimizing/instruction_simplifier.cc2
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc4
-rw-r--r--compiler/optimizing/loop_analysis.cc10
-rw-r--r--compiler/optimizing/loop_analysis.h7
-rw-r--r--compiler/optimizing/loop_optimization.cc54
-rw-r--r--compiler/optimizing/loop_optimization.h6
-rw-r--r--compiler/optimizing/nodes.cc16
-rw-r--r--compiler/optimizing/nodes.h48
-rw-r--r--compiler/optimizing/optimizing_cfi_test.cc3
-rw-r--r--compiler/optimizing/pc_relative_fixups_mips.cc4
-rw-r--r--compiler/optimizing/pc_relative_fixups_x86.cc3
-rw-r--r--compiler/optimizing/reference_type_propagation.cc4
-rw-r--r--compiler/optimizing/sharpening.cc26
-rw-r--r--compiler/optimizing/stack_map_stream.cc5
23 files changed, 513 insertions, 294 deletions
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index d1c83ce625..760b1dd09b 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -64,7 +64,6 @@ using helpers::DRegisterFrom;
using helpers::FPRegisterFrom;
using helpers::HeapOperand;
using helpers::HeapOperandFrom;
-using helpers::InputCPURegisterAt;
using helpers::InputCPURegisterOrZeroRegAt;
using helpers::InputFPRegisterAt;
using helpers::InputOperandAt;
@@ -78,7 +77,6 @@ using helpers::OutputFPRegister;
using helpers::OutputRegister;
using helpers::QRegisterFrom;
using helpers::RegisterFrom;
-using helpers::SRegisterFrom;
using helpers::StackOperandFrom;
using helpers::VIXLRegCodeFromART;
using helpers::WRegisterFrom;
@@ -4555,10 +4553,6 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(
EmitAddPlaceholder(add_label, XRegisterFrom(temp), XRegisterFrom(temp));
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
- // Load method address from literal pool.
- __ Ldr(XRegisterFrom(temp), DeduplicateUint64Literal(invoke->GetMethodAddress()));
- break;
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
// Add ADRP with its PC-relative .data.bimg.rel.ro patch.
uint32_t boot_image_offset = GetBootImageOffset(invoke);
@@ -4581,6 +4575,10 @@ void CodeGeneratorARM64::GenerateStaticOrDirectCall(
EmitLdrOffsetPlaceholder(ldr_label, XRegisterFrom(temp), XRegisterFrom(temp));
break;
}
+ case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+ // Load method address from literal pool.
+ __ Ldr(XRegisterFrom(temp), DeduplicateUint64Literal(invoke->GetMethodAddress()));
+ break;
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
return; // No code pointer retrieval; the runtime performs the call directly.
@@ -4812,8 +4810,7 @@ void CodeGeneratorARM64::LoadBootImageAddress(vixl::aarch64::Register reg,
// Add ADD with its PC-relative type patch.
vixl::aarch64::Label* add_label = NewBootImageIntrinsicPatch(boot_image_reference, adrp_label);
EmitAddPlaceholder(add_label, reg.X(), reg.X());
- } else if (GetCompilerOptions().GetCompilePic()) {
- DCHECK(Runtime::Current()->IsAotCompiler());
+ } else if (Runtime::Current()->IsAotCompiler()) {
// Add ADRP with its PC-relative .data.bimg.rel.ro patch.
vixl::aarch64::Label* adrp_label = NewBootImageRelRoPatch(boot_image_reference);
EmitAdrpPlaceholder(adrp_label, reg.X());
@@ -4821,6 +4818,7 @@ void CodeGeneratorARM64::LoadBootImageAddress(vixl::aarch64::Register reg,
vixl::aarch64::Label* ldr_label = NewBootImageRelRoPatch(boot_image_reference, adrp_label);
EmitLdrOffsetPlaceholder(ldr_label, reg.W(), reg.X());
} else {
+ DCHECK(Runtime::Current()->UseJitCompilation());
gc::Heap* heap = Runtime::Current()->GetHeap();
DCHECK(!heap->GetBootImageSpaces().empty());
const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -5016,10 +5014,10 @@ HLoadClass::LoadKind CodeGeneratorARM64::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadClass::LoadKind::kJitBootImageAddress:
case HLoadClass::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kRuntimeCall:
break;
}
@@ -5113,14 +5111,6 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA
codegen_->EmitAddPlaceholder(add_label, out.X(), out.X());
break;
}
- case HLoadClass::LoadKind::kBootImageAddress: {
- DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
- DCHECK_NE(address, 0u);
- __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address));
- break;
- }
case HLoadClass::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
uint32_t boot_image_offset = codegen_->GetBootImageOffset(cls);
@@ -5153,6 +5143,13 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA
generate_null_check = true;
break;
}
+ case HLoadClass::LoadKind::kJitBootImageAddress: {
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+ DCHECK_NE(address, 0u);
+ __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address));
+ break;
+ }
case HLoadClass::LoadKind::kJitTableAddress: {
__ Ldr(out, codegen_->DeduplicateJitClassLiteral(cls->GetDexFile(),
cls->GetTypeIndex(),
@@ -5239,10 +5236,10 @@ HLoadString::LoadKind CodeGeneratorARM64::GetSupportedLoadStringKind(
case HLoadString::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadString::LoadKind::kJitBootImageAddress:
case HLoadString::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kRuntimeCall:
break;
}
@@ -5294,13 +5291,6 @@ void InstructionCodeGeneratorARM64::VisitLoadString(HLoadString* load) NO_THREAD
codegen_->EmitAddPlaceholder(add_label, out.X(), out.X());
return;
}
- case HLoadString::LoadKind::kBootImageAddress: {
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(load->GetString().Get()));
- DCHECK_NE(address, 0u);
- __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address));
- return;
- }
case HLoadString::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
// Add ADRP with its PC-relative .data.bimg.rel.ro patch.
@@ -5339,6 +5329,12 @@ void InstructionCodeGeneratorARM64::VisitLoadString(HLoadString* load) NO_THREAD
codegen_->MaybeGenerateMarkingRegisterCheck(/* code */ __LINE__);
return;
}
+ case HLoadString::LoadKind::kJitBootImageAddress: {
+ uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+ DCHECK_NE(address, 0u);
+ __ Ldr(out.W(), codegen_->DeduplicateBootImageAddressLiteral(address));
+ return;
+ }
case HLoadString::LoadKind::kJitTableAddress: {
__ Ldr(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(),
load->GetStringIndex(),
@@ -5678,14 +5674,6 @@ void InstructionCodeGeneratorARM64::GenerateIntRemForPower2Denom(HRem *instructi
}
}
-void InstructionCodeGeneratorARM64::GenerateIntRemForOneOrMinusOneDenom(HRem *instruction) {
- int64_t imm = Int64FromLocation(instruction->GetLocations()->InAt(1));
- DCHECK(imm == 1 || imm == -1) << imm;
-
- Register out = OutputRegister(instruction);
- __ Mov(out, 0);
-}
-
void InstructionCodeGeneratorARM64::GenerateIntRemForConstDenom(HRem *instruction) {
int64_t imm = Int64FromLocation(instruction->GetLocations()->InAt(1));
@@ -5695,10 +5683,12 @@ void InstructionCodeGeneratorARM64::GenerateIntRemForConstDenom(HRem *instructio
return;
}
- if (imm == 1 || imm == -1) {
- // TODO: These cases need to be optimized in InstructionSimplifier
- GenerateIntRemForOneOrMinusOneDenom(instruction);
- } else if (IsPowerOfTwo(AbsOrMin(imm))) {
+ if (IsPowerOfTwo(AbsOrMin(imm))) {
+ // Cases imm == -1 or imm == 1 are handled in constant folding by
+ // InstructionWithAbsorbingInputSimplifier.
+ // If the cases have survided till code generation they are handled in
+ // GenerateIntRemForPower2Denom becauses -1 and 1 are the power of 2 (2^0).
+ // The correct code is generated for them, just more instructions.
GenerateIntRemForPower2Denom(instruction);
} else {
DCHECK(imm < -2 || imm > 2) << imm;
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index c44fa48066..93bab3180c 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -327,7 +327,6 @@ class InstructionCodeGeneratorARM64 : public InstructionCodeGenerator {
void GenerateIntDivForPower2Denom(HDiv *instruction);
void GenerateIntRem(HRem* instruction);
void GenerateIntRemForConstDenom(HRem *instruction);
- void GenerateIntRemForOneOrMinusOneDenom(HRem *instruction);
void GenerateIntRemForPower2Denom(HRem *instruction);
void HandleGoto(HInstruction* got, HBasicBlock* successor);
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index deab239362..6d6d1a2aa9 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -48,7 +48,6 @@ using namespace vixl32; // NOLINT(build/namespaces)
using helpers::DRegisterFrom;
using helpers::DWARFReg;
-using helpers::HighDRegisterFrom;
using helpers::HighRegisterFrom;
using helpers::InputDRegisterAt;
using helpers::InputOperandAt;
@@ -7374,10 +7373,10 @@ HLoadClass::LoadKind CodeGeneratorARMVIXL::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadClass::LoadKind::kJitBootImageAddress:
case HLoadClass::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kRuntimeCall:
break;
}
@@ -7465,14 +7464,6 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_
codegen_->EmitMovwMovtPlaceholder(labels, out);
break;
}
- case HLoadClass::LoadKind::kBootImageAddress: {
- DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
- DCHECK_NE(address, 0u);
- __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address));
- break;
- }
case HLoadClass::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
@@ -7489,6 +7480,13 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_
generate_null_check = true;
break;
}
+ case HLoadClass::LoadKind::kJitBootImageAddress: {
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+ DCHECK_NE(address, 0u);
+ __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address));
+ break;
+ }
case HLoadClass::LoadKind::kJitTableAddress: {
__ Ldr(out, codegen_->DeduplicateJitClassLiteral(cls->GetDexFile(),
cls->GetTypeIndex(),
@@ -7649,10 +7647,10 @@ HLoadString::LoadKind CodeGeneratorARMVIXL::GetSupportedLoadStringKind(
case HLoadString::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadString::LoadKind::kJitBootImageAddress:
case HLoadString::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kRuntimeCall:
break;
}
@@ -7699,13 +7697,6 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadString(HLoadString* load) NO_THRE
codegen_->EmitMovwMovtPlaceholder(labels, out);
return;
}
- case HLoadString::LoadKind::kBootImageAddress: {
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(load->GetString().Get()));
- DCHECK_NE(address, 0u);
- __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address));
- return;
- }
case HLoadString::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
@@ -7729,6 +7720,12 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadString(HLoadString* load) NO_THRE
codegen_->MaybeGenerateMarkingRegisterCheck(/* code */ 16);
return;
}
+ case HLoadString::LoadKind::kJitBootImageAddress: {
+ uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+ DCHECK_NE(address, 0u);
+ __ Ldr(out, codegen_->DeduplicateBootImageAddressLiteral(address));
+ return;
+ }
case HLoadString::LoadKind::kJitTableAddress: {
__ Ldr(out, codegen_->DeduplicateJitStringLiteral(load->GetDexFile(),
load->GetStringIndex(),
@@ -9336,9 +9333,6 @@ void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
EmitMovwMovtPlaceholder(labels, temp_reg);
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
- __ Mov(RegisterFrom(temp), Operand::From(invoke->GetMethodAddress()));
- break;
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
uint32_t boot_image_offset = GetBootImageOffset(invoke);
PcRelativePatchInfo* labels = NewBootImageRelRoPatch(boot_image_offset);
@@ -9355,6 +9349,9 @@ void CodeGeneratorARMVIXL::GenerateStaticOrDirectCall(
GetAssembler()->LoadFromOffset(kLoadWord, temp_reg, temp_reg, /* offset*/ 0);
break;
}
+ case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+ __ Mov(RegisterFrom(temp), Operand::From(invoke->GetMethodAddress()));
+ break;
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
return; // No code pointer retrieval; the runtime performs the call directly.
@@ -9500,7 +9497,7 @@ vixl32::Label* CodeGeneratorARMVIXL::NewBakerReadBarrierPatch(uint32_t custom_da
}
VIXLUInt32Literal* CodeGeneratorARMVIXL::DeduplicateBootImageAddressLiteral(uint32_t address) {
- return DeduplicateUint32Literal(dchecked_integral_cast<uint32_t>(address), &uint32_literals_);
+ return DeduplicateUint32Literal(address, &uint32_literals_);
}
VIXLUInt32Literal* CodeGeneratorARMVIXL::DeduplicateJitStringLiteral(
@@ -9532,13 +9529,13 @@ void CodeGeneratorARMVIXL::LoadBootImageAddress(vixl32::Register reg,
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
NewBootImageIntrinsicPatch(boot_image_reference);
EmitMovwMovtPlaceholder(labels, reg);
- } else if (GetCompilerOptions().GetCompilePic()) {
- DCHECK(Runtime::Current()->IsAotCompiler());
+ } else if (Runtime::Current()->IsAotCompiler()) {
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
NewBootImageRelRoPatch(boot_image_reference);
EmitMovwMovtPlaceholder(labels, reg);
__ Ldr(reg, MemOperand(reg, /* offset */ 0));
} else {
+ DCHECK(Runtime::Current()->UseJitCompilation());
gc::Heap* heap = Runtime::Current()->GetHeap();
DCHECK(!heap->GetBootImageSpaces().empty());
uintptr_t address =
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index c7295e4db1..4aed2c091c 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1758,13 +1758,13 @@ void CodeGeneratorMIPS::LoadBootImageAddress(Register reg, uint32_t boot_image_r
PcRelativePatchInfo* info_low = NewBootImageIntrinsicPatch(boot_image_reference, info_high);
EmitPcRelativeAddressPlaceholderHigh(info_high, TMP, /* base */ ZERO);
__ Addiu(reg, TMP, /* placeholder */ 0x5678, &info_low->label);
- } else if (GetCompilerOptions().GetCompilePic()) {
- DCHECK(Runtime::Current()->IsAotCompiler());
+ } else if (Runtime::Current()->IsAotCompiler()) {
PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_reference);
PcRelativePatchInfo* info_low = NewBootImageRelRoPatch(boot_image_reference, info_high);
EmitPcRelativeAddressPlaceholderHigh(info_high, reg, /* base */ ZERO);
__ Lw(reg, reg, /* placeholder */ 0x5678, &info_low->label);
} else {
+ DCHECK(Runtime::Current()->UseJitCompilation());
gc::Heap* heap = Runtime::Current()->GetHeap();
DCHECK(!heap->GetBootImageSpaces().empty());
const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -7879,10 +7879,10 @@ HLoadString::LoadKind CodeGeneratorMIPS::GetSupportedLoadStringKind(
case HLoadString::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadString::LoadKind::kJitBootImageAddress:
case HLoadString::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kRuntimeCall:
break;
}
@@ -7902,10 +7902,10 @@ HLoadClass::LoadKind CodeGeneratorMIPS::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadClass::LoadKind::kJitBootImageAddress:
case HLoadClass::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kRuntimeCall:
break;
}
@@ -7982,9 +7982,6 @@ void CodeGeneratorMIPS::GenerateStaticOrDirectCall(
__ Addiu(temp_reg, TMP, /* placeholder */ 0x5678, &info_low->label);
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
- __ LoadConst32(temp.AsRegister<Register>(), invoke->GetMethodAddress());
- break;
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
uint32_t boot_image_offset = GetBootImageOffset(invoke);
PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_offset);
@@ -8004,6 +8001,9 @@ void CodeGeneratorMIPS::GenerateStaticOrDirectCall(
__ Lw(temp_reg, TMP, /* placeholder */ 0x5678, &info_low->label);
break;
}
+ case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+ __ LoadConst32(temp.AsRegister<Register>(), invoke->GetMethodAddress());
+ break;
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
return; // No code pointer retrieval; the runtime performs the call directly.
@@ -8114,14 +8114,14 @@ void LocationsBuilderMIPS::VisitLoadClass(HLoadClass* cls) {
switch (load_kind) {
// We need an extra register for PC-relative literals on R2.
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kBootImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kJitBootImageAddress:
if (isR6) {
break;
}
if (has_irreducible_loops) {
- if (load_kind != HLoadClass::LoadKind::kBootImageAddress) {
+ if (load_kind != HLoadClass::LoadKind::kJitBootImageAddress) {
codegen_->ClobberRA();
}
break;
@@ -8166,9 +8166,9 @@ void InstructionCodeGeneratorMIPS::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAF
switch (load_kind) {
// We need an extra register for PC-relative literals on R2.
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kBootImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kJitBootImageAddress:
base_or_current_method_reg =
(isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>();
break;
@@ -8210,20 +8210,6 @@ void InstructionCodeGeneratorMIPS::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAF
__ Addiu(out, out, /* placeholder */ 0x5678, &info_low->label);
break;
}
- case HLoadClass::LoadKind::kBootImageAddress: {
- DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
- DCHECK_NE(address, 0u);
- if (isR6 || !has_irreducible_loops) {
- __ LoadLiteral(out,
- base_or_current_method_reg,
- codegen_->DeduplicateBootImageAddressLiteral(address));
- } else {
- __ LoadConst32(out, address);
- }
- break;
- }
case HLoadClass::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
uint32_t boot_image_offset = codegen_->GetBootImageOffset(cls);
@@ -8254,6 +8240,19 @@ void InstructionCodeGeneratorMIPS::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAF
generate_null_check = true;
break;
}
+ case HLoadClass::LoadKind::kJitBootImageAddress: {
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+ DCHECK_NE(address, 0u);
+ if (isR6 || !has_irreducible_loops) {
+ __ LoadLiteral(out,
+ base_or_current_method_reg,
+ codegen_->DeduplicateBootImageAddressLiteral(address));
+ } else {
+ __ LoadConst32(out, address);
+ }
+ break;
+ }
case HLoadClass::LoadKind::kJitTableAddress: {
CodeGeneratorMIPS::JitPatchInfo* info = codegen_->NewJitRootClassPatch(cls->GetDexFile(),
cls->GetTypeIndex(),
@@ -8343,15 +8342,15 @@ void LocationsBuilderMIPS::VisitLoadString(HLoadString* load) {
const bool has_irreducible_loops = codegen_->GetGraph()->HasIrreducibleLoops();
switch (load_kind) {
// We need an extra register for PC-relative literals on R2.
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
case HLoadString::LoadKind::kBootImageRelRo:
case HLoadString::LoadKind::kBssEntry:
+ case HLoadString::LoadKind::kJitBootImageAddress:
if (isR6) {
break;
}
if (has_irreducible_loops) {
- if (load_kind != HLoadString::LoadKind::kBootImageAddress) {
+ if (load_kind != HLoadString::LoadKind::kJitBootImageAddress) {
codegen_->ClobberRA();
}
break;
@@ -8395,10 +8394,10 @@ void InstructionCodeGeneratorMIPS::VisitLoadString(HLoadString* load) NO_THREAD_
bool has_irreducible_loops = GetGraph()->HasIrreducibleLoops();
switch (load_kind) {
// We need an extra register for PC-relative literals on R2.
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
case HLoadString::LoadKind::kBootImageRelRo:
case HLoadString::LoadKind::kBssEntry:
+ case HLoadString::LoadKind::kJitBootImageAddress:
base_or_current_method_reg =
(isR6 || has_irreducible_loops) ? ZERO : locations->InAt(0).AsRegister<Register>();
break;
@@ -8420,19 +8419,6 @@ void InstructionCodeGeneratorMIPS::VisitLoadString(HLoadString* load) NO_THREAD_
__ Addiu(out, out, /* placeholder */ 0x5678, &info_low->label);
return;
}
- case HLoadString::LoadKind::kBootImageAddress: {
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(load->GetString().Get()));
- DCHECK_NE(address, 0u);
- if (isR6 || !has_irreducible_loops) {
- __ LoadLiteral(out,
- base_or_current_method_reg,
- codegen_->DeduplicateBootImageAddressLiteral(address));
- } else {
- __ LoadConst32(out, address);
- }
- return;
- }
case HLoadString::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
uint32_t boot_image_offset = codegen_->GetBootImageOffset(load);
@@ -8468,6 +8454,18 @@ void InstructionCodeGeneratorMIPS::VisitLoadString(HLoadString* load) NO_THREAD_
__ Bind(slow_path->GetExitLabel());
return;
}
+ case HLoadString::LoadKind::kJitBootImageAddress: {
+ uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+ DCHECK_NE(address, 0u);
+ if (isR6 || !has_irreducible_loops) {
+ __ LoadLiteral(out,
+ base_or_current_method_reg,
+ codegen_->DeduplicateBootImageAddressLiteral(address));
+ } else {
+ __ LoadConst32(out, address);
+ }
+ return;
+ }
case HLoadString::LoadKind::kJitTableAddress: {
CodeGeneratorMIPS::JitPatchInfo* info =
codegen_->NewJitRootStringPatch(load->GetDexFile(),
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index ffde45e95e..75169139cd 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -1657,14 +1657,14 @@ void CodeGeneratorMIPS64::LoadBootImageAddress(GpuRegister reg, uint32_t boot_im
PcRelativePatchInfo* info_low = NewBootImageIntrinsicPatch(boot_image_reference, info_high);
EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
__ Daddiu(reg, AT, /* placeholder */ 0x5678);
- } else if (GetCompilerOptions().GetCompilePic()) {
- DCHECK(Runtime::Current()->IsAotCompiler());
+ } else if (Runtime::Current()->IsAotCompiler()) {
PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_reference);
PcRelativePatchInfo* info_low = NewBootImageRelRoPatch(boot_image_reference, info_high);
EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
// Note: Boot image is in the low 4GiB and the entry is 32-bit, so emit a 32-bit load.
__ Lwu(reg, AT, /* placeholder */ 0x5678);
} else {
+ DCHECK(Runtime::Current()->UseJitCompilation());
gc::Heap* heap = Runtime::Current()->GetHeap();
DCHECK(!heap->GetBootImageSpaces().empty());
uintptr_t address =
@@ -5995,10 +5995,10 @@ HLoadString::LoadKind CodeGeneratorMIPS64::GetSupportedLoadStringKind(
case HLoadString::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadString::LoadKind::kJitBootImageAddress:
case HLoadString::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kRuntimeCall:
break;
}
@@ -6022,10 +6022,10 @@ HLoadClass::LoadKind CodeGeneratorMIPS64::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadClass::LoadKind::kJitBootImageAddress:
case HLoadClass::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kRuntimeCall:
break;
}
@@ -6073,11 +6073,6 @@ void CodeGeneratorMIPS64::GenerateStaticOrDirectCall(
__ Daddiu(temp.AsRegister<GpuRegister>(), AT, /* placeholder */ 0x5678);
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
- __ LoadLiteral(temp.AsRegister<GpuRegister>(),
- kLoadDoubleword,
- DeduplicateUint64Literal(invoke->GetMethodAddress()));
- break;
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
uint32_t boot_image_offset = GetBootImageOffset(invoke);
PcRelativePatchInfo* info_high = NewBootImageRelRoPatch(boot_image_offset);
@@ -6096,6 +6091,11 @@ void CodeGeneratorMIPS64::GenerateStaticOrDirectCall(
__ Ld(temp.AsRegister<GpuRegister>(), AT, /* placeholder */ 0x5678);
break;
}
+ case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+ __ LoadLiteral(temp.AsRegister<GpuRegister>(),
+ kLoadDoubleword,
+ DeduplicateUint64Literal(invoke->GetMethodAddress()));
+ break;
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
return; // No code pointer retrieval; the runtime performs the call directly.
@@ -6264,16 +6264,6 @@ void InstructionCodeGeneratorMIPS64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S
__ Daddiu(out, AT, /* placeholder */ 0x5678);
break;
}
- case HLoadClass::LoadKind::kBootImageAddress: {
- DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
- DCHECK_NE(address, 0u);
- __ LoadLiteral(out,
- kLoadUnsignedWord,
- codegen_->DeduplicateBootImageAddressLiteral(address));
- break;
- }
case HLoadClass::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
uint32_t boot_image_offset = codegen_->GetBootImageOffset(cls);
@@ -6300,6 +6290,15 @@ void InstructionCodeGeneratorMIPS64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S
generate_null_check = true;
break;
}
+ case HLoadClass::LoadKind::kJitBootImageAddress: {
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+ DCHECK_NE(address, 0u);
+ __ LoadLiteral(out,
+ kLoadUnsignedWord,
+ codegen_->DeduplicateBootImageAddressLiteral(address));
+ break;
+ }
case HLoadClass::LoadKind::kJitTableAddress:
__ LoadLiteral(out,
kLoadUnsignedWord,
@@ -6415,15 +6414,6 @@ void InstructionCodeGeneratorMIPS64::VisitLoadString(HLoadString* load) NO_THREA
__ Daddiu(out, AT, /* placeholder */ 0x5678);
return;
}
- case HLoadString::LoadKind::kBootImageAddress: {
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(load->GetString().Get()));
- DCHECK_NE(address, 0u);
- __ LoadLiteral(out,
- kLoadUnsignedWord,
- codegen_->DeduplicateBootImageAddressLiteral(address));
- return;
- }
case HLoadString::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
uint32_t boot_image_offset = codegen_->GetBootImageOffset(load);
@@ -6455,6 +6445,14 @@ void InstructionCodeGeneratorMIPS64::VisitLoadString(HLoadString* load) NO_THREA
__ Bind(slow_path->GetExitLabel());
return;
}
+ case HLoadString::LoadKind::kJitBootImageAddress: {
+ uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+ DCHECK_NE(address, 0u);
+ __ LoadLiteral(out,
+ kLoadUnsignedWord,
+ codegen_->DeduplicateBootImageAddressLiteral(address));
+ return;
+ }
case HLoadString::LoadKind::kJitTableAddress:
__ LoadLiteral(out,
kLoadUnsignedWord,
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 1c0d283ef6..30436eef9c 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4828,9 +4828,6 @@ void CodeGeneratorX86::GenerateStaticOrDirectCall(
RecordBootImageMethodPatch(invoke);
break;
}
- case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
- __ movl(temp.AsRegister<Register>(), Immediate(invoke->GetMethodAddress()));
- break;
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
temp.AsRegister<Register>());
@@ -4847,6 +4844,9 @@ void CodeGeneratorX86::GenerateStaticOrDirectCall(
RecordMethodBssEntryPatch(invoke);
break;
}
+ case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+ __ movl(temp.AsRegister<Register>(), Immediate(invoke->GetMethodAddress()));
+ break;
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
return; // No code pointer retrieval; the runtime performs the call directly.
@@ -4979,8 +4979,7 @@ void CodeGeneratorX86::LoadBootImageAddress(Register reg,
invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex()).AsRegister<Register>();
__ leal(reg, Address(method_address_reg, CodeGeneratorX86::kDummy32BitOffset));
RecordBootImageIntrinsicPatch(method_address, boot_image_reference);
- } else if (GetCompilerOptions().GetCompilePic()) {
- DCHECK(Runtime::Current()->IsAotCompiler());
+ } else if (Runtime::Current()->IsAotCompiler()) {
DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
HX86ComputeBaseMethodAddress* method_address =
invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
@@ -4990,6 +4989,7 @@ void CodeGeneratorX86::LoadBootImageAddress(Register reg,
__ movl(reg, Address(method_address_reg, CodeGeneratorX86::kDummy32BitOffset));
RecordBootImageRelRoPatch(method_address, boot_image_reference);
} else {
+ DCHECK(Runtime::Current()->UseJitCompilation());
gc::Heap* heap = Runtime::Current()->GetHeap();
DCHECK(!heap->GetBootImageSpaces().empty());
const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -6447,10 +6447,10 @@ HLoadClass::LoadKind CodeGeneratorX86::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadClass::LoadKind::kJitBootImageAddress:
case HLoadClass::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kRuntimeCall:
break;
}
@@ -6549,14 +6549,6 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE
codegen_->RecordBootImageTypePatch(cls);
break;
}
- case HLoadClass::LoadKind::kBootImageAddress: {
- DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
- DCHECK_NE(address, 0u);
- __ movl(out, Immediate(address));
- break;
- }
case HLoadClass::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
Register method_address = locations->InAt(0).AsRegister<Register>();
@@ -6573,6 +6565,13 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE
generate_null_check = true;
break;
}
+ case HLoadClass::LoadKind::kJitBootImageAddress: {
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+ DCHECK_NE(address, 0u);
+ __ movl(out, Immediate(address));
+ break;
+ }
case HLoadClass::LoadKind::kJitTableAddress: {
Address address = Address::Absolute(CodeGeneratorX86::kDummy32BitOffset);
Label* fixup_label = codegen_->NewJitRootClassPatch(
@@ -6686,10 +6685,10 @@ HLoadString::LoadKind CodeGeneratorX86::GetSupportedLoadStringKind(
case HLoadString::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadString::LoadKind::kJitBootImageAddress:
case HLoadString::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kRuntimeCall:
break;
}
@@ -6748,13 +6747,6 @@ void InstructionCodeGeneratorX86::VisitLoadString(HLoadString* load) NO_THREAD_S
codegen_->RecordBootImageStringPatch(load);
return;
}
- case HLoadString::LoadKind::kBootImageAddress: {
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(load->GetString().Get()));
- DCHECK_NE(address, 0u);
- __ movl(out, Immediate(address));
- return;
- }
case HLoadString::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
Register method_address = locations->InAt(0).AsRegister<Register>();
@@ -6776,6 +6768,12 @@ void InstructionCodeGeneratorX86::VisitLoadString(HLoadString* load) NO_THREAD_S
__ Bind(slow_path->GetExitLabel());
return;
}
+ case HLoadString::LoadKind::kJitBootImageAddress: {
+ uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+ DCHECK_NE(address, 0u);
+ __ movl(out, Immediate(address));
+ return;
+ }
case HLoadString::LoadKind::kJitTableAddress: {
Address address = Address::Absolute(CodeGeneratorX86::kDummy32BitOffset);
Label* fixup_label = codegen_->NewJitRootStringPatch(
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 3073be6ca7..0d7837e70f 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -996,9 +996,6 @@ void CodeGeneratorX86_64::GenerateStaticOrDirectCall(
Address::Absolute(kDummy32BitOffset, /* no_rip */ false));
RecordBootImageMethodPatch(invoke);
break;
- case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
- Load64BitValue(temp.AsRegister<CpuRegister>(), invoke->GetMethodAddress());
- break;
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo: {
// Note: Boot image is in the low 4GiB and the entry is 32-bit, so emit a 32-bit load.
__ movl(temp.AsRegister<CpuRegister>(),
@@ -1012,6 +1009,9 @@ void CodeGeneratorX86_64::GenerateStaticOrDirectCall(
RecordMethodBssEntryPatch(invoke);
break;
}
+ case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+ Load64BitValue(temp.AsRegister<CpuRegister>(), invoke->GetMethodAddress());
+ break;
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
GenerateInvokeStaticOrDirectRuntimeCall(invoke, temp, slow_path);
return; // No code pointer retrieval; the runtime performs the call directly.
@@ -1117,11 +1117,11 @@ void CodeGeneratorX86_64::LoadBootImageAddress(CpuRegister reg, uint32_t boot_im
if (GetCompilerOptions().IsBootImage()) {
__ leal(reg, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
RecordBootImageIntrinsicPatch(boot_image_reference);
- } else if (GetCompilerOptions().GetCompilePic()) {
- DCHECK(Runtime::Current()->IsAotCompiler());
+ } else if (Runtime::Current()->IsAotCompiler()) {
__ movl(reg, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
RecordBootImageRelRoPatch(boot_image_reference);
} else {
+ DCHECK(Runtime::Current()->UseJitCompilation());
gc::Heap* heap = Runtime::Current()->GetHeap();
DCHECK(!heap->GetBootImageSpaces().empty());
const uint8_t* address = heap->GetBootImageSpaces()[0]->Begin() + boot_image_reference;
@@ -5793,10 +5793,10 @@ HLoadClass::LoadKind CodeGeneratorX86_64::GetSupportedLoadClassKind(
case HLoadClass::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadClass::LoadKind::kJitBootImageAddress:
case HLoadClass::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kRuntimeCall:
break;
}
@@ -5889,14 +5889,6 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S
__ leal(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
codegen_->RecordBootImageTypePatch(cls);
break;
- case HLoadClass::LoadKind::kBootImageAddress: {
- DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(cls->GetClass().Get()));
- DCHECK_NE(address, 0u);
- __ movl(out, Immediate(static_cast<int32_t>(address))); // Zero-extended.
- break;
- }
case HLoadClass::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
__ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
@@ -5912,6 +5904,13 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S
generate_null_check = true;
break;
}
+ case HLoadClass::LoadKind::kJitBootImageAddress: {
+ DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
+ uint32_t address = reinterpret_cast32<uint32_t>(cls->GetClass().Get());
+ DCHECK_NE(address, 0u);
+ __ movl(out, Immediate(static_cast<int32_t>(address))); // Zero-extended.
+ break;
+ }
case HLoadClass::LoadKind::kJitTableAddress: {
Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
/* no_rip */ true);
@@ -5989,10 +5988,10 @@ HLoadString::LoadKind CodeGeneratorX86_64::GetSupportedLoadStringKind(
case HLoadString::LoadKind::kBssEntry:
DCHECK(!Runtime::Current()->UseJitCompilation());
break;
+ case HLoadString::LoadKind::kJitBootImageAddress:
case HLoadString::LoadKind::kJitTableAddress:
DCHECK(Runtime::Current()->UseJitCompilation());
break;
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kRuntimeCall:
break;
}
@@ -6044,13 +6043,6 @@ void InstructionCodeGeneratorX86_64::VisitLoadString(HLoadString* load) NO_THREA
codegen_->RecordBootImageStringPatch(load);
return;
}
- case HLoadString::LoadKind::kBootImageAddress: {
- uint32_t address = dchecked_integral_cast<uint32_t>(
- reinterpret_cast<uintptr_t>(load->GetString().Get()));
- DCHECK_NE(address, 0u);
- __ movl(out, Immediate(static_cast<int32_t>(address))); // Zero-extended.
- return;
- }
case HLoadString::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
__ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
@@ -6070,6 +6062,12 @@ void InstructionCodeGeneratorX86_64::VisitLoadString(HLoadString* load) NO_THREA
__ Bind(slow_path->GetExitLabel());
return;
}
+ case HLoadString::LoadKind::kJitBootImageAddress: {
+ uint32_t address = reinterpret_cast32<uint32_t>(load->GetString().Get());
+ DCHECK_NE(address, 0u);
+ __ movl(out, Immediate(static_cast<int32_t>(address))); // Zero-extended.
+ return;
+ }
case HLoadString::LoadKind::kJitTableAddress: {
Address address = Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset,
/* no_rip */ true);
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 771e066d2f..e555d0d890 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -854,7 +854,7 @@ ArtMethod* HInstructionBuilder::ResolveMethod(uint16_t method_idx, InvokeType in
// make this an invoke-unresolved to handle cross-dex invokes or abstract super methods, both of
// which require runtime handling.
if (invoke_type == kSuper) {
- ObjPtr<mirror::Class> compiling_class = GetCompilingClass();
+ ObjPtr<mirror::Class> compiling_class = ResolveCompilingClass(soa);
if (compiling_class == nullptr) {
// We could not determine the method's class we need to wait until runtime.
DCHECK(Runtime::Current()->IsAotCompiler());
@@ -973,8 +973,8 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
= HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit;
ScopedObjectAccess soa(Thread::Current());
if (invoke_type == kStatic) {
- clinit_check = ProcessClinitCheckForInvoke(
- dex_pc, resolved_method, &clinit_check_requirement);
+ clinit_check =
+ ProcessClinitCheckForInvoke(soa, dex_pc, resolved_method, &clinit_check_requirement);
} else if (invoke_type == kSuper) {
if (IsSameDexFile(*resolved_method->GetDexFile(), *dex_compilation_unit_->GetDexFile())) {
// Update the method index to the one resolved. Note that this may be a no-op if
@@ -1063,7 +1063,7 @@ HNewInstance* HInstructionBuilder::BuildNewInstance(dex::TypeIndex type_index, u
HInstruction* cls = load_class;
Handle<mirror::Class> klass = load_class->GetClass();
- if (!IsInitialized(klass)) {
+ if (!IsInitialized(soa, klass)) {
cls = new (allocator_) HClinitCheck(load_class, dex_pc);
AppendInstruction(cls);
}
@@ -1147,7 +1147,152 @@ void HInstructionBuilder::BuildConstructorFenceForAllocation(HInstruction* alloc
MethodCompilationStat::kConstructorFenceGeneratedNew);
}
-bool HInstructionBuilder::IsInitialized(Handle<mirror::Class> cls) const {
+static bool IsInBootImage(ObjPtr<mirror::Class> cls, const CompilerOptions& compiler_options)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (compiler_options.IsBootImage()) {
+ std::string temp;
+ const char* descriptor = cls->GetDescriptor(&temp);
+ return compiler_options.IsImageClass(descriptor);
+ } else {
+ return Runtime::Current()->GetHeap()->FindSpaceFromObject(cls, false)->IsImageSpace();
+ }
+}
+
+static bool IsSubClass(ObjPtr<mirror::Class> to_test, ObjPtr<mirror::Class> super_class)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return to_test != nullptr && !to_test->IsInterface() && to_test->IsSubClass(super_class);
+}
+
+static bool HasTrivialClinit(ObjPtr<mirror::Class> klass, PointerSize pointer_size)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ // Check if the class has encoded fields that trigger bytecode execution.
+ // (Encoded fields are just a different representation of <clinit>.)
+ if (klass->NumStaticFields() != 0u) {
+ DCHECK(klass->GetClassDef() != nullptr);
+ EncodedStaticFieldValueIterator it(klass->GetDexFile(), *klass->GetClassDef());
+ for (; it.HasNext(); it.Next()) {
+ switch (it.GetValueType()) {
+ case EncodedArrayValueIterator::ValueType::kBoolean:
+ case EncodedArrayValueIterator::ValueType::kByte:
+ case EncodedArrayValueIterator::ValueType::kShort:
+ case EncodedArrayValueIterator::ValueType::kChar:
+ case EncodedArrayValueIterator::ValueType::kInt:
+ case EncodedArrayValueIterator::ValueType::kLong:
+ case EncodedArrayValueIterator::ValueType::kFloat:
+ case EncodedArrayValueIterator::ValueType::kDouble:
+ case EncodedArrayValueIterator::ValueType::kNull:
+ case EncodedArrayValueIterator::ValueType::kString:
+ // Primitive, null or j.l.String initialization is permitted.
+ break;
+ case EncodedArrayValueIterator::ValueType::kType:
+ // Type initialization can load classes and execute bytecode through a class loader
+ // which can execute arbitrary bytecode. We do not optimize for known class loaders;
+ // kType is rarely used (if ever).
+ return false;
+ default:
+ // Other types in the encoded static field list are rejected by the DexFileVerifier.
+ LOG(FATAL) << "Unexpected type " << it.GetValueType();
+ UNREACHABLE();
+ }
+ }
+ }
+ // Check if the class has <clinit> that executes arbitrary code.
+ // Initialization of static fields of the class itself with constants is allowed.
+ ArtMethod* clinit = klass->FindClassInitializer(pointer_size);
+ if (clinit != nullptr) {
+ const DexFile& dex_file = *clinit->GetDexFile();
+ CodeItemInstructionAccessor accessor(dex_file, clinit->GetCodeItem());
+ for (DexInstructionPcPair it : accessor) {
+ switch (it->Opcode()) {
+ case Instruction::CONST_4:
+ case Instruction::CONST_16:
+ case Instruction::CONST:
+ case Instruction::CONST_HIGH16:
+ case Instruction::CONST_WIDE_16:
+ case Instruction::CONST_WIDE_32:
+ case Instruction::CONST_WIDE:
+ case Instruction::CONST_WIDE_HIGH16:
+ case Instruction::CONST_STRING:
+ case Instruction::CONST_STRING_JUMBO:
+ // Primitive, null or j.l.String initialization is permitted.
+ break;
+ case Instruction::RETURN_VOID:
+ case Instruction::RETURN_VOID_NO_BARRIER:
+ break;
+ case Instruction::SPUT:
+ case Instruction::SPUT_WIDE:
+ case Instruction::SPUT_OBJECT:
+ case Instruction::SPUT_BOOLEAN:
+ case Instruction::SPUT_BYTE:
+ case Instruction::SPUT_CHAR:
+ case Instruction::SPUT_SHORT:
+ // Only initialization of a static field of the same class is permitted.
+ if (dex_file.GetFieldId(it->VRegB_21c()).class_idx_ != klass->GetDexTypeIndex()) {
+ return false;
+ }
+ break;
+ case Instruction::NEW_ARRAY:
+ // Only primitive arrays are permitted.
+ if (Primitive::GetType(dex_file.GetTypeDescriptor(dex_file.GetTypeId(
+ dex::TypeIndex(it->VRegC_22c())))[1]) == Primitive::kPrimNot) {
+ return false;
+ }
+ break;
+ case Instruction::APUT:
+ case Instruction::APUT_WIDE:
+ case Instruction::APUT_BOOLEAN:
+ case Instruction::APUT_BYTE:
+ case Instruction::APUT_CHAR:
+ case Instruction::APUT_SHORT:
+ case Instruction::FILL_ARRAY_DATA:
+ case Instruction::NOP:
+ // Allow initialization of primitive arrays (only constants can be stored).
+ // Note: We expect NOPs used for fill-array-data-payload but accept all NOPs
+ // (even unreferenced switch payloads if they make it through the verifier).
+ break;
+ default:
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+static bool HasTrivialInitialization(ObjPtr<mirror::Class> cls,
+ const CompilerOptions& compiler_options)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ Runtime* runtime = Runtime::Current();
+ PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+
+ // Check the superclass chain.
+ for (ObjPtr<mirror::Class> klass = cls; klass != nullptr; klass = klass->GetSuperClass()) {
+ if (klass->IsInitialized() && IsInBootImage(klass, compiler_options)) {
+ break; // `klass` and its superclasses are already initialized in the boot image.
+ }
+ if (!HasTrivialClinit(klass, pointer_size)) {
+ return false;
+ }
+ }
+
+ // Also check interfaces with default methods as they need to be initialized as well.
+ ObjPtr<mirror::IfTable> iftable = cls->GetIfTable();
+ DCHECK(iftable != nullptr);
+ for (int32_t i = 0, count = iftable->Count(); i != count; ++i) {
+ ObjPtr<mirror::Class> iface = iftable->GetInterface(i);
+ if (!iface->HasDefaultMethods()) {
+ continue; // Initializing `cls` does not initialize this interface.
+ }
+ if (iface->IsInitialized() && IsInBootImage(iface, compiler_options)) {
+ continue; // This interface is already initialized in the boot image.
+ }
+ if (!HasTrivialClinit(iface, pointer_size)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool HInstructionBuilder::IsInitialized(ScopedObjectAccess& soa, Handle<mirror::Class> cls) const {
if (cls == nullptr) {
return false;
}
@@ -1162,48 +1307,77 @@ bool HInstructionBuilder::IsInitialized(Handle<mirror::Class> cls) const {
}
// Assume loaded only if klass is in the boot image. App classes cannot be assumed
// loaded because we don't even know what class loader will be used to load them.
- const CompilerOptions& compiler_options = compiler_driver_->GetCompilerOptions();
- if (compiler_options.IsBootImage()) {
- std::string temp;
- const char* descriptor = cls->GetDescriptor(&temp);
- if (compiler_options.IsImageClass(descriptor)) {
- return true;
- }
- } else {
- if (runtime->GetHeap()->FindSpaceFromObject(cls.Get(), false)->IsImageSpace()) {
- return true;
- }
+ if (IsInBootImage(cls.Get(), compiler_driver_->GetCompilerOptions())) {
+ return true;
}
}
- // We can avoid the class initialization check for `cls` only in static methods in the
+ // We can avoid the class initialization check for `cls` in static methods in the
// very same class. Instance methods of the same class can run on an escaped instance
// of an erroneous class. Even a superclass may need to be checked as the subclass
// can be completely initialized while the superclass is initializing and the subclass
// remains initialized when the superclass initializer throws afterwards. b/62478025
// Note: The HClinitCheck+HInvokeStaticOrDirect merging can still apply.
- if ((dex_compilation_unit_->GetAccessFlags() & kAccStatic) != 0u &&
- GetOutermostCompilingClass() == cls.Get()) {
+ ObjPtr<mirror::Class> outermost_cls = ResolveOutermostCompilingClass(soa);
+ bool is_static = (dex_compilation_unit_->GetAccessFlags() & kAccStatic) != 0u;
+ if (is_static && outermost_cls == cls.Get()) {
return true;
}
+ // Remember if the compiled class is a subclass of `cls`. By the time this is used
+ // below the `outermost_cls` may be invalidated by calling ResolveCompilingClass().
+ bool is_subclass = IsSubClass(outermost_cls, cls.Get());
+ if (dex_compilation_unit_ != outer_compilation_unit_) {
+ // Check also the innermost method. Though excessive copies of ClinitCheck can be
+ // eliminated by GVN, that happens only after the decision whether to inline the
+ // graph or not and that may depend on the presence of the ClinitCheck.
+ // TODO: We should walk over the entire inlined method chain, but we don't pass that
+ // information to the builder.
+ ObjPtr<mirror::Class> innermost_cls = ResolveCompilingClass(soa);
+ if (is_static && innermost_cls == cls.Get()) {
+ return true;
+ }
+ is_subclass = is_subclass || IsSubClass(innermost_cls, cls.Get());
+ }
- // Note: We could walk over the inlined methods to avoid allocating excessive
- // `HClinitCheck`s in inlined static methods but they shall be eliminated by GVN.
+ // Otherwise, we may be able to avoid the check if `cls` is a superclass of a method being
+ // compiled here (anywhere in the inlining chain) as the `cls` must have started initializing
+ // before calling any `cls` or subclass methods. Static methods require a clinit check and
+ // instance methods require an instance which cannot be created before doing a clinit check.
+ // When a subclass of `cls` starts initializing, it starts initializing its superclass
+ // chain up to `cls` without running any bytecode, i.e. without any opportunity for circular
+ // initialization weirdness.
+ //
+ // If the initialization of `cls` is trivial (`cls` and its superclasses and superinterfaces
+ // with default methods initialize only their own static fields using constant values), it must
+ // complete, either successfully or by throwing and marking `cls` erroneous, without allocating
+ // any instances of `cls` or subclasses (or any other class) and without calling any methods.
+ // If it completes by throwing, no instances of `cls` shall be created and no subclass method
+ // bytecode shall execute (see above), therefore the instruction we're building shall be
+ // unreachable. By reaching the instruction, we know that `cls` was initialized successfully.
+ //
+ // TODO: We should walk over the entire inlined methods chain, but we don't pass that
+ // information to the builder. (We could also check if we're guaranteed a non-null instance
+ // of `cls` at this location but that's outside the scope of the instruction builder.)
+ if (is_subclass && HasTrivialInitialization(cls.Get(), compiler_driver_->GetCompilerOptions())) {
+ return true;
+ }
return false;
}
HClinitCheck* HInstructionBuilder::ProcessClinitCheckForInvoke(
- uint32_t dex_pc,
- ArtMethod* resolved_method,
- HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) {
+ ScopedObjectAccess& soa,
+ uint32_t dex_pc,
+ ArtMethod* resolved_method,
+ HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement) {
Handle<mirror::Class> klass = handles_->NewHandle(resolved_method->GetDeclaringClass());
HClinitCheck* clinit_check = nullptr;
- if (IsInitialized(klass)) {
+ if (IsInitialized(soa, klass)) {
*clinit_check_requirement = HInvokeStaticOrDirect::ClinitCheckRequirement::kNone;
} else {
- HLoadClass* cls = BuildLoadClass(klass->GetDexTypeIndex(),
+ HLoadClass* cls = BuildLoadClass(soa,
+ klass->GetDexTypeIndex(),
klass->GetDexFile(),
klass,
dex_pc,
@@ -1438,21 +1612,23 @@ bool HInstructionBuilder::BuildInstanceFieldAccess(const Instruction& instructio
return true;
}
-static ObjPtr<mirror::Class> GetClassFrom(CompilerDriver* driver,
- const DexCompilationUnit& compilation_unit) {
- ScopedObjectAccess soa(Thread::Current());
+static ObjPtr<mirror::Class> ResolveClassFrom(ScopedObjectAccess& soa,
+ CompilerDriver* driver,
+ const DexCompilationUnit& compilation_unit)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
Handle<mirror::ClassLoader> class_loader = compilation_unit.GetClassLoader();
Handle<mirror::DexCache> dex_cache = compilation_unit.GetDexCache();
return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit);
}
-ObjPtr<mirror::Class> HInstructionBuilder::GetOutermostCompilingClass() const {
- return GetClassFrom(compiler_driver_, *outer_compilation_unit_);
+ObjPtr<mirror::Class> HInstructionBuilder::ResolveOutermostCompilingClass(
+ ScopedObjectAccess& soa) const {
+ return ResolveClassFrom(soa, compiler_driver_, *outer_compilation_unit_);
}
-ObjPtr<mirror::Class> HInstructionBuilder::GetCompilingClass() const {
- return GetClassFrom(compiler_driver_, *dex_compilation_unit_);
+ObjPtr<mirror::Class> HInstructionBuilder::ResolveCompilingClass(ScopedObjectAccess& soa) const {
+ return ResolveClassFrom(soa, compiler_driver_, *dex_compilation_unit_);
}
bool HInstructionBuilder::IsOutermostCompilingClass(dex::TypeIndex type_index) const {
@@ -1462,7 +1638,7 @@ bool HInstructionBuilder::IsOutermostCompilingClass(dex::TypeIndex type_index) c
Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader();
Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
soa, dex_cache, class_loader, type_index, dex_compilation_unit_)));
- Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
+ Handle<mirror::Class> outer_class(hs.NewHandle(ResolveOutermostCompilingClass(soa)));
// GetOutermostCompilingClass returns null when the class is unresolved
// (e.g. if it derives from an unresolved class). This is bogus knowing that
@@ -1496,7 +1672,7 @@ ArtField* HInstructionBuilder::ResolveField(uint16_t field_idx, bool is_static,
ClassLinker* class_linker = dex_compilation_unit_->GetClassLinker();
Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader();
- Handle<mirror::Class> compiling_class(hs.NewHandle(GetCompilingClass()));
+ Handle<mirror::Class> compiling_class(hs.NewHandle(ResolveCompilingClass(soa)));
ArtField* resolved_field = class_linker->ResolveField(field_idx,
dex_compilation_unit_->GetDexCache(),
@@ -1557,7 +1733,8 @@ void HInstructionBuilder::BuildStaticFieldAccess(const Instruction& instruction,
DataType::Type field_type = GetFieldAccessType(*dex_file_, field_index);
Handle<mirror::Class> klass = handles_->NewHandle(resolved_field->GetDeclaringClass());
- HLoadClass* constant = BuildLoadClass(klass->GetDexTypeIndex(),
+ HLoadClass* constant = BuildLoadClass(soa,
+ klass->GetDexTypeIndex(),
klass->GetDexFile(),
klass,
dex_pc,
@@ -1573,7 +1750,7 @@ void HInstructionBuilder::BuildStaticFieldAccess(const Instruction& instruction,
}
HInstruction* cls = constant;
- if (!IsInitialized(klass)) {
+ if (!IsInitialized(soa, klass)) {
cls = new (allocator_) HClinitCheck(constant, dex_pc);
AppendInstruction(cls);
}
@@ -1802,11 +1979,12 @@ HLoadClass* HInstructionBuilder::BuildLoadClass(dex::TypeIndex type_index, uint3
ScopedObjectAccess soa(Thread::Current());
const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
Handle<mirror::Class> klass = ResolveClass(soa, type_index);
- bool needs_access_check = LoadClassNeedsAccessCheck(klass);
- return BuildLoadClass(type_index, dex_file, klass, dex_pc, needs_access_check);
+ bool needs_access_check = LoadClassNeedsAccessCheck(soa, klass);
+ return BuildLoadClass(soa, type_index, dex_file, klass, dex_pc, needs_access_check);
}
-HLoadClass* HInstructionBuilder::BuildLoadClass(dex::TypeIndex type_index,
+HLoadClass* HInstructionBuilder::BuildLoadClass(ScopedObjectAccess& soa,
+ dex::TypeIndex type_index,
const DexFile& dex_file,
Handle<mirror::Class> klass,
uint32_t dex_pc,
@@ -1823,12 +2001,17 @@ HLoadClass* HInstructionBuilder::BuildLoadClass(dex::TypeIndex type_index,
}
// Note: `klass` must be from `handles_`.
+ bool is_referrers_class = false;
+ if (klass != nullptr) {
+ ObjPtr<mirror::Class> outermost_cls = ResolveOutermostCompilingClass(soa);
+ is_referrers_class = (outermost_cls == klass.Get());
+ }
HLoadClass* load_class = new (allocator_) HLoadClass(
graph_->GetCurrentMethod(),
type_index,
*actual_dex_file,
klass,
- klass != nullptr && (klass.Get() == GetOutermostCompilingClass()),
+ is_referrers_class,
dex_pc,
needs_access_check);
@@ -1856,13 +2039,14 @@ Handle<mirror::Class> HInstructionBuilder::ResolveClass(ScopedObjectAccess& soa,
return handles_->NewHandle(klass);
}
-bool HInstructionBuilder::LoadClassNeedsAccessCheck(Handle<mirror::Class> klass) {
+bool HInstructionBuilder::LoadClassNeedsAccessCheck(ScopedObjectAccess& soa,
+ Handle<mirror::Class> klass) {
if (klass == nullptr) {
return true;
} else if (klass->IsPublic()) {
return false;
} else {
- ObjPtr<mirror::Class> compiling_class = GetCompilingClass();
+ ObjPtr<mirror::Class> compiling_class = ResolveCompilingClass(soa);
return compiling_class == nullptr || !compiling_class->CanAccess(klass.Get());
}
}
@@ -1891,7 +2075,7 @@ void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction,
ScopedObjectAccess soa(Thread::Current());
const DexFile& dex_file = *dex_compilation_unit_->GetDexFile();
Handle<mirror::Class> klass = ResolveClass(soa, type_index);
- bool needs_access_check = LoadClassNeedsAccessCheck(klass);
+ bool needs_access_check = LoadClassNeedsAccessCheck(soa, klass);
TypeCheckKind check_kind = HSharpening::ComputeTypeCheckKind(
klass.Get(), code_generator_, needs_access_check);
@@ -1909,7 +2093,7 @@ void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction,
bitstring_path_to_root = graph_->GetIntConstant(static_cast<int32_t>(path_to_root), dex_pc);
bitstring_mask = graph_->GetIntConstant(static_cast<int32_t>(mask), dex_pc);
} else {
- class_or_null = BuildLoadClass(type_index, dex_file, klass, dex_pc, needs_access_check);
+ class_or_null = BuildLoadClass(soa, type_index, dex_file, klass, dex_pc, needs_access_check);
}
DCHECK(class_or_null != nullptr);
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index 578172a18e..af1b86ca6f 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -219,7 +219,8 @@ class HInstructionBuilder : public ValueObject {
// Builds a `HLoadClass` loading the given `type_index`.
HLoadClass* BuildLoadClass(dex::TypeIndex type_index, uint32_t dex_pc);
- HLoadClass* BuildLoadClass(dex::TypeIndex type_index,
+ HLoadClass* BuildLoadClass(ScopedObjectAccess& soa,
+ dex::TypeIndex type_index,
const DexFile& dex_file,
Handle<mirror::Class> klass,
uint32_t dex_pc,
@@ -229,7 +230,7 @@ class HInstructionBuilder : public ValueObject {
Handle<mirror::Class> ResolveClass(ScopedObjectAccess& soa, dex::TypeIndex type_index)
REQUIRES_SHARED(Locks::mutator_lock_);
- bool LoadClassNeedsAccessCheck(Handle<mirror::Class> klass)
+ bool LoadClassNeedsAccessCheck(ScopedObjectAccess& soa, Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
// Builds a `HLoadMethodHandle` loading the given `method_handle_index`.
@@ -239,10 +240,12 @@ class HInstructionBuilder : public ValueObject {
void BuildLoadMethodType(dex::ProtoIndex proto_index, uint32_t dex_pc);
// Returns the outer-most compiling method's class.
- ObjPtr<mirror::Class> GetOutermostCompilingClass() const;
+ ObjPtr<mirror::Class> ResolveOutermostCompilingClass(ScopedObjectAccess& soa) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the class whose method is being compiled.
- ObjPtr<mirror::Class> GetCompilingClass() const;
+ ObjPtr<mirror::Class> ResolveCompilingClass(ScopedObjectAccess& soa) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
// Returns whether `type_index` points to the outer-most compiling method's class.
bool IsOutermostCompilingClass(dex::TypeIndex type_index) const;
@@ -269,6 +272,7 @@ class HInstructionBuilder : public ValueObject {
void HandleStringInitResult(HInvokeStaticOrDirect* invoke);
HClinitCheck* ProcessClinitCheckForInvoke(
+ ScopedObjectAccess& soa,
uint32_t dex_pc,
ArtMethod* method,
HInvokeStaticOrDirect::ClinitCheckRequirement* clinit_check_requirement)
@@ -282,7 +286,8 @@ class HInstructionBuilder : public ValueObject {
void BuildConstructorFenceForAllocation(HInstruction* allocation);
// Return whether the compiler can assume `cls` is initialized.
- bool IsInitialized(Handle<mirror::Class> cls) const REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsInitialized(ScopedObjectAccess& soa, Handle<mirror::Class> cls) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
// Try to resolve a method using the class linker. Return null if a method could
// not be resolved.
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 70af49f8f0..f493b66cfd 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -2268,7 +2268,7 @@ void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction)
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
PointerSize image_size = class_linker->GetImagePointerSize();
HInvokeStaticOrDirect* invoke = instruction->AsInvokeStaticOrDirect();
- mirror::Class* system = invoke->GetResolvedMethod()->GetDeclaringClass();
+ ObjPtr<mirror::Class> system = invoke->GetResolvedMethod()->GetDeclaringClass();
ArtMethod* method = nullptr;
switch (source_component_type) {
case DataType::Type::kBool:
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index f11e5a1989..2963308da8 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -41,19 +41,15 @@ using helpers::HighRegisterFrom;
using helpers::InputDRegisterAt;
using helpers::InputRegisterAt;
using helpers::InputSRegisterAt;
-using helpers::InputVRegisterAt;
using helpers::Int32ConstantFrom;
using helpers::LocationFrom;
using helpers::LowRegisterFrom;
using helpers::LowSRegisterFrom;
using helpers::HighSRegisterFrom;
using helpers::OutputDRegister;
-using helpers::OutputSRegister;
using helpers::OutputRegister;
-using helpers::OutputVRegister;
using helpers::RegisterFrom;
using helpers::SRegisterFrom;
-using helpers::DRegisterFromS;
using namespace vixl::aarch32; // NOLINT(build/namespaces)
diff --git a/compiler/optimizing/loop_analysis.cc b/compiler/optimizing/loop_analysis.cc
index efb23e7d3e..d355cedb35 100644
--- a/compiler/optimizing/loop_analysis.cc
+++ b/compiler/optimizing/loop_analysis.cc
@@ -84,6 +84,8 @@ class ArchDefaultLoopHelper : public ArchNoOptsLoopHelper {
static constexpr uint32_t kScalarHeuristicMaxBodySizeInstr = 17;
// Loop's maximum basic block count. Loops with higher count will not be peeled/unrolled.
static constexpr uint32_t kScalarHeuristicMaxBodySizeBlocks = 6;
+ // Maximum number of instructions to be created as a result of full unrolling.
+ static constexpr uint32_t kScalarHeuristicFullyUnrolledMaxInstrThreshold = 35;
bool IsLoopNonBeneficialForScalarOpts(LoopAnalysisInfo* analysis_info) const OVERRIDE {
return analysis_info->HasLongTypeInstructions() ||
@@ -108,6 +110,14 @@ class ArchDefaultLoopHelper : public ArchNoOptsLoopHelper {
bool IsLoopPeelingEnabled() const OVERRIDE { return true; }
+ bool IsFullUnrollingBeneficial(LoopAnalysisInfo* analysis_info) const OVERRIDE {
+ int64_t trip_count = analysis_info->GetTripCount();
+ // We assume that trip count is known.
+ DCHECK_NE(trip_count, LoopAnalysisInfo::kUnknownTripCount);
+ size_t instr_num = analysis_info->GetNumberOfInstructions();
+ return (trip_count * instr_num < kScalarHeuristicFullyUnrolledMaxInstrThreshold);
+ }
+
protected:
bool IsLoopTooBig(LoopAnalysisInfo* loop_analysis_info,
size_t instr_threshold,
diff --git a/compiler/optimizing/loop_analysis.h b/compiler/optimizing/loop_analysis.h
index bcb7b70494..57509ee410 100644
--- a/compiler/optimizing/loop_analysis.h
+++ b/compiler/optimizing/loop_analysis.h
@@ -160,6 +160,13 @@ class ArchNoOptsLoopHelper : public ArenaObject<kArenaAllocOptimization> {
// Returns 'false' by default, should be overridden by particular target loop helper.
virtual bool IsLoopPeelingEnabled() const { return false; }
+ // Returns whether it is beneficial to fully unroll the loop.
+ //
+ // Returns 'false' by default, should be overridden by particular target loop helper.
+ virtual bool IsFullUnrollingBeneficial(LoopAnalysisInfo* analysis_info ATTRIBUTE_UNUSED) const {
+ return false;
+ }
+
// Returns optimal SIMD unrolling factor for the loop.
//
// Returns kNoUnrollingFactor by default, should be overridden by particular target loop helper.
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 440cd3351e..7d66155b39 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -422,6 +422,15 @@ static void TryToEvaluateIfCondition(HIf* instruction, HGraph* graph) {
}
}
+// Peel the first 'count' iterations of the loop.
+static void PeelByCount(HLoopInformation* loop_info, int count) {
+ for (int i = 0; i < count; i++) {
+ // Perform peeling.
+ PeelUnrollSimpleHelper helper(loop_info);
+ helper.DoPeeling();
+ }
+}
+
//
// Public methods.
//
@@ -811,6 +820,45 @@ bool HLoopOptimization::TryPeelingForLoopInvariantExitsElimination(LoopAnalysisI
return true;
}
+bool HLoopOptimization::TryFullUnrolling(LoopAnalysisInfo* analysis_info, bool generate_code) {
+ // Fully unroll loops with a known and small trip count.
+ int64_t trip_count = analysis_info->GetTripCount();
+ if (!arch_loop_helper_->IsLoopPeelingEnabled() ||
+ trip_count == LoopAnalysisInfo::kUnknownTripCount ||
+ !arch_loop_helper_->IsFullUnrollingBeneficial(analysis_info)) {
+ return false;
+ }
+
+ if (generate_code) {
+ // Peeling of the N first iterations (where N equals to the trip count) will effectively
+ // eliminate the loop: after peeling we will have N sequential iterations copied into the loop
+ // preheader and the original loop. The trip count of this loop will be 0 as the sequential
+ // iterations are executed first and there are exactly N of them. Thus we can statically
+ // evaluate the loop exit condition to 'false' and fully eliminate it.
+ //
+ // Here is an example of full unrolling of a loop with a trip count 2:
+ //
+ // loop_cond_1
+ // loop_body_1 <- First iteration.
+ // |
+ // \ v
+ // ==\ loop_cond_2
+ // ==/ loop_body_2 <- Second iteration.
+ // / |
+ // <- v <-
+ // loop_cond \ loop_cond \ <- This cond is always false.
+ // loop_body _/ loop_body _/
+ //
+ HLoopInformation* loop_info = analysis_info->GetLoopInfo();
+ PeelByCount(loop_info, trip_count);
+ HIf* loop_hif = loop_info->GetHeader()->GetLastInstruction()->AsIf();
+ int32_t constant = loop_info->Contains(*loop_hif->IfTrueSuccessor()) ? 0 : 1;
+ loop_hif->ReplaceInput(graph_->GetIntConstant(constant), 0u);
+ }
+
+ return true;
+}
+
bool HLoopOptimization::TryPeelingAndUnrolling(LoopNode* node) {
// Don't run peeling/unrolling if compiler_options_ is nullptr (i.e., running under tests)
// as InstructionSet is needed.
@@ -828,7 +876,8 @@ bool HLoopOptimization::TryPeelingAndUnrolling(LoopNode* node) {
return false;
}
- if (!TryPeelingForLoopInvariantExitsElimination(&analysis_info, /*generate_code*/ false) &&
+ if (!TryFullUnrolling(&analysis_info, /*generate_code*/ false) &&
+ !TryPeelingForLoopInvariantExitsElimination(&analysis_info, /*generate_code*/ false) &&
!TryUnrollingForBranchPenaltyReduction(&analysis_info, /*generate_code*/ false)) {
return false;
}
@@ -838,7 +887,8 @@ bool HLoopOptimization::TryPeelingAndUnrolling(LoopNode* node) {
return false;
}
- return TryPeelingForLoopInvariantExitsElimination(&analysis_info) ||
+ return TryFullUnrolling(&analysis_info) ||
+ TryPeelingForLoopInvariantExitsElimination(&analysis_info) ||
TryUnrollingForBranchPenaltyReduction(&analysis_info);
}
diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h
index bc4792458b..644b740ed4 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -155,6 +155,12 @@ class HLoopOptimization : public HOptimization {
bool TryPeelingForLoopInvariantExitsElimination(LoopAnalysisInfo* analysis_info,
bool generate_code = true);
+ // Tries to perform whole loop unrolling for a small loop with a small trip count to eliminate
+ // the loop check overhead and to have more opportunities for inter-iteration optimizations.
+ // Returns whether transformation happened. 'generate_code' determines whether the optimization
+ // should be actually applied.
+ bool TryFullUnrolling(LoopAnalysisInfo* analysis_info, bool generate_code = true);
+
// Tries to apply scalar loop peeling and unrolling.
bool TryPeelingAndUnrolling(LoopNode* node);
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 50ce7559f5..8f822cce5a 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2930,12 +2930,12 @@ std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind
return os << "Recursive";
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative:
return os << "BootImageLinkTimePcRelative";
- case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
- return os << "DirectAddress";
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageRelRo:
return os << "BootImageRelRo";
case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry:
return os << "BssEntry";
+ case HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress:
+ return os << "JitDirectAddress";
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall:
return os << "RuntimeCall";
default:
@@ -2967,8 +2967,8 @@ bool HLoadClass::InstructionDataEquals(const HInstruction* other) const {
return false;
}
switch (GetLoadKind()) {
- case LoadKind::kBootImageAddress:
case LoadKind::kBootImageRelRo:
+ case LoadKind::kJitBootImageAddress:
case LoadKind::kJitTableAddress: {
ScopedObjectAccess soa(Thread::Current());
return GetClass().Get() == other_load_class->GetClass().Get();
@@ -2985,12 +2985,12 @@ std::ostream& operator<<(std::ostream& os, HLoadClass::LoadKind rhs) {
return os << "ReferrersClass";
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
return os << "BootImageLinkTimePcRelative";
- case HLoadClass::LoadKind::kBootImageAddress:
- return os << "BootImageAddress";
case HLoadClass::LoadKind::kBootImageRelRo:
return os << "BootImageRelRo";
case HLoadClass::LoadKind::kBssEntry:
return os << "BssEntry";
+ case HLoadClass::LoadKind::kJitBootImageAddress:
+ return os << "JitBootImageAddress";
case HLoadClass::LoadKind::kJitTableAddress:
return os << "JitTableAddress";
case HLoadClass::LoadKind::kRuntimeCall:
@@ -3010,8 +3010,8 @@ bool HLoadString::InstructionDataEquals(const HInstruction* other) const {
return false;
}
switch (GetLoadKind()) {
- case LoadKind::kBootImageAddress:
case LoadKind::kBootImageRelRo:
+ case LoadKind::kJitBootImageAddress:
case LoadKind::kJitTableAddress: {
ScopedObjectAccess soa(Thread::Current());
return GetString().Get() == other_load_string->GetString().Get();
@@ -3025,12 +3025,12 @@ std::ostream& operator<<(std::ostream& os, HLoadString::LoadKind rhs) {
switch (rhs) {
case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
return os << "BootImageLinkTimePcRelative";
- case HLoadString::LoadKind::kBootImageAddress:
- return os << "BootImageAddress";
case HLoadString::LoadKind::kBootImageRelRo:
return os << "BootImageRelRo";
case HLoadString::LoadKind::kBssEntry:
return os << "BssEntry";
+ case HLoadString::LoadKind::kJitBootImageAddress:
+ return os << "JitBootImageAddress";
case HLoadString::LoadKind::kJitTableAddress:
return os << "JitTableAddress";
case HLoadString::LoadKind::kRuntimeCall:
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index cd8d07a17a..16a7417301 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4439,18 +4439,18 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
// Used for boot image methods referenced by boot image code.
kBootImageLinkTimePcRelative,
- // Use ArtMethod* at a known address, embed the direct address in the code.
- // Used for app->boot calls with non-relocatable image and for JIT-compiled calls.
- kDirectAddress,
-
// Load from an entry in the .data.bimg.rel.ro using a PC-relative load.
// Used for app->boot calls with relocatable image.
kBootImageRelRo,
// 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.
+ // Used for methods outside boot image referenced by AOT-compiled app and boot image code.
kBssEntry,
+ // Use ArtMethod* at a known address, embed the direct address in the code.
+ // Used for for JIT-compiled calls.
+ kJitDirectAddress,
+
// Make a runtime call to resolve and call the method. This is the last-resort-kind
// used when other kinds are unimplemented on a particular architecture.
kRuntimeCall,
@@ -4576,7 +4576,7 @@ class HInvokeStaticOrDirect FINAL : public HInvoke {
bool IsRecursive() const { return GetMethodLoadKind() == MethodLoadKind::kRecursive; }
bool NeedsDexCacheOfDeclaringClass() const OVERRIDE;
bool IsStringInit() const { return GetMethodLoadKind() == MethodLoadKind::kStringInit; }
- bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kDirectAddress; }
+ bool HasMethodAddress() const { return GetMethodLoadKind() == MethodLoadKind::kJitDirectAddress; }
bool HasPcRelativeMethodLoadKind() const {
return GetMethodLoadKind() == MethodLoadKind::kBootImageLinkTimePcRelative ||
GetMethodLoadKind() == MethodLoadKind::kBootImageRelRo ||
@@ -6155,18 +6155,18 @@ class HLoadClass FINAL : public HInstruction {
// Used for boot image classes referenced by boot image code.
kBootImageLinkTimePcRelative,
- // Use a known boot image Class* address, embedded in the code by the codegen.
- // Used for boot image classes referenced by apps in JIT- and AOT-compiled code (non-PIC).
- kBootImageAddress,
-
// Load from an entry in the .data.bimg.rel.ro using a PC-relative load.
- // Used for boot image classes referenced by apps in AOT-compiled code (PIC).
+ // Used for boot image classes referenced by apps in AOT-compiled code.
kBootImageRelRo,
// 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.
+ // Used for classes outside boot image referenced by AOT-compiled app and boot image code.
kBssEntry,
+ // Use a known boot image Class* address, embedded in the code by the codegen.
+ // Used for boot image classes referenced by apps in JIT-compiled code.
+ kJitBootImageAddress,
+
// Load from the root table associated with the JIT compiled method.
kJitTableAddress,
@@ -6248,8 +6248,6 @@ class HLoadClass FINAL : public HInstruction {
return NeedsAccessCheck() ||
MustGenerateClinitCheck() ||
// If the class is in the boot image, the lookup in the runtime call cannot throw.
- // This keeps CanThrow() consistent between non-PIC (using kBootImageAddress) and
- // PIC and subsequently avoids a DCE behavior dependency on the PIC option.
((GetLoadKind() == LoadKind::kRuntimeCall ||
GetLoadKind() == LoadKind::kBssEntry) &&
!IsInBootImage());
@@ -6366,9 +6364,9 @@ inline void HLoadClass::AddSpecialInput(HInstruction* special_input) {
// The special input is used for PC-relative loads on some architectures,
// including literal pool loads, which are PC-relative too.
DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
- GetLoadKind() == LoadKind::kBootImageAddress ||
GetLoadKind() == LoadKind::kBootImageRelRo ||
- GetLoadKind() == LoadKind::kBssEntry) << GetLoadKind();
+ GetLoadKind() == LoadKind::kBssEntry ||
+ GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
DCHECK(special_input_.GetInstruction() == nullptr);
special_input_ = HUserRecord<HInstruction*>(special_input);
special_input->AddUseAt(this, 0);
@@ -6382,18 +6380,18 @@ class HLoadString FINAL : public HInstruction {
// Used for boot image strings referenced by boot image code.
kBootImageLinkTimePcRelative,
- // Use a known boot image String* address, embedded in the code by the codegen.
- // Used for boot image strings referenced by apps in JIT- and AOT-compiled code (non-PIC).
- kBootImageAddress,
-
// Load from an entry in the .data.bimg.rel.ro using a PC-relative load.
- // Used for boot image strings referenced by apps in AOT-compiled code (PIC).
+ // Used for boot image strings referenced by apps in AOT-compiled code.
kBootImageRelRo,
// Load from an entry in the .bss section using a PC-relative load.
- // Used for strings outside boot image when .bss is accessible with a PC-relative load.
+ // Used for strings outside boot image referenced by AOT-compiled app and boot image code.
kBssEntry,
+ // Use a known boot image String* address, embedded in the code by the codegen.
+ // Used for boot image strings referenced by apps in JIT-compiled code.
+ kJitBootImageAddress,
+
// Load from the root table associated with the JIT compiled method.
kJitTableAddress,
@@ -6459,8 +6457,8 @@ class HLoadString FINAL : public HInstruction {
bool NeedsEnvironment() const OVERRIDE {
LoadKind load_kind = GetLoadKind();
if (load_kind == LoadKind::kBootImageLinkTimePcRelative ||
- load_kind == LoadKind::kBootImageAddress ||
load_kind == LoadKind::kBootImageRelRo ||
+ load_kind == LoadKind::kJitBootImageAddress ||
load_kind == LoadKind::kJitTableAddress) {
return false;
}
@@ -6533,9 +6531,9 @@ inline void HLoadString::AddSpecialInput(HInstruction* special_input) {
// The special input is used for PC-relative loads on some architectures,
// including literal pool loads, which are PC-relative too.
DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative ||
- GetLoadKind() == LoadKind::kBootImageAddress ||
GetLoadKind() == LoadKind::kBootImageRelRo ||
- GetLoadKind() == LoadKind::kBssEntry) << GetLoadKind();
+ GetLoadKind() == LoadKind::kBssEntry ||
+ GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind();
// HLoadString::GetInputRecords() returns an empty array at this point,
// so use the GetInputRecords() from the base class to set the input record.
DCHECK(special_input_.GetInstruction() == nullptr);
diff --git a/compiler/optimizing/optimizing_cfi_test.cc b/compiler/optimizing/optimizing_cfi_test.cc
index 1c1cf28294..04301f5366 100644
--- a/compiler/optimizing/optimizing_cfi_test.cc
+++ b/compiler/optimizing/optimizing_cfi_test.cc
@@ -34,8 +34,6 @@
namespace vixl32 = vixl::aarch32;
-using vixl32::r0;
-
namespace art {
// Run the tests only on host.
@@ -194,6 +192,7 @@ TEST_ISA(kMips64)
#ifdef ART_ENABLE_CODEGEN_arm
TEST_F(OptimizingCFITest, kThumb2Adjust) {
+ using vixl32::r0;
std::vector<uint8_t> expected_asm(
expected_asm_kThumb2_adjust,
expected_asm_kThumb2_adjust + arraysize(expected_asm_kThumb2_adjust));
diff --git a/compiler/optimizing/pc_relative_fixups_mips.cc b/compiler/optimizing/pc_relative_fixups_mips.cc
index f18ecc1458..a7e97a1ce5 100644
--- a/compiler/optimizing/pc_relative_fixups_mips.cc
+++ b/compiler/optimizing/pc_relative_fixups_mips.cc
@@ -74,9 +74,9 @@ class PCRelativeHandlerVisitor : public HGraphVisitor {
HLoadClass::LoadKind load_kind = load_class->GetLoadKind();
switch (load_kind) {
case HLoadClass::LoadKind::kBootImageLinkTimePcRelative:
- case HLoadClass::LoadKind::kBootImageAddress:
case HLoadClass::LoadKind::kBootImageRelRo:
case HLoadClass::LoadKind::kBssEntry:
+ case HLoadClass::LoadKind::kJitBootImageAddress:
// Add a base register for PC-relative literals on R2.
InitializePCRelativeBasePointer();
load_class->AddSpecialInput(base_);
@@ -90,9 +90,9 @@ class PCRelativeHandlerVisitor : public HGraphVisitor {
HLoadString::LoadKind load_kind = load_string->GetLoadKind();
switch (load_kind) {
case HLoadString::LoadKind::kBootImageLinkTimePcRelative:
- case HLoadString::LoadKind::kBootImageAddress:
case HLoadString::LoadKind::kBootImageRelRo:
case HLoadString::LoadKind::kBssEntry:
+ case HLoadString::LoadKind::kJitBootImageAddress:
// Add a base register for PC-relative literals on R2.
InitializePCRelativeBasePointer();
load_string->AddSpecialInput(base_);
diff --git a/compiler/optimizing/pc_relative_fixups_x86.cc b/compiler/optimizing/pc_relative_fixups_x86.cc
index 05ec765b19..41f2f776fc 100644
--- a/compiler/optimizing/pc_relative_fixups_x86.cc
+++ b/compiler/optimizing/pc_relative_fixups_x86.cc
@@ -17,6 +17,7 @@
#include "pc_relative_fixups_x86.h"
#include "code_generator_x86.h"
#include "intrinsics_x86.h"
+#include "runtime.h"
namespace art {
namespace x86 {
@@ -238,7 +239,7 @@ class PCRelativeHandlerVisitor : public HGraphVisitor {
case Intrinsics::kIntegerValueOf:
// This intrinsic can be call free if it loads the address of the boot image object.
// If we're compiling PIC, we need the address base for loading from .data.bimg.rel.ro.
- if (!codegen_->GetCompilerOptions().GetCompilePic()) {
+ if (Runtime::Current()->UseJitCompilation()) {
break;
}
FALLTHROUGH_INTENDED;
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index f3fe62561f..0d622484ee 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -563,7 +563,7 @@ void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* inst
ArtMethod* method = cl->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
dex_method_index, dex_cache, loader, /* referrer */ nullptr, kDirect);
DCHECK(method != nullptr);
- mirror::Class* declaring_class = method->GetDeclaringClass();
+ ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass();
DCHECK(declaring_class != nullptr);
DCHECK(declaring_class->IsStringClass())
<< "Expected String class: " << declaring_class->PrettyDescriptor();
@@ -572,7 +572,7 @@ void ReferenceTypePropagation::RTPVisitor::SetClassAsTypeInfo(HInstruction* inst
}
instr->SetReferenceTypeInfo(
ReferenceTypeInfo::Create(handle_cache_->GetStringClassHandle(), /* is_exact */ true));
- } else if (IsAdmissible(klass.Ptr())) {
+ } else if (IsAdmissible(klass)) {
ReferenceTypeInfo::TypeHandle handle = handle_cache_->NewHandle(klass);
is_exact = is_exact || handle->CannotBeAssignedFromOtherTypes();
instr->SetReferenceTypeInfo(ReferenceTypeInfo::Create(handle, is_exact));
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 27482ac5bf..5c2f57e314 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -63,10 +63,6 @@ static bool IsInBootImage(ArtMethod* method) {
return false;
}
-static bool AOTCanEmbedMethod(ArtMethod* method, const CompilerOptions& options) {
- return IsInBootImage(method) && !options.GetCompilePic();
-}
-
static bool BootImageAOTCanEmbedMethod(ArtMethod* method, const CompilerOptions& compiler_options) {
DCHECK(compiler_options.IsBootImage());
ScopedObjectAccess soa(Thread::Current());
@@ -120,11 +116,10 @@ void HSharpening::SharpenInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke,
method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kBssEntry;
}
code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
- } else if (Runtime::Current()->UseJitCompilation() ||
- AOTCanEmbedMethod(callee, compiler_options)) {
+ } else if (Runtime::Current()->UseJitCompilation()) {
// JIT or on-device AOT compilation referencing a boot image method.
// Use the method address directly.
- method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress;
+ method_load_kind = HInvokeStaticOrDirect::MethodLoadKind::kJitDirectAddress;
method_load_data = reinterpret_cast<uintptr_t>(callee);
code_ptr_location = HInvokeStaticOrDirect::CodePtrLocation::kCallArtMethod;
} else if (IsInBootImage(callee)) {
@@ -199,8 +194,7 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind(
if (runtime->UseJitCompilation()) {
DCHECK(!compiler_options.GetCompilePic());
if (is_in_boot_image) {
- // TODO: Use direct pointers for all non-moving spaces, not just boot image. Bug: 29530787
- desired_load_kind = HLoadClass::LoadKind::kBootImageAddress;
+ desired_load_kind = HLoadClass::LoadKind::kJitBootImageAddress;
} else if (klass != nullptr) {
desired_load_kind = HLoadClass::LoadKind::kJitTableAddress;
} else {
@@ -212,11 +206,7 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind(
}
} else if (is_in_boot_image) {
// AOT app compilation, boot image class.
- if (codegen->GetCompilerOptions().GetCompilePic()) {
- desired_load_kind = HLoadClass::LoadKind::kBootImageRelRo;
- } else {
- desired_load_kind = HLoadClass::LoadKind::kBootImageAddress;
- }
+ desired_load_kind = HLoadClass::LoadKind::kBootImageRelRo;
} else {
// Not JIT and the klass is not in boot image.
desired_load_kind = HLoadClass::LoadKind::kBssEntry;
@@ -348,7 +338,7 @@ void HSharpening::ProcessLoadString(
string = class_linker->LookupString(string_index, dex_cache.Get());
if (string != nullptr) {
if (runtime->GetHeap()->ObjectIsInBootImageSpace(string)) {
- desired_load_kind = HLoadString::LoadKind::kBootImageAddress;
+ desired_load_kind = HLoadString::LoadKind::kJitBootImageAddress;
} else {
desired_load_kind = HLoadString::LoadKind::kJitTableAddress;
}
@@ -359,11 +349,7 @@ void HSharpening::ProcessLoadString(
// AOT app compilation. Try to lookup the string without allocating if not found.
string = class_linker->LookupString(string_index, dex_cache.Get());
if (string != nullptr && runtime->GetHeap()->ObjectIsInBootImageSpace(string)) {
- if (codegen->GetCompilerOptions().GetCompilePic()) {
- desired_load_kind = HLoadString::LoadKind::kBootImageRelRo;
- } else {
- desired_load_kind = HLoadString::LoadKind::kBootImageAddress;
- }
+ desired_load_kind = HLoadString::LoadKind::kBootImageRelRo;
} else {
desired_load_kind = HLoadString::LoadKind::kBssEntry;
}
diff --git a/compiler/optimizing/stack_map_stream.cc b/compiler/optimizing/stack_map_stream.cc
index a65fbcc514..d74d7b695c 100644
--- a/compiler/optimizing/stack_map_stream.cc
+++ b/compiler/optimizing/stack_map_stream.cc
@@ -179,7 +179,7 @@ void StackMapStream::BeginInlineInfoEntry(ArtMethod* method,
ScopedObjectAccess soa(Thread::Current());
DCHECK(IsSameDexFile(*outer_dex_file, *method->GetDexFile()));
}
- uint32_t dex_method_index = method->GetDexMethodIndexUnchecked();
+ uint32_t dex_method_index = method->GetDexMethodIndex();
entry[InlineInfo::kMethodInfoIndex] = method_infos_.Dedup({dex_method_index});
}
current_inline_infos_.push_back(entry);
@@ -196,8 +196,7 @@ void StackMapStream::BeginInlineInfoEntry(ArtMethod* method,
if (encode_art_method) {
CHECK_EQ(inline_info.GetArtMethod(), method);
} else {
- CHECK_EQ(method_infos_[inline_info.GetMethodInfoIndex()][0],
- method->GetDexMethodIndexUnchecked());
+ CHECK_EQ(method_infos_[inline_info.GetMethodInfoIndex()][0], method->GetDexMethodIndex());
}
});
}