diff options
Diffstat (limited to 'compiler/optimizing')
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()); } }); } |