diff options
20 files changed, 586 insertions, 97 deletions
diff --git a/compiler/linker/linker_patch.h b/compiler/linker/linker_patch.h index 7fedf2e86e..4000fc2523 100644 --- a/compiler/linker/linker_patch.h +++ b/compiler/linker/linker_patch.h @@ -50,6 +50,8 @@ class LinkerPatch { kCallRelative, kTypeRelative, kTypeBssEntry, + kPublicTypeBssEntry, + kPackageTypeBssEntry, kStringRelative, kStringBssEntry, kCallEntrypoint, @@ -122,6 +124,26 @@ class LinkerPatch { return patch; } + static LinkerPatch PublicTypeBssEntryPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_type_idx) { + LinkerPatch patch(literal_offset, Type::kPublicTypeBssEntry, target_dex_file); + patch.type_idx_ = target_type_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + + static LinkerPatch PackageTypeBssEntryPatch(size_t literal_offset, + const DexFile* target_dex_file, + uint32_t pc_insn_offset, + uint32_t target_type_idx) { + LinkerPatch patch(literal_offset, Type::kPackageTypeBssEntry, target_dex_file); + patch.type_idx_ = target_type_idx; + patch.pc_insn_offset_ = pc_insn_offset; + return patch; + } + static LinkerPatch RelativeStringPatch(size_t literal_offset, const DexFile* target_dex_file, uint32_t pc_insn_offset, @@ -192,13 +214,17 @@ class LinkerPatch { const DexFile* TargetTypeDexFile() const { DCHECK(patch_type_ == Type::kTypeRelative || - patch_type_ == Type::kTypeBssEntry); + patch_type_ == Type::kTypeBssEntry || + patch_type_ == Type::kPublicTypeBssEntry || + patch_type_ == Type::kPackageTypeBssEntry); return target_dex_file_; } dex::TypeIndex TargetTypeIndex() const { DCHECK(patch_type_ == Type::kTypeRelative || - patch_type_ == Type::kTypeBssEntry); + patch_type_ == Type::kTypeBssEntry || + patch_type_ == Type::kPublicTypeBssEntry || + patch_type_ == Type::kPackageTypeBssEntry); return dex::TypeIndex(type_idx_); } @@ -221,6 +247,8 @@ class LinkerPatch { patch_type_ == Type::kMethodBssEntry || patch_type_ == Type::kTypeRelative || patch_type_ == Type::kTypeBssEntry || + patch_type_ == Type::kPublicTypeBssEntry || + patch_type_ == Type::kPackageTypeBssEntry || patch_type_ == Type::kStringRelative || patch_type_ == Type::kStringBssEntry); return pc_insn_offset_; diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 3ff83b4b81..a5d206064f 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -327,8 +327,13 @@ class LoadClassSlowPathARM64 : public SlowPathCodeARM64 { DCHECK(IsSameDexFile(cls_->GetDexFile(), arm64_codegen->GetGraph()->GetDexFile())); dex::TypeIndex type_index = cls_->GetTypeIndex(); __ Mov(calling_convention.GetRegisterAt(0).W(), type_index.index_); - arm64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this); - CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>(); + if (cls_->NeedsAccessCheck()) { + CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>(); + arm64_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this); + } else { + CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>(); + arm64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this); + } // If we also must_do_clinit, the resolved type is now in the correct register. } else { DCHECK(must_do_clinit); @@ -942,6 +947,8 @@ CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph, method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -4733,10 +4740,26 @@ vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageTypePatch( } vixl::aarch64::Label* CodeGeneratorARM64::NewBssEntryTypePatch( - const DexFile& dex_file, - dex::TypeIndex type_index, + HLoadClass* load_class, vixl::aarch64::Label* adrp_label) { - return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &type_bss_entry_patches_); + const DexFile& dex_file = load_class->GetDexFile(); + dex::TypeIndex type_index = load_class->GetTypeIndex(); + ArenaDeque<PcRelativePatchInfo>* patches = nullptr; + switch (load_class->GetLoadKind()) { + case HLoadClass::LoadKind::kBssEntry: + patches = &type_bss_entry_patches_; + break; + case HLoadClass::LoadKind::kBssEntryPublic: + patches = &public_type_bss_entry_patches_; + break; + case HLoadClass::LoadKind::kBssEntryPackage: + patches = &package_type_bss_entry_patches_; + break; + default: + LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind(); + UNREACHABLE(); + } + return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, patches); } vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageStringPatch( @@ -4916,6 +4939,8 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin method_bss_entry_patches_.size() + boot_image_type_patches_.size() + type_bss_entry_patches_.size() + + public_type_bss_entry_patches_.size() + + package_type_bss_entry_patches_.size() + boot_image_string_patches_.size() + string_bss_entry_patches_.size() + boot_image_other_patches_.size() + @@ -4945,6 +4970,10 @@ void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* lin method_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>( + public_type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>( + package_type_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( string_bss_entry_patches_, linker_patches); for (const PatchInfo<vixl::aarch64::Label>& info : call_entrypoint_patches_) { @@ -5063,6 +5092,8 @@ HLoadClass::LoadKind CodeGeneratorARM64::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: case HLoadClass::LoadKind::kBssEntry: + case HLoadClass::LoadKind::kBssEntryPublic: + case HLoadClass::LoadKind::kBssEntryPackage: DCHECK(!GetCompilerOptions().IsJitCompiler()); break; case HLoadClass::LoadKind::kJitBootImageAddress: @@ -5086,7 +5117,9 @@ void LocationsBuilderARM64::VisitLoadClass(HLoadClass* cls) { DCHECK(calling_convention.GetRegisterAt(0).Is(vixl::aarch64::x0)); return; } - DCHECK(!cls->NeedsAccessCheck()); + DCHECK_EQ(cls->NeedsAccessCheck(), + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage); const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage(); LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier) @@ -5120,7 +5153,9 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ __LINE__); return; } - DCHECK(!cls->NeedsAccessCheck()); + DCHECK_EQ(cls->NeedsAccessCheck(), + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage); Location out_loc = cls->GetLocations()->Out(); Register out = OutputRegister(cls); @@ -5170,16 +5205,15 @@ void InstructionCodeGeneratorARM64::VisitLoadClass(HLoadClass* cls) NO_THREAD_SA codegen_->EmitLdrOffsetPlaceholder(ldr_label, out.W(), out.X()); break; } - case HLoadClass::LoadKind::kBssEntry: { + case HLoadClass::LoadKind::kBssEntry: + case HLoadClass::LoadKind::kBssEntryPublic: + case HLoadClass::LoadKind::kBssEntryPackage: { // Add ADRP with its PC-relative Class .bss entry patch. - const DexFile& dex_file = cls->GetDexFile(); - dex::TypeIndex type_index = cls->GetTypeIndex(); vixl::aarch64::Register temp = XRegisterFrom(out_loc); - vixl::aarch64::Label* adrp_label = codegen_->NewBssEntryTypePatch(dex_file, type_index); + vixl::aarch64::Label* adrp_label = codegen_->NewBssEntryTypePatch(cls); codegen_->EmitAdrpPlaceholder(adrp_label, temp); // Add LDR with its PC-relative Class .bss entry patch. - vixl::aarch64::Label* ldr_label = - codegen_->NewBssEntryTypePatch(dex_file, type_index, adrp_label); + vixl::aarch64::Label* ldr_label = codegen_->NewBssEntryTypePatch(cls, adrp_label); // /* GcRoot<mirror::Class> */ out = *(base_address + offset) /* PC-relative */ // All aligned loads are implicitly atomic consume operations on ARM64. codegen_->GenerateGcRootFieldLoad(cls, diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index 04b2c549f4..447c0b501f 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -736,8 +736,7 @@ class CodeGeneratorARM64 : public CodeGenerator { // to be bound before the instruction. The instruction will be either the // ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing // to the associated ADRP patch label). - vixl::aarch64::Label* NewBssEntryTypePatch(const DexFile& dex_file, - dex::TypeIndex type_index, + vixl::aarch64::Label* NewBssEntryTypePatch(HLoadClass* load_class, vixl::aarch64::Label* adrp_label = nullptr); // Add a new boot image string patch for an instruction and return the label @@ -1048,6 +1047,10 @@ class CodeGeneratorARM64 : public CodeGenerator { ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_; + // PC-relative public type patch info for kBssEntryPublic. + ArenaDeque<PcRelativePatchInfo> public_type_bss_entry_patches_; + // PC-relative package type patch info for kBssEntryPackage. + ArenaDeque<PcRelativePatchInfo> package_type_bss_entry_patches_; // PC-relative String patch info for kBootImageLinkTimePcRelative. ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_; // PC-relative String patch info for kBssEntry. diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 9b1f5abeee..9aefdabdb4 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -530,8 +530,13 @@ class LoadClassSlowPathARMVIXL : public SlowPathCodeARMVIXL { DCHECK(IsSameDexFile(cls_->GetDexFile(), arm_codegen->GetGraph()->GetDexFile())); dex::TypeIndex type_index = cls_->GetTypeIndex(); __ Mov(calling_convention.GetRegisterAt(0), type_index.index_); - arm_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this); - CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>(); + if (cls_->NeedsAccessCheck()) { + CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>(); + arm_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this); + } else { + CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>(); + arm_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this); + } // If we also must_do_clinit, the resolved type is now in the correct register. } else { DCHECK(must_do_clinit); @@ -1863,6 +1868,8 @@ CodeGeneratorARMVIXL::CodeGeneratorARMVIXL(HGraph* graph, method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -7299,6 +7306,8 @@ HLoadClass::LoadKind CodeGeneratorARMVIXL::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: case HLoadClass::LoadKind::kBssEntry: + case HLoadClass::LoadKind::kBssEntryPublic: + case HLoadClass::LoadKind::kBssEntryPackage: DCHECK(!GetCompilerOptions().IsJitCompiler()); break; case HLoadClass::LoadKind::kJitBootImageAddress: @@ -7322,7 +7331,9 @@ void LocationsBuilderARMVIXL::VisitLoadClass(HLoadClass* cls) { DCHECK(calling_convention.GetRegisterAt(0).Is(r0)); return; } - DCHECK(!cls->NeedsAccessCheck()); + DCHECK_EQ(cls->NeedsAccessCheck(), + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage); const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage(); LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier) @@ -7356,7 +7367,9 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_ codegen_->MaybeGenerateMarkingRegisterCheck(/* code= */ 15); return; } - DCHECK(!cls->NeedsAccessCheck()); + DCHECK_EQ(cls->NeedsAccessCheck(), + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage); LocationSummary* locations = cls->GetLocations(); Location out_loc = locations->Out(); @@ -7396,9 +7409,10 @@ void InstructionCodeGeneratorARMVIXL::VisitLoadClass(HLoadClass* cls) NO_THREAD_ __ Ldr(out, MemOperand(out, /* offset= */ 0)); break; } - case HLoadClass::LoadKind::kBssEntry: { - CodeGeneratorARMVIXL::PcRelativePatchInfo* labels = - codegen_->NewTypeBssEntryPatch(cls->GetDexFile(), cls->GetTypeIndex()); + case HLoadClass::LoadKind::kBssEntry: + case HLoadClass::LoadKind::kBssEntryPublic: + case HLoadClass::LoadKind::kBssEntryPackage: { + CodeGeneratorARMVIXL::PcRelativePatchInfo* labels = codegen_->NewTypeBssEntryPatch(cls); codegen_->EmitMovwMovtPlaceholder(labels, out); // All aligned loads are implicitly atomic consume operations on ARM. codegen_->GenerateGcRootFieldLoad(cls, out_loc, out, /* offset= */ 0, read_barrier_option); @@ -9247,7 +9261,24 @@ CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageTyp } CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewTypeBssEntryPatch( - const DexFile& dex_file, dex::TypeIndex type_index) { + HLoadClass* load_class) { + const DexFile& dex_file = load_class->GetDexFile(); + dex::TypeIndex type_index = load_class->GetTypeIndex(); + ArenaDeque<PcRelativePatchInfo>* patches = nullptr; + switch (load_class->GetLoadKind()) { + case HLoadClass::LoadKind::kBssEntry: + patches = &type_bss_entry_patches_; + break; + case HLoadClass::LoadKind::kBssEntryPublic: + patches = &public_type_bss_entry_patches_; + break; + case HLoadClass::LoadKind::kBssEntryPackage: + patches = &package_type_bss_entry_patches_; + break; + default: + LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind(); + UNREACHABLE(); + } return NewPcRelativePatch(&dex_file, type_index.index_, &type_bss_entry_patches_); } @@ -9397,6 +9428,8 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l /* MOVW+MOVT for each entry */ 2u * method_bss_entry_patches_.size() + /* MOVW+MOVT for each entry */ 2u * boot_image_type_patches_.size() + /* MOVW+MOVT for each entry */ 2u * type_bss_entry_patches_.size() + + /* MOVW+MOVT for each entry */ 2u * public_type_bss_entry_patches_.size() + + /* MOVW+MOVT for each entry */ 2u * package_type_bss_entry_patches_.size() + /* MOVW+MOVT for each entry */ 2u * boot_image_string_patches_.size() + /* MOVW+MOVT for each entry */ 2u * string_bss_entry_patches_.size() + /* MOVW+MOVT for each entry */ 2u * boot_image_other_patches_.size() + @@ -9426,6 +9459,10 @@ void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* l method_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>( + public_type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>( + package_type_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( string_bss_entry_patches_, linker_patches); for (const PatchInfo<vixl32::Label>& info : call_entrypoint_patches_) { diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h index f9b7c0d291..0453d20cc6 100644 --- a/compiler/optimizing/code_generator_arm_vixl.h +++ b/compiler/optimizing/code_generator_arm_vixl.h @@ -615,7 +615,7 @@ class CodeGeneratorARMVIXL : public CodeGenerator { PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method); PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method); PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index); - PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file, dex::TypeIndex type_index); + PcRelativePatchInfo* NewTypeBssEntryPatch(HLoadClass* load_class); PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file, dex::StringIndex string_index); PcRelativePatchInfo* NewStringBssEntryPatch(const DexFile& dex_file, @@ -924,6 +924,10 @@ class CodeGeneratorARMVIXL : public CodeGenerator { ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_; + // PC-relative public type patch info for kBssEntryPublic. + ArenaDeque<PcRelativePatchInfo> public_type_bss_entry_patches_; + // PC-relative package type patch info for kBssEntryPackage. + ArenaDeque<PcRelativePatchInfo> package_type_bss_entry_patches_; // PC-relative String patch info for kBootImageLinkTimePcRelative. ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_; // PC-relative String patch info for kBssEntry. diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 303c35ec3b..86e6b959ed 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -291,8 +291,13 @@ class LoadClassSlowPathX86 : public SlowPathCode { DCHECK(IsSameDexFile(cls_->GetDexFile(), x86_codegen->GetGraph()->GetDexFile())); dex::TypeIndex type_index = cls_->GetTypeIndex(); __ movl(calling_convention.GetRegisterAt(0), Immediate(type_index.index_)); - x86_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this); - CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>(); + if (cls_->NeedsAccessCheck()) { + CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>(); + x86_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this); + } else { + CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>(); + x86_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this); + } // If we also must_do_clinit, the resolved type is now in the correct register. } else { DCHECK(must_do_clinit); @@ -1056,6 +1061,8 @@ CodeGeneratorX86::CodeGeneratorX86(HGraph* graph, method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -5362,9 +5369,24 @@ void CodeGeneratorX86::RecordBootImageTypePatch(HLoadClass* load_class) { Label* CodeGeneratorX86::NewTypeBssEntryPatch(HLoadClass* load_class) { HX86ComputeBaseMethodAddress* method_address = load_class->InputAt(0)->AsX86ComputeBaseMethodAddress(); - type_bss_entry_patches_.emplace_back( + ArenaDeque<X86PcRelativePatchInfo>* patches = nullptr; + switch (load_class->GetLoadKind()) { + case HLoadClass::LoadKind::kBssEntry: + patches = &type_bss_entry_patches_; + break; + case HLoadClass::LoadKind::kBssEntryPublic: + patches = &public_type_bss_entry_patches_; + break; + case HLoadClass::LoadKind::kBssEntryPackage: + patches = &package_type_bss_entry_patches_; + break; + default: + LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind(); + UNREACHABLE(); + } + patches->emplace_back( method_address, &load_class->GetDexFile(), load_class->GetTypeIndex().index_); - return &type_bss_entry_patches_.back().label; + return &patches->back().label; } void CodeGeneratorX86::RecordBootImageStringPatch(HLoadString* load_string) { @@ -5469,6 +5491,8 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke method_bss_entry_patches_.size() + boot_image_type_patches_.size() + type_bss_entry_patches_.size() + + public_type_bss_entry_patches_.size() + + package_type_bss_entry_patches_.size() + boot_image_string_patches_.size() + string_bss_entry_patches_.size() + boot_image_other_patches_.size(); @@ -5496,6 +5520,10 @@ void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linke method_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>( + public_type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>( + package_type_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( string_bss_entry_patches_, linker_patches); DCHECK_EQ(size, linker_patches->size()); @@ -6933,6 +6961,8 @@ HLoadClass::LoadKind CodeGeneratorX86::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: case HLoadClass::LoadKind::kBssEntry: + case HLoadClass::LoadKind::kBssEntryPublic: + case HLoadClass::LoadKind::kBssEntryPackage: DCHECK(!GetCompilerOptions().IsJitCompiler()); break; case HLoadClass::LoadKind::kJitBootImageAddress: @@ -6956,7 +6986,9 @@ void LocationsBuilderX86::VisitLoadClass(HLoadClass* cls) { DCHECK_EQ(calling_convention.GetRegisterAt(0), EAX); return; } - DCHECK(!cls->NeedsAccessCheck()); + DCHECK_EQ(cls->NeedsAccessCheck(), + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage); const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage(); LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier) @@ -6967,14 +6999,11 @@ void LocationsBuilderX86::VisitLoadClass(HLoadClass* cls) { locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers. } - if (load_kind == HLoadClass::LoadKind::kReferrersClass || - load_kind == HLoadClass::LoadKind::kBootImageLinkTimePcRelative || - load_kind == HLoadClass::LoadKind::kBootImageRelRo || - load_kind == HLoadClass::LoadKind::kBssEntry) { + if (load_kind == HLoadClass::LoadKind::kReferrersClass || cls->HasPcRelativeLoadKind()) { locations->SetInAt(0, Location::RequiresRegister()); } locations->SetOut(Location::RequiresRegister()); - if (load_kind == HLoadClass::LoadKind::kBssEntry) { + if (call_kind == LocationSummary::kCallOnSlowPath && cls->HasPcRelativeLoadKind()) { if (!kUseReadBarrier || kUseBakerReadBarrier) { // Rely on the type resolution and/or initialization to save everything. locations->SetCustomSlowPathCallerSaves(OneRegInReferenceOutSaveEverythingCallerSaves()); @@ -7002,7 +7031,9 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE codegen_->GenerateLoadClassRuntimeCall(cls); return; } - DCHECK(!cls->NeedsAccessCheck()); + DCHECK_EQ(cls->NeedsAccessCheck(), + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage); LocationSummary* locations = cls->GetLocations(); Location out_loc = locations->Out(); @@ -7043,7 +7074,9 @@ void InstructionCodeGeneratorX86::VisitLoadClass(HLoadClass* cls) NO_THREAD_SAFE codegen_->GetBootImageOffset(cls)); break; } - case HLoadClass::LoadKind::kBssEntry: { + case HLoadClass::LoadKind::kBssEntry: + case HLoadClass::LoadKind::kBssEntryPublic: + case HLoadClass::LoadKind::kBssEntryPackage: { Register method_address = locations->InAt(0).AsRegister<Register>(); Address address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset); Label* fixup_label = codegen_->NewTypeBssEntryPatch(cls); diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index a573e845a0..b0575ba969 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -715,6 +715,10 @@ class CodeGeneratorX86 : public CodeGenerator { ArenaDeque<X86PcRelativePatchInfo> boot_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<X86PcRelativePatchInfo> type_bss_entry_patches_; + // PC-relative public type patch info for kBssEntryPublic. + ArenaDeque<X86PcRelativePatchInfo> public_type_bss_entry_patches_; + // PC-relative package type patch info for kBssEntryPackage. + ArenaDeque<X86PcRelativePatchInfo> package_type_bss_entry_patches_; // PC-relative String patch info for kBootImageLinkTimePcRelative. ArenaDeque<X86PcRelativePatchInfo> boot_image_string_patches_; // PC-relative String patch info for kBssEntry. diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index f18fde054c..202b58b9ee 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -272,8 +272,13 @@ class LoadClassSlowPathX86_64 : public SlowPathCode { DCHECK(IsSameDexFile(cls_->GetDexFile(), x86_64_codegen->GetGraph()->GetDexFile())); dex::TypeIndex type_index = cls_->GetTypeIndex(); __ movl(CpuRegister(RAX), Immediate(type_index.index_)); - x86_64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this); - CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>(); + if (cls_->NeedsAccessCheck()) { + CheckEntrypointTypes<kQuickResolveTypeAndVerifyAccess, void*, uint32_t>(); + x86_64_codegen->InvokeRuntime(kQuickResolveTypeAndVerifyAccess, instruction_, dex_pc, this); + } else { + CheckEntrypointTypes<kQuickResolveType, void*, uint32_t>(); + x86_64_codegen->InvokeRuntime(kQuickResolveType, instruction_, dex_pc, this); + } // If we also must_do_clinit, the resolved type is now in the correct register. } else { DCHECK(must_do_clinit); @@ -1162,9 +1167,23 @@ void CodeGeneratorX86_64::RecordBootImageTypePatch(HLoadClass* load_class) { } Label* CodeGeneratorX86_64::NewTypeBssEntryPatch(HLoadClass* load_class) { - type_bss_entry_patches_.emplace_back( - &load_class->GetDexFile(), load_class->GetTypeIndex().index_); - return &type_bss_entry_patches_.back().label; + ArenaDeque<PatchInfo<Label>>* patches = nullptr; + switch (load_class->GetLoadKind()) { + case HLoadClass::LoadKind::kBssEntry: + patches = &type_bss_entry_patches_; + break; + case HLoadClass::LoadKind::kBssEntryPublic: + patches = &public_type_bss_entry_patches_; + break; + case HLoadClass::LoadKind::kBssEntryPackage: + patches = &package_type_bss_entry_patches_; + break; + default: + LOG(FATAL) << "Unexpected load kind: " << load_class->GetLoadKind(); + UNREACHABLE(); + } + patches->emplace_back(&load_class->GetDexFile(), load_class->GetTypeIndex().index_); + return &patches->back().label; } void CodeGeneratorX86_64::RecordBootImageStringPatch(HLoadString* load_string) { @@ -1249,6 +1268,8 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li method_bss_entry_patches_.size() + boot_image_type_patches_.size() + type_bss_entry_patches_.size() + + public_type_bss_entry_patches_.size() + + package_type_bss_entry_patches_.size() + boot_image_string_patches_.size() + string_bss_entry_patches_.size() + boot_image_other_patches_.size(); @@ -1276,6 +1297,10 @@ void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* li method_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeBssEntryPatch>( type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::PublicTypeBssEntryPatch>( + public_type_bss_entry_patches_, linker_patches); + EmitPcRelativeLinkerPatches<linker::LinkerPatch::PackageTypeBssEntryPatch>( + package_type_bss_entry_patches_, linker_patches); EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringBssEntryPatch>( string_bss_entry_patches_, linker_patches); DCHECK_EQ(size, linker_patches->size()); @@ -1370,6 +1395,8 @@ CodeGeneratorX86_64::CodeGeneratorX86_64(HGraph* graph, method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + public_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), + package_type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), boot_image_other_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)), @@ -6092,6 +6119,8 @@ HLoadClass::LoadKind CodeGeneratorX86_64::GetSupportedLoadClassKind( case HLoadClass::LoadKind::kBootImageLinkTimePcRelative: case HLoadClass::LoadKind::kBootImageRelRo: case HLoadClass::LoadKind::kBssEntry: + case HLoadClass::LoadKind::kBssEntryPublic: + case HLoadClass::LoadKind::kBssEntryPackage: DCHECK(!GetCompilerOptions().IsJitCompiler()); break; case HLoadClass::LoadKind::kJitBootImageAddress: @@ -6114,7 +6143,9 @@ void LocationsBuilderX86_64::VisitLoadClass(HLoadClass* cls) { Location::RegisterLocation(RAX)); return; } - DCHECK(!cls->NeedsAccessCheck()); + DCHECK_EQ(cls->NeedsAccessCheck(), + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage); const bool requires_read_barrier = kEmitCompilerReadBarrier && !cls->IsInBootImage(); LocationSummary::CallKind call_kind = (cls->NeedsEnvironment() || requires_read_barrier) @@ -6157,7 +6188,9 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S codegen_->GenerateLoadClassRuntimeCall(cls); return; } - DCHECK(!cls->NeedsAccessCheck()); + DCHECK_EQ(cls->NeedsAccessCheck(), + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage); LocationSummary* locations = cls->GetLocations(); Location out_loc = locations->Out(); @@ -6196,7 +6229,9 @@ void InstructionCodeGeneratorX86_64::VisitLoadClass(HLoadClass* cls) NO_THREAD_S codegen_->RecordBootImageRelRoPatch(codegen_->GetBootImageOffset(cls)); break; } - case HLoadClass::LoadKind::kBssEntry: { + case HLoadClass::LoadKind::kBssEntry: + case HLoadClass::LoadKind::kBssEntryPublic: + case HLoadClass::LoadKind::kBssEntryPackage: { Address address = Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false); Label* fixup_label = codegen_->NewTypeBssEntryPatch(cls); diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index dc18a249be..81988b4386 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -668,6 +668,10 @@ class CodeGeneratorX86_64 : public CodeGenerator { ArenaDeque<PatchInfo<Label>> boot_image_type_patches_; // PC-relative type patch info for kBssEntry. ArenaDeque<PatchInfo<Label>> type_bss_entry_patches_; + // PC-relative public type patch info for kBssEntryPublic. + ArenaDeque<PatchInfo<Label>> public_type_bss_entry_patches_; + // PC-relative package type patch info for kBssEntryPackage. + ArenaDeque<PatchInfo<Label>> package_type_bss_entry_patches_; // PC-relative String patch info for kBootImageLinkTimePcRelative. ArenaDeque<PatchInfo<Label>> boot_image_string_patches_; // PC-relative String patch info for kBssEntry. diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index d7a66f1400..b674937ee3 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -6391,6 +6391,21 @@ class HLoadClass final : public HInstruction { // Used for classes outside boot image referenced by AOT-compiled app and boot image code. kBssEntry, + // Load from an entry for public class in the .bss section using a PC-relative load. + // Used for classes that were unresolved during AOT-compilation outside the literal + // package of the compiling class. Such classes are accessible only if they are public + // and the .bss entry shall therefore be filled only if the resolved class is public. + kBssEntryPublic, + + // Load from an entry for package class in the .bss section using a PC-relative load. + // Used for classes that were unresolved during AOT-compilation but within the literal + // package of the compiling class. Such classes are accessible if they are public or + // in the same package which, given the literal package match, requires only matching + // defining class loader and the .bss entry shall therefore be filled only if at least + // one of those conditions holds. Note that all code in an oat file belongs to classes + // with the same defining class loader. + kBssEntryPackage, + // 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, @@ -6443,7 +6458,9 @@ class HLoadClass final : public HInstruction { bool HasPcRelativeLoadKind() const { return GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative || GetLoadKind() == LoadKind::kBootImageRelRo || - GetLoadKind() == LoadKind::kBssEntry; + GetLoadKind() == LoadKind::kBssEntry || + GetLoadKind() == LoadKind::kBssEntryPublic || + GetLoadKind() == LoadKind::kBssEntryPackage; } bool CanBeMoved() const override { return true; } @@ -6459,9 +6476,6 @@ class HLoadClass final : public HInstruction { } void SetMustGenerateClinitCheck(bool generate_clinit_check) { - // The entrypoint the code generator is going to call does not do - // clinit of the class. - DCHECK(!NeedsAccessCheck()); SetPackedFlag<kFlagGenerateClInitCheck>(generate_clinit_check); } @@ -6514,9 +6528,14 @@ class HLoadClass final : public HInstruction { bool MustResolveTypeOnSlowPath() const { // Check that this instruction has a slow path. - DCHECK(GetLoadKind() != LoadKind::kRuntimeCall); // kRuntimeCall calls on main path. - DCHECK(GetLoadKind() == LoadKind::kBssEntry || MustGenerateClinitCheck()); - return GetLoadKind() == LoadKind::kBssEntry; + LoadKind load_kind = GetLoadKind(); + DCHECK(load_kind != LoadKind::kRuntimeCall); // kRuntimeCall calls on main path. + bool must_resolve_type_on_slow_path = + load_kind == LoadKind::kBssEntry || + load_kind == LoadKind::kBssEntryPublic || + load_kind == LoadKind::kBssEntryPackage; + DCHECK(must_resolve_type_on_slow_path || MustGenerateClinitCheck()); + return must_resolve_type_on_slow_path; } void MarkInBootImage() { @@ -6558,6 +6577,8 @@ class HLoadClass final : public HInstruction { return load_kind == LoadKind::kReferrersClass || load_kind == LoadKind::kBootImageLinkTimePcRelative || load_kind == LoadKind::kBssEntry || + load_kind == LoadKind::kBssEntryPublic || + load_kind == LoadKind::kBssEntryPackage || load_kind == LoadKind::kRuntimeCall; } @@ -6565,14 +6586,14 @@ class HLoadClass final : public HInstruction { // The special input is the HCurrentMethod for kRuntimeCall or kReferrersClass. // For other load kinds it's empty or possibly some architecture-specific instruction - // for PC-relative loads, i.e. kBssEntry or kBootImageLinkTimePcRelative. + // for PC-relative loads, i.e. kBssEntry* or kBootImageLinkTimePcRelative. HUserRecord<HInstruction*> special_input_; // A type index and dex file where the class can be accessed. The dex file can be: // - The compiling method's dex file if the class is defined there too. // - The compiling method's dex file if the class is referenced there. // - The dex file where the class is defined. When the load kind can only be - // kBssEntry or kRuntimeCall, we cannot emit code for this `HLoadClass`. + // kBssEntry* or kRuntimeCall, we cannot emit code for this `HLoadClass`. const dex::TypeIndex type_index_; const DexFile& dex_file_; @@ -6601,6 +6622,8 @@ inline void HLoadClass::AddSpecialInput(HInstruction* special_input) { DCHECK(GetLoadKind() == LoadKind::kBootImageLinkTimePcRelative || GetLoadKind() == LoadKind::kBootImageRelRo || GetLoadKind() == LoadKind::kBssEntry || + GetLoadKind() == LoadKind::kBssEntryPublic || + GetLoadKind() == LoadKind::kBssEntryPackage || GetLoadKind() == LoadKind::kJitBootImageAddress) << GetLoadKind(); DCHECK(special_input_.GetInstruction() == nullptr); special_input_ = HUserRecord<HInstruction*>(special_input); diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc index 8c4615d8c2..d5edc3da36 100644 --- a/compiler/optimizing/prepare_for_register_allocation.cc +++ b/compiler/optimizing/prepare_for_register_allocation.cc @@ -166,7 +166,6 @@ void PrepareForRegisterAllocation::VisitClinitCheck(HClinitCheck* check) { } } else if (can_merge_with_load_class && load_class->GetLoadKind() != HLoadClass::LoadKind::kRuntimeCall) { - DCHECK(!load_class->NeedsAccessCheck()); // Pass the initialization duty to the `HLoadClass` instruction, // and remove the instruction from the graph. DCHECK(load_class->HasEnvironment()); diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc index 393369dcb6..f570c60843 100644 --- a/compiler/optimizing/sharpening.cc +++ b/compiler/optimizing/sharpening.cc @@ -158,24 +158,55 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind( load_class->GetLoadKind() == HLoadClass::LoadKind::kReferrersClass) << load_class->GetLoadKind(); DCHECK(!load_class->IsInBootImage()) << "HLoadClass should not be optimized before sharpening."; + const DexFile& dex_file = load_class->GetDexFile(); + dex::TypeIndex type_index = load_class->GetTypeIndex(); + const CompilerOptions& compiler_options = codegen->GetCompilerOptions(); - HLoadClass::LoadKind load_kind = load_class->GetLoadKind(); + bool is_in_boot_image = false; + HLoadClass::LoadKind desired_load_kind = HLoadClass::LoadKind::kInvalid; - if (load_class->NeedsAccessCheck()) { - // We need to call the runtime anyway, so we simply get the class as that call's return value. - } else if (load_kind == HLoadClass::LoadKind::kReferrersClass) { + if (load_class->GetLoadKind() == HLoadClass::LoadKind::kReferrersClass) { + DCHECK(!load_class->NeedsAccessCheck()); // Loading from the ArtMethod* is the most efficient retrieval in code size. // TODO: This may not actually be true for all architectures and // locations of target classes. The additional register pressure // for using the ArtMethod* should be considered. + desired_load_kind = HLoadClass::LoadKind::kReferrersClass; + } else if (load_class->NeedsAccessCheck()) { + DCHECK_EQ(load_class->GetLoadKind(), HLoadClass::LoadKind::kRuntimeCall); + if (klass != nullptr) { + // Resolved class that needs access check must be really inaccessible + // and the access check is bound to fail. Just emit the runtime call. + desired_load_kind = HLoadClass::LoadKind::kRuntimeCall; + } else if (compiler_options.IsJitCompiler()) { + // Unresolved class while JITting means that either we never hit this + // instruction or it failed. Either way, just emit the runtime call. + // (Though we could consider emitting Deoptimize instead and + // recompile if the instruction succeeds in interpreter.) + desired_load_kind = HLoadClass::LoadKind::kRuntimeCall; + } else { + // For AOT, check if the class is in the same literal package as the + // compiling class and pick an appropriate .bss entry. + auto package_length = [](const char* descriptor) { + const char* slash_pos = strrchr(descriptor, '/'); + return (slash_pos != nullptr) ? static_cast<size_t>(slash_pos - descriptor) : 0u; + }; + const char* klass_descriptor = dex_file.StringByTypeIdx(type_index); + const uint32_t klass_package_length = package_length(klass_descriptor); + const DexFile* referrer_dex_file = dex_compilation_unit.GetDexFile(); + const dex::TypeIndex referrer_type_index = + referrer_dex_file->GetClassDef(dex_compilation_unit.GetClassDefIndex()).class_idx_; + const char* referrer_descriptor = referrer_dex_file->StringByTypeIdx(referrer_type_index); + const uint32_t referrer_package_length = package_length(referrer_descriptor); + bool same_package = + (referrer_package_length == klass_package_length) && + memcmp(referrer_descriptor, klass_descriptor, referrer_package_length) == 0; + desired_load_kind = same_package + ? HLoadClass::LoadKind::kBssEntryPackage + : HLoadClass::LoadKind::kBssEntryPublic; + } } else { - const DexFile& dex_file = load_class->GetDexFile(); - dex::TypeIndex type_index = load_class->GetTypeIndex(); - - bool is_in_boot_image = false; - HLoadClass::LoadKind desired_load_kind = HLoadClass::LoadKind::kInvalid; Runtime* runtime = Runtime::Current(); - const CompilerOptions& compiler_options = codegen->GetCompilerOptions(); if (compiler_options.IsBootImage() || compiler_options.IsBootImageExtension()) { // Compiling boot image or boot image extension. Check if the class is a boot image class. DCHECK(!compiler_options.IsJitCompiler()); @@ -227,17 +258,19 @@ HLoadClass::LoadKind HSharpening::ComputeLoadClassKind( desired_load_kind = HLoadClass::LoadKind::kBssEntry; } } - DCHECK_NE(desired_load_kind, HLoadClass::LoadKind::kInvalid); + } + DCHECK_NE(desired_load_kind, HLoadClass::LoadKind::kInvalid); - if (is_in_boot_image) { - load_class->MarkInBootImage(); - } - load_kind = codegen->GetSupportedLoadClassKind(desired_load_kind); + if (is_in_boot_image) { + load_class->MarkInBootImage(); } + HLoadClass::LoadKind load_kind = codegen->GetSupportedLoadClassKind(desired_load_kind); if (!IsSameDexFile(load_class->GetDexFile(), *dex_compilation_unit.GetDexFile())) { - if ((load_kind == HLoadClass::LoadKind::kRuntimeCall) || - (load_kind == HLoadClass::LoadKind::kBssEntry)) { + if (load_kind == HLoadClass::LoadKind::kRuntimeCall || + load_kind == HLoadClass::LoadKind::kBssEntry || + load_kind == HLoadClass::LoadKind::kBssEntryPublic || + load_kind == HLoadClass::LoadKind::kBssEntryPackage) { // We actually cannot reference this class, we're forced to bail. // We cannot reference this class with Bss, as the entrypoint will lookup the class // in the caller's dex file, but that dex file does not reference the class. diff --git a/dex2oat/linker/arm64/relative_patcher_arm64.cc b/dex2oat/linker/arm64/relative_patcher_arm64.cc index 2260f66d1f..494391bd45 100644 --- a/dex2oat/linker/arm64/relative_patcher_arm64.cc +++ b/dex2oat/linker/arm64/relative_patcher_arm64.cc @@ -67,6 +67,8 @@ inline bool IsAdrpPatch(const LinkerPatch& patch) { case LinkerPatch::Type::kMethodBssEntry: case LinkerPatch::Type::kTypeRelative: case LinkerPatch::Type::kTypeBssEntry: + case LinkerPatch::Type::kPublicTypeBssEntry: + case LinkerPatch::Type::kPackageTypeBssEntry: case LinkerPatch::Type::kStringRelative: case LinkerPatch::Type::kStringBssEntry: return patch.LiteralOffset() == patch.PcInsnOffset(); @@ -261,6 +263,8 @@ void Arm64RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code, patch.GetType() == LinkerPatch::Type::kTypeRelative || patch.GetType() == LinkerPatch::Type::kStringRelative || patch.GetType() == LinkerPatch::Type::kTypeBssEntry || + patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry || + patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry || patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType(); } shift = 0u; // No shift for ADD. @@ -269,6 +273,8 @@ void Arm64RelativePatcher::PatchPcRelativeReference(std::vector<uint8_t>* code, DCHECK(patch.GetType() == LinkerPatch::Type::kDataBimgRelRo || patch.GetType() == LinkerPatch::Type::kMethodBssEntry || patch.GetType() == LinkerPatch::Type::kTypeBssEntry || + patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry || + patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry || patch.GetType() == LinkerPatch::Type::kStringBssEntry) << patch.GetType(); DCHECK_EQ(insn & 0xbfbffc00, 0xb9000000) << std::hex << insn; } diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index a49b7d4f0d..73ad9e9682 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -351,6 +351,8 @@ class OatWriter::OatDexFile { uint32_t class_offsets_offset_; uint32_t method_bss_mapping_offset_; uint32_t type_bss_mapping_offset_; + uint32_t public_type_bss_mapping_offset_; + uint32_t package_type_bss_mapping_offset_; uint32_t string_bss_mapping_offset_; // Offset of dex sections that will have different runtime madvise states. @@ -412,6 +414,8 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options, bss_method_entry_references_(), bss_method_entries_(), bss_type_entries_(), + bss_public_type_entries_(), + bss_package_type_entries_(), bss_string_entries_(), oat_data_offset_(0u), oat_header_(nullptr), @@ -456,6 +460,8 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options, size_oat_dex_file_dex_layout_sections_alignment_(0), size_oat_dex_file_method_bss_mapping_offset_(0), size_oat_dex_file_type_bss_mapping_offset_(0), + size_oat_dex_file_public_type_bss_mapping_offset_(0), + size_oat_dex_file_package_type_bss_mapping_offset_(0), size_oat_dex_file_string_bss_mapping_offset_(0), size_oat_lookup_table_alignment_(0), size_oat_lookup_table_(0), @@ -467,6 +473,8 @@ OatWriter::OatWriter(const CompilerOptions& compiler_options, size_oat_class_method_offsets_(0), size_method_bss_mappings_(0u), size_type_bss_mappings_(0u), + size_public_type_bss_mappings_(0u), + size_package_type_bss_mappings_(0u), size_string_bss_mappings_(0u), relative_patcher_(nullptr), profile_compilation_info_(info), @@ -917,6 +925,18 @@ class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor { target_type.dex_file->NumTypeIds(), &writer_->bss_type_entry_references_); writer_->bss_type_entries_.Overwrite(target_type, /* placeholder */ 0u); + } else if (patch.GetType() == LinkerPatch::Type::kPublicTypeBssEntry) { + TypeReference target_type(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); + AddBssReference(target_type, + target_type.dex_file->NumTypeIds(), + &writer_->bss_public_type_entry_references_); + writer_->bss_public_type_entries_.Overwrite(target_type, /* placeholder */ 0u); + } else if (patch.GetType() == LinkerPatch::Type::kPackageTypeBssEntry) { + TypeReference target_type(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); + AddBssReference(target_type, + target_type.dex_file->NumTypeIds(), + &writer_->bss_package_type_entry_references_); + writer_->bss_package_type_entries_.Overwrite(target_type, /* placeholder */ 0u); } else if (patch.GetType() == LinkerPatch::Type::kStringBssEntry) { StringReference target_string(patch.TargetStringDexFile(), patch.TargetStringIndex()); AddBssReference(target_string, @@ -1839,6 +1859,26 @@ class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor { target_offset); break; } + case LinkerPatch::Type::kPublicTypeBssEntry: { + TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); + uint32_t target_offset = + writer_->bss_start_ + writer_->bss_public_type_entries_.Get(ref); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } + case LinkerPatch::Type::kPackageTypeBssEntry: { + TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); + uint32_t target_offset = + writer_->bss_start_ + writer_->bss_package_type_entries_.Get(ref); + writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, + patch, + offset_ + literal_offset, + target_offset); + break; + } case LinkerPatch::Type::kMethodRelative: { uint32_t target_offset = GetTargetMethodOffset(GetTargetMethod(patch)); writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, @@ -2125,9 +2165,22 @@ static size_t CalculateIndexBssMappingSize(size_t number_of_indexes, return IndexBssMapping::ComputeSize(number_of_entries); } +static size_t CalculateIndexBssMappingSize( + const DexFile* dex_file, + const BitVector& type_indexes, + const SafeMap<TypeReference, size_t, TypeReferenceValueComparator>& bss_entries) { + return CalculateIndexBssMappingSize( + dex_file->NumTypeIds(), + sizeof(GcRoot<mirror::Class>), + type_indexes, + [=](uint32_t index) { return bss_entries.Get({dex_file, dex::TypeIndex(index)}); }); +} + size_t OatWriter::InitIndexBssMappings(size_t offset) { if (bss_method_entry_references_.empty() && bss_type_entry_references_.empty() && + bss_public_type_entry_references_.empty() && + bss_package_type_entry_references_.empty() && bss_string_entry_references_.empty()) { return offset; } @@ -2138,6 +2191,8 @@ size_t OatWriter::InitIndexBssMappings(size_t offset) { size_t number_of_method_dex_files = 0u; size_t number_of_type_dex_files = 0u; + size_t number_of_public_type_dex_files = 0u; + size_t number_of_package_type_dex_files = 0u; size_t number_of_string_dex_files = 0u; PointerSize pointer_size = GetInstructionSetPointerSize(oat_header_->GetInstructionSet()); for (size_t i = 0, size = dex_files_->size(); i != size; ++i) { @@ -2161,13 +2216,23 @@ size_t OatWriter::InitIndexBssMappings(size_t offset) { const BitVector& type_indexes = type_it->second; ++number_of_type_dex_files; oat_dex_files_[i].type_bss_mapping_offset_ = offset; - offset += CalculateIndexBssMappingSize( - dex_file->NumTypeIds(), - sizeof(GcRoot<mirror::Class>), - type_indexes, - [=](uint32_t index) { - return bss_type_entries_.Get({dex_file, dex::TypeIndex(index)}); - }); + offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_type_entries_); + } + + auto public_type_it = bss_public_type_entry_references_.find(dex_file); + if (public_type_it != bss_public_type_entry_references_.end()) { + const BitVector& type_indexes = public_type_it->second; + ++number_of_public_type_dex_files; + oat_dex_files_[i].public_type_bss_mapping_offset_ = offset; + offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_public_type_entries_); + } + + auto package_type_it = bss_package_type_entry_references_.find(dex_file); + if (package_type_it != bss_package_type_entry_references_.end()) { + const BitVector& type_indexes = package_type_it->second; + ++number_of_package_type_dex_files; + oat_dex_files_[i].package_type_bss_mapping_offset_ = offset; + offset += CalculateIndexBssMappingSize(dex_file, type_indexes, bss_package_type_entries_); } auto string_it = bss_string_entry_references_.find(dex_file); @@ -2187,6 +2252,8 @@ size_t OatWriter::InitIndexBssMappings(size_t offset) { // Check that all dex files targeted by bss entries are in `*dex_files_`. CHECK_EQ(number_of_method_dex_files, bss_method_entry_references_.size()); CHECK_EQ(number_of_type_dex_files, bss_type_entry_references_.size()); + CHECK_EQ(number_of_public_type_dex_files, bss_public_type_entry_references_.size()); + CHECK_EQ(number_of_package_type_dex_files, bss_package_type_entry_references_.size()); CHECK_EQ(number_of_string_dex_files, bss_string_entry_references_.size()); return offset; } @@ -2338,6 +2405,8 @@ void OatWriter::InitBssLayout(InstructionSet instruction_set) { DCHECK_EQ(bss_size_, 0u); if (bss_method_entries_.empty() && bss_type_entries_.empty() && + bss_public_type_entries_.empty() && + bss_package_type_entries_.empty() && bss_string_entries_.empty()) { // Nothing to put to the .bss section. return; @@ -2361,6 +2430,18 @@ void OatWriter::InitBssLayout(InstructionSet instruction_set) { entry.second = bss_size_; bss_size_ += sizeof(GcRoot<mirror::Class>); } + // Prepare offsets for .bss public Class entries. + for (auto& entry : bss_public_type_entries_) { + DCHECK_EQ(entry.second, 0u); + entry.second = bss_size_; + bss_size_ += sizeof(GcRoot<mirror::Class>); + } + // Prepare offsets for .bss package Class entries. + for (auto& entry : bss_package_type_entries_) { + DCHECK_EQ(entry.second, 0u); + entry.second = bss_size_; + bss_size_ += sizeof(GcRoot<mirror::Class>); + } // Prepare offsets for .bss String entries. for (auto& entry : bss_string_entries_) { DCHECK_EQ(entry.second, 0u); @@ -2738,6 +2819,8 @@ bool OatWriter::CheckOatSize(OutputStream* out, size_t file_offset, size_t relat DO_STAT(size_oat_dex_file_dex_layout_sections_alignment_); DO_STAT(size_oat_dex_file_method_bss_mapping_offset_); DO_STAT(size_oat_dex_file_type_bss_mapping_offset_); + DO_STAT(size_oat_dex_file_public_type_bss_mapping_offset_); + DO_STAT(size_oat_dex_file_package_type_bss_mapping_offset_); DO_STAT(size_oat_dex_file_string_bss_mapping_offset_); DO_STAT(size_oat_lookup_table_alignment_); DO_STAT(size_oat_lookup_table_); @@ -2749,6 +2832,8 @@ bool OatWriter::CheckOatSize(OutputStream* out, size_t file_offset, size_t relat DO_STAT(size_oat_class_method_offsets_); DO_STAT(size_method_bss_mappings_); DO_STAT(size_type_bss_mappings_); + DO_STAT(size_public_type_bss_mappings_); + DO_STAT(size_package_type_bss_mappings_); DO_STAT(size_string_bss_mappings_); #undef DO_STAT @@ -2914,12 +2999,27 @@ size_t WriteIndexBssMapping(OutputStream* out, return mappings_size; } +size_t WriteIndexBssMapping( + OutputStream* out, + const DexFile* dex_file, + const BitVector& type_indexes, + const SafeMap<TypeReference, size_t, TypeReferenceValueComparator>& bss_entries) { + return WriteIndexBssMapping( + out, + dex_file->NumTypeIds(), + sizeof(GcRoot<mirror::Class>), + type_indexes, + [=](uint32_t index) { return bss_entries.Get({dex_file, dex::TypeIndex(index)}); }); +} + size_t OatWriter::WriteIndexBssMappings(OutputStream* out, size_t file_offset, size_t relative_offset) { TimingLogger::ScopedTiming split("WriteMethodBssMappings", timings_); if (bss_method_entry_references_.empty() && bss_type_entry_references_.empty() && + bss_public_type_entry_references_.empty() && + bss_package_type_entry_references_.empty() && bss_string_entry_references_.empty()) { return relative_offset; } @@ -2960,14 +3060,8 @@ size_t OatWriter::WriteIndexBssMappings(OutputStream* out, const BitVector& type_indexes = type_it->second; DCHECK_EQ(relative_offset, oat_dex_file->type_bss_mapping_offset_); DCHECK_OFFSET(); - size_t type_mappings_size = WriteIndexBssMapping( - out, - dex_file->NumTypeIds(), - sizeof(GcRoot<mirror::Class>), - type_indexes, - [=](uint32_t index) { - return bss_type_entries_.Get({dex_file, dex::TypeIndex(index)}); - }); + size_t type_mappings_size = + WriteIndexBssMapping(out, dex_file, type_indexes, bss_type_entries_); if (type_mappings_size == 0u) { return 0u; } @@ -2977,6 +3071,38 @@ size_t OatWriter::WriteIndexBssMappings(OutputStream* out, DCHECK_EQ(0u, oat_dex_file->type_bss_mapping_offset_); } + auto public_type_it = bss_public_type_entry_references_.find(dex_file); + if (public_type_it != bss_public_type_entry_references_.end()) { + const BitVector& type_indexes = public_type_it->second; + DCHECK_EQ(relative_offset, oat_dex_file->public_type_bss_mapping_offset_); + DCHECK_OFFSET(); + size_t public_type_mappings_size = + WriteIndexBssMapping(out, dex_file, type_indexes, bss_public_type_entries_); + if (public_type_mappings_size == 0u) { + return 0u; + } + size_public_type_bss_mappings_ += public_type_mappings_size; + relative_offset += public_type_mappings_size; + } else { + DCHECK_EQ(0u, oat_dex_file->public_type_bss_mapping_offset_); + } + + auto package_type_it = bss_package_type_entry_references_.find(dex_file); + if (package_type_it != bss_package_type_entry_references_.end()) { + const BitVector& type_indexes = package_type_it->second; + DCHECK_EQ(relative_offset, oat_dex_file->package_type_bss_mapping_offset_); + DCHECK_OFFSET(); + size_t package_type_mappings_size = + WriteIndexBssMapping(out, dex_file, type_indexes, bss_package_type_entries_); + if (package_type_mappings_size == 0u) { + return 0u; + } + size_package_type_bss_mappings_ += package_type_mappings_size; + relative_offset += package_type_mappings_size; + } else { + DCHECK_EQ(0u, oat_dex_file->package_type_bss_mapping_offset_); + } + auto string_it = bss_string_entry_references_.find(dex_file); if (string_it != bss_string_entry_references_.end()) { const BitVector& string_indexes = string_it->second; @@ -3918,6 +4044,8 @@ OatWriter::OatDexFile::OatDexFile(const char* dex_file_location, class_offsets_offset_(0u), method_bss_mapping_offset_(0u), type_bss_mapping_offset_(0u), + public_type_bss_mapping_offset_(0u), + package_type_bss_mapping_offset_(0u), string_bss_mapping_offset_(0u), dex_sections_layout_offset_(0u), class_offsets_() { @@ -3932,6 +4060,8 @@ size_t OatWriter::OatDexFile::SizeOf() const { + sizeof(lookup_table_offset_) + sizeof(method_bss_mapping_offset_) + sizeof(type_bss_mapping_offset_) + + sizeof(public_type_bss_mapping_offset_) + + sizeof(package_type_bss_mapping_offset_) + sizeof(string_bss_mapping_offset_) + sizeof(dex_sections_layout_offset_); } @@ -3994,6 +4124,21 @@ bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream* out) cons } oat_writer->size_oat_dex_file_type_bss_mapping_offset_ += sizeof(type_bss_mapping_offset_); + if (!out->WriteFully(&public_type_bss_mapping_offset_, sizeof(public_type_bss_mapping_offset_))) { + PLOG(ERROR) << "Failed to write public type bss mapping offset to " << out->GetLocation(); + return false; + } + oat_writer->size_oat_dex_file_public_type_bss_mapping_offset_ += + sizeof(public_type_bss_mapping_offset_); + + if (!out->WriteFully(&package_type_bss_mapping_offset_, + sizeof(package_type_bss_mapping_offset_))) { + PLOG(ERROR) << "Failed to write package type bss mapping offset to " << out->GetLocation(); + return false; + } + oat_writer->size_oat_dex_file_package_type_bss_mapping_offset_ += + sizeof(package_type_bss_mapping_offset_); + if (!out->WriteFully(&string_bss_mapping_offset_, sizeof(string_bss_mapping_offset_))) { PLOG(ERROR) << "Failed to write string bss mapping offset to " << out->GetLocation(); return false; diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h index 8d4f574bb3..2fd75719f4 100644 --- a/dex2oat/linker/oat_writer.h +++ b/dex2oat/linker/oat_writer.h @@ -441,6 +441,12 @@ class OatWriter { // Map for recording references to GcRoot<mirror::Class> entries in .bss. SafeMap<const DexFile*, BitVector> bss_type_entry_references_; + // Map for recording references to public GcRoot<mirror::Class> entries in .bss. + SafeMap<const DexFile*, BitVector> bss_public_type_entry_references_; + + // Map for recording references to package GcRoot<mirror::Class> entries in .bss. + SafeMap<const DexFile*, BitVector> bss_package_type_entry_references_; + // Map for recording references to GcRoot<mirror::String> entries in .bss. SafeMap<const DexFile*, BitVector> bss_string_entry_references_; @@ -454,6 +460,16 @@ class OatWriter { // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`. SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_type_entries_; + // Map for allocating public Class entries in .bss. Indexed by TypeReference for the source + // type in the dex file with the "type value comparator" for deduplication. The value + // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`. + SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_public_type_entries_; + + // Map for allocating package Class entries in .bss. Indexed by TypeReference for the source + // type in the dex file with the "type value comparator" for deduplication. The value + // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`. + SafeMap<TypeReference, size_t, TypeReferenceValueComparator> bss_package_type_entries_; + // Map for allocating String entries in .bss. Indexed by StringReference for the source // string in the dex file with the "string value comparator" for deduplication. The value // is the target offset for patching, starting at `bss_start_ + bss_roots_offset_`. @@ -519,6 +535,8 @@ class OatWriter { uint32_t size_oat_dex_file_dex_layout_sections_alignment_; uint32_t size_oat_dex_file_method_bss_mapping_offset_; uint32_t size_oat_dex_file_type_bss_mapping_offset_; + uint32_t size_oat_dex_file_public_type_bss_mapping_offset_; + uint32_t size_oat_dex_file_package_type_bss_mapping_offset_; uint32_t size_oat_dex_file_string_bss_mapping_offset_; uint32_t size_oat_lookup_table_alignment_; uint32_t size_oat_lookup_table_; @@ -530,6 +548,8 @@ class OatWriter { uint32_t size_oat_class_method_offsets_; uint32_t size_method_bss_mappings_; uint32_t size_type_bss_mappings_; + uint32_t size_public_type_bss_mappings_; + uint32_t size_package_type_bss_mappings_; uint32_t size_string_bss_mappings_; // The helper for processing relative patches is external so that we can patch across oat files. diff --git a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc index 838b5b5083..c576640e8f 100644 --- a/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_dexcache_entrypoints.cc @@ -85,12 +85,22 @@ static inline void StoreTypeInBss(ArtMethod* outer_method, DCHECK(dex_file != nullptr); const OatDexFile* oat_dex_file = dex_file->GetOatDexFile(); if (oat_dex_file != nullptr) { - size_t bss_offset = IndexBssMappingLookup::GetBssOffset(oat_dex_file->GetTypeBssMapping(), - type_idx.index_, - dex_file->NumTypeIds(), - sizeof(GcRoot<mirror::Class>)); - if (bss_offset != IndexBssMappingLookup::npos) { - StoreObjectInBss(outer_method, oat_dex_file->GetOatFile(), bss_offset, resolved_type); + auto store = [=](const IndexBssMapping* mapping) REQUIRES_SHARED(Locks::mutator_lock_) { + size_t bss_offset = IndexBssMappingLookup::GetBssOffset(mapping, + type_idx.index_, + dex_file->NumTypeIds(), + sizeof(GcRoot<mirror::Class>)); + if (bss_offset != IndexBssMappingLookup::npos) { + StoreObjectInBss(outer_method, oat_dex_file->GetOatFile(), bss_offset, resolved_type); + } + }; + store(oat_dex_file->GetTypeBssMapping()); + if (resolved_type->IsPublic()) { + store(oat_dex_file->GetPublicTypeBssMapping()); + } + if (resolved_type->IsPublic() || + resolved_type->GetClassLoader() == outer_method->GetClassLoader()) { + store(oat_dex_file->GetPackageTypeBssMapping()); } } } @@ -180,7 +190,9 @@ extern "C" mirror::Class* artResolveTypeAndVerifyAccessFromCode(uint32_t type_id self, /* can_run_clinit= */ false, /* verify_access= */ true); - // Do not StoreTypeInBss(); access check entrypoint is never used together with .bss. + if (LIKELY(result != nullptr) && CanReferenceBss(caller_and_outer.outer_method, caller)) { + StoreTypeInBss(caller_and_outer.outer_method, dex::TypeIndex(type_idx), result); + } return result.Ptr(); } diff --git a/runtime/oat.h b/runtime/oat.h index 960e878080..558c1e597b 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,8 +32,8 @@ class InstructionSetFeatures; class PACKED(4) OatHeader { public: static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } }; - // Last oat version changed reason: Removal of Thread->tls32_.debug_suspend_count - static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '8', '5', '\0' } }; + // Last oat version changed reason: Use .bss for ResoveTypeAndVerifyAccess. + static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '8', '6', '\0' } }; static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline"; static constexpr const char* kDebuggableKey = "debuggable"; diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 7a89abedf7..499d90b874 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -883,12 +883,18 @@ bool OatFileBase::Setup(int zip_fd, const IndexBssMapping* method_bss_mapping; const IndexBssMapping* type_bss_mapping; + const IndexBssMapping* public_type_bss_mapping; + const IndexBssMapping* package_type_bss_mapping; const IndexBssMapping* string_bss_mapping; if (!ReadIndexBssMapping( this, &oat, i, dex_file_location, "method", &method_bss_mapping, error_msg) || !ReadIndexBssMapping( this, &oat, i, dex_file_location, "type", &type_bss_mapping, error_msg) || !ReadIndexBssMapping( + this, &oat, i, dex_file_location, "type", &public_type_bss_mapping, error_msg) || + !ReadIndexBssMapping( + this, &oat, i, dex_file_location, "type", &package_type_bss_mapping, error_msg) || + !ReadIndexBssMapping( this, &oat, i, dex_file_location, "string", &string_bss_mapping, error_msg)) { return false; } @@ -903,6 +909,8 @@ bool OatFileBase::Setup(int zip_fd, lookup_table_data, method_bss_mapping, type_bss_mapping, + public_type_bss_mapping, + package_type_bss_mapping, string_bss_mapping, class_offsets_pointer, dex_layout_sections); @@ -1869,6 +1877,8 @@ OatDexFile::OatDexFile(const OatFile* oat_file, const uint8_t* lookup_table_data, const IndexBssMapping* method_bss_mapping_data, const IndexBssMapping* type_bss_mapping_data, + const IndexBssMapping* public_type_bss_mapping_data, + const IndexBssMapping* package_type_bss_mapping_data, const IndexBssMapping* string_bss_mapping_data, const uint32_t* oat_class_offsets_pointer, const DexLayoutSections* dex_layout_sections) @@ -1880,6 +1890,8 @@ OatDexFile::OatDexFile(const OatFile* oat_file, lookup_table_data_(lookup_table_data), method_bss_mapping_(method_bss_mapping_data), type_bss_mapping_(type_bss_mapping_data), + public_type_bss_mapping_(public_type_bss_mapping_data), + package_type_bss_mapping_(package_type_bss_mapping_data), string_bss_mapping_(string_bss_mapping_data), oat_class_offsets_pointer_(oat_class_offsets_pointer), lookup_table_(), diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 039c3de7c6..9e21b7e9e3 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -522,6 +522,14 @@ class OatDexFile final { return type_bss_mapping_; } + const IndexBssMapping* GetPublicTypeBssMapping() const { + return public_type_bss_mapping_; + } + + const IndexBssMapping* GetPackageTypeBssMapping() const { + return package_type_bss_mapping_; + } + const IndexBssMapping* GetStringBssMapping() const { return string_bss_mapping_; } @@ -565,6 +573,8 @@ class OatDexFile final { const uint8_t* lookup_table_data, const IndexBssMapping* method_bss_mapping, const IndexBssMapping* type_bss_mapping, + const IndexBssMapping* public_type_bss_mapping, + const IndexBssMapping* package_type_bss_mapping, const IndexBssMapping* string_bss_mapping, const uint32_t* oat_class_offsets_pointer, const DexLayoutSections* dex_layout_sections); @@ -588,6 +598,8 @@ class OatDexFile final { const uint8_t* const lookup_table_data_ = nullptr; const IndexBssMapping* const method_bss_mapping_ = nullptr; const IndexBssMapping* const type_bss_mapping_ = nullptr; + const IndexBssMapping* const public_type_bss_mapping_ = nullptr; + const IndexBssMapping* const package_type_bss_mapping_ = nullptr; const IndexBssMapping* const string_bss_mapping_ = nullptr; const uint32_t* const oat_class_offsets_pointer_ = nullptr; TypeLookupTable lookup_table_; diff --git a/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java index 073b03ea38..4864e64eba 100644 --- a/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java +++ b/test/727-checker-unresolved-class/src/unresolved/UnresolvedPublicClass.java @@ -18,6 +18,8 @@ package unresolved; import getters.GetUnresolvedPublicClass; import getters.GetUnresolvedPublicClassFromDifferentDexFile; +import resolved.PackagePrivateSubclassOfUnresolvedClass; +import resolved.PublicSubclassOfUnresolvedClass; import resolved.ResolvedPackagePrivateClass; import resolved.ResolvedPublicSubclassOfPackagePrivateClass; @@ -31,6 +33,10 @@ public class UnresolvedPublicClass { $noinline$testResolvedPublicClass(); $noinline$testResolvedPackagePrivateClass(); + $noinline$testUnresolvedPublicClass(); + $noinline$testUnresolvedPackagePrivateClass(); + $noinline$testUnresolvedPublicClassInSamePackage(); + $noinline$testUnresolvedPackagePrivateClassInSamePackage(); $noinline$testPublicFieldInResolvedPackagePrivateClass(); $noinline$testPublicFieldInPackagePrivateClassViaResolvedPublicSubclass(); @@ -104,6 +110,45 @@ public class UnresolvedPublicClass { } catch (IllegalAccessError expected) {} } + /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClass() builder (after) + /// CHECK: LoadClass class_name:resolved.PublicSubclassOfUnresolvedClass needs_access_check:true + + /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClass() builder (after) + /// CHECK: LoadClass load_kind:BssEntryPublic class_name:resolved.PublicSubclassOfUnresolvedClass + static void $noinline$testUnresolvedPublicClass() { + Class<?> c = PublicSubclassOfUnresolvedClass.class; + } + + /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClass() builder (after) + /// CHECK: LoadClass class_name:resolved.PackagePrivateSubclassOfUnresolvedClass needs_access_check:true + + /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClass() builder (after) + /// CHECK: LoadClass load_kind:BssEntryPublic class_name:resolved.PackagePrivateSubclassOfUnresolvedClass + static void $noinline$testUnresolvedPackagePrivateClass() { + try { + Class<?> c = PackagePrivateSubclassOfUnresolvedClass.class; + throw new Error("Unreachable"); + } catch (IllegalAccessError expected) {} + } + + /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClassInSamePackage() builder (after) + /// CHECK: LoadClass class_name:unresolved.UnresolvedPublicClazz needs_access_check:true + + /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPublicClassInSamePackage() builder (after) + /// CHECK: LoadClass load_kind:BssEntryPackage class_name:unresolved.UnresolvedPublicClazz + static void $noinline$testUnresolvedPublicClassInSamePackage() { + Class<?> c = UnresolvedPublicClazz.class; + } + + /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClassInSamePackage() builder (after) + /// CHECK: LoadClass class_name:unresolved.UnresolvedPackagePrivateClass needs_access_check:true + + /// CHECK-START-{ARM,ARM64,X86,X86_64}: void unresolved.UnresolvedPublicClass.$noinline$testUnresolvedPackagePrivateClassInSamePackage() builder (after) + /// CHECK: LoadClass load_kind:BssEntryPackage class_name:unresolved.UnresolvedPackagePrivateClass + static void $noinline$testUnresolvedPackagePrivateClassInSamePackage() { + Class<?> c = UnresolvedPackagePrivateClass.class; + } + /// CHECK-START: void unresolved.UnresolvedPublicClass.$noinline$testPublicFieldInResolvedPackagePrivateClass() builder (after) /// CHECK: UnresolvedStaticFieldSet |