diff options
author | 2017-09-17 13:44:24 -0700 | |
---|---|---|
committer | 2017-09-18 10:57:06 -0700 | |
commit | fc8b422c286501346b5b797420fb616aaa5e952a (patch) | |
tree | 61c857a895cdad9ce387a899f92824701259df32 | |
parent | 7090dfe84f78b1928fcbdfd664d0dd9ea52633ff (diff) |
Clean up AtomicDexRefMap
Make ClassReference, TypeReference, and MethodReference extend
DexFileReference. This enables using all of these types as the key
for AtomicDexRefMap.
Test: test-art-host
Bug: 63851220
Bug: 63756964
Change-Id: Ida3c94cadb53272cb5057e5cebc5971c1ab4d366
35 files changed, 278 insertions, 238 deletions
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc index 54ddc2188b..c8e3d5edd8 100644 --- a/compiler/dex/inline_method_analyser.cc +++ b/compiler/dex/inline_method_analyser.cc @@ -509,7 +509,7 @@ bool InlineMethodAnalyser::AnalyseMethodCode(const DexFile::CodeItem* code_item, } bool InlineMethodAnalyser::IsSyntheticAccessor(MethodReference ref) { - const DexFile::MethodId& method_id = ref.dex_file->GetMethodId(ref.dex_method_index); + const DexFile::MethodId& method_id = ref.dex_file->GetMethodId(ref.index); const char* method_name = ref.dex_file->GetMethodName(method_id); // javac names synthetic accessors "access$nnn", // jack names them "-getN", "-putN", "-wrapN". diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc index cfb56e30a8..03c90d82c8 100644 --- a/compiler/dex/verification_results.cc +++ b/compiler/dex/verification_results.cc @@ -52,18 +52,16 @@ void VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method // We'll punt this later. return; } - AtomicMap::InsertResult result = atomic_verified_methods_.Insert( - DexFileReference(ref.dex_file, ref.dex_method_index), - /*expected*/ nullptr, - verified_method.get()); + AtomicMap::InsertResult result = atomic_verified_methods_.Insert(ref, + /*expected*/ nullptr, + verified_method.get()); const VerifiedMethod* existing = nullptr; bool inserted; if (result != AtomicMap::kInsertResultInvalidDexFile) { inserted = (result == AtomicMap::kInsertResultSuccess); if (!inserted) { // Rare case. - CHECK(atomic_verified_methods_.Get(DexFileReference(ref.dex_file, ref.dex_method_index), - &existing)); + CHECK(atomic_verified_methods_.Get(ref, &existing)); CHECK_NE(verified_method.get(), existing); } } else { @@ -100,7 +98,7 @@ void VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method const VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) { const VerifiedMethod* ret = nullptr; - if (atomic_verified_methods_.Get(DexFileReference(ref.dex_file, ref.dex_method_index), &ret)) { + if (atomic_verified_methods_.Get(ref, &ret)) { return ret; } ReaderMutexLock mu(Thread::Current(), verified_methods_lock_); @@ -114,7 +112,7 @@ void VerificationResults::CreateVerifiedMethodFor(MethodReference ref) { // at runtime. std::unique_ptr<VerifiedMethod> verified_method = std::make_unique<VerifiedMethod>( /* encountered_error_types */ 0, /* has_runtime_throw */ false); - if (atomic_verified_methods_.Insert(DexFileReference(ref.dex_file, ref.dex_method_index), + if (atomic_verified_methods_.Insert(ref, /*expected*/ nullptr, verified_method.get()) == AtomicMap::InsertResult::kInsertResultSuccess) { @@ -149,7 +147,7 @@ bool VerificationResults::IsCandidateForCompilation(MethodReference&, } void VerificationResults::AddDexFile(const DexFile* dex_file) { - atomic_verified_methods_.AddDexFile(dex_file, dex_file->NumMethodIds()); + atomic_verified_methods_.AddDexFile(dex_file); WriterMutexLock mu(Thread::Current(), verified_methods_lock_); // There can be some verified methods that are already registered for the dex_file since we set // up well known classes earlier. Remove these and put them in the array so that we don't @@ -157,9 +155,7 @@ void VerificationResults::AddDexFile(const DexFile* dex_file) { for (auto it = verified_methods_.begin(); it != verified_methods_.end(); ) { MethodReference ref = it->first; if (ref.dex_file == dex_file) { - CHECK(atomic_verified_methods_.Insert(DexFileReference(ref.dex_file, ref.dex_method_index), - nullptr, - it->second) == + CHECK(atomic_verified_methods_.Insert(ref, nullptr, it->second) == AtomicMap::kInsertResultSuccess); it = verified_methods_.erase(it); } else { diff --git a/compiler/dex/verification_results.h b/compiler/dex/verification_results.h index 5a03599de0..d19e993661 100644 --- a/compiler/dex/verification_results.h +++ b/compiler/dex/verification_results.h @@ -64,10 +64,8 @@ class VerificationResults { private: // Verified methods. The method array is fixed to avoid needing a lock to extend it. - using AtomicMap = AtomicDexRefMap<const VerifiedMethod*>; - using VerifiedMethodMap = SafeMap<MethodReference, - const VerifiedMethod*, - MethodReferenceComparator>; + using AtomicMap = AtomicDexRefMap<MethodReference, const VerifiedMethod*>; + using VerifiedMethodMap = SafeMap<MethodReference, const VerifiedMethod*>; VerifiedMethodMap verified_methods_ GUARDED_BY(verified_methods_lock_); const CompilerOptions* const compiler_options_; diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index b9c0314cb1..678f090532 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -896,7 +896,7 @@ void CompilerDriver::PreCompile(jobject class_loader, for (const DexFile* dex_file : dex_files) { // Can be already inserted if the caller is CompileOne. This happens for gtests. if (!compiled_methods_.HaveDexFile(dex_file)) { - compiled_methods_.AddDexFile(dex_file, dex_file->NumMethodIds()); + compiled_methods_.AddDexFile(dex_file); } } // Resolve eagerly to prepare for compilation. @@ -964,7 +964,7 @@ bool CompilerDriver::IsMethodToCompile(const MethodReference& method_ref) const return true; } - std::string tmp = method_ref.dex_file->PrettyMethod(method_ref.dex_method_index, true); + std::string tmp = method_ref.PrettyMethod(); return methods_to_compile_->find(tmp.c_str()) != methods_to_compile_->end(); } @@ -985,8 +985,7 @@ bool CompilerDriver::ShouldCompileBasedOnProfile(const MethodReference& method_r if (kDebugProfileGuidedCompilation) { LOG(INFO) << "[ProfileGuidedCompilation] " - << (result ? "Compiled" : "Skipped") << " method:" - << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index, true); + << (result ? "Compiled" : "Skipped") << " method:" << method_ref.PrettyMethod(true); } return result; } @@ -1359,7 +1358,7 @@ void CompilerDriver::MarkForDexToDexCompilation(Thread* self, const MethodRefere &dex_to_dex_references_.back().GetDexFile() != method_ref.dex_file) { dex_to_dex_references_.emplace_back(*method_ref.dex_file); } - dex_to_dex_references_.back().GetMethodIndexes().SetBit(method_ref.dex_method_index); + dex_to_dex_references_.back().GetMethodIndexes().SetBit(method_ref.index); } bool CompilerDriver::CanAccessTypeWithoutChecks(ObjPtr<mirror::Class> referrer_class, @@ -1944,7 +1943,7 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, if (compiler_only_verifies) { // Just update the compiled_classes_ map. The compiler doesn't need to resolve // the type. - DexFileReference ref(dex_file, i); + ClassReference ref(dex_file, i); mirror::Class::Status existing = mirror::Class::kStatusNotReady; DCHECK(compiled_classes_.Get(ref, &existing)) << ref.dex_file->GetLocation(); ClassStateTable::InsertResult result = @@ -2220,7 +2219,7 @@ void CompilerDriver::SetVerifiedDexFile(jobject class_loader, TimingLogger* timings) { TimingLogger::ScopedTiming t("Verify Dex File", timings); if (!compiled_classes_.HaveDexFile(&dex_file)) { - compiled_classes_.AddDexFile(&dex_file, dex_file.NumClassDefs()); + compiled_classes_.AddDexFile(&dex_file); } ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files, @@ -2877,38 +2876,36 @@ void CompilerDriver::CompileDexFile(jobject class_loader, void CompilerDriver::AddCompiledMethod(const MethodReference& method_ref, CompiledMethod* const compiled_method, size_t non_relative_linker_patch_count) { - DCHECK(GetCompiledMethod(method_ref) == nullptr) - << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index); - MethodTable::InsertResult result = compiled_methods_.Insert( - DexFileReference(method_ref.dex_file, method_ref.dex_method_index), - /*expected*/ nullptr, - compiled_method); + DCHECK(GetCompiledMethod(method_ref) == nullptr) << method_ref.PrettyMethod(); + MethodTable::InsertResult result = compiled_methods_.Insert(method_ref, + /*expected*/ nullptr, + compiled_method); CHECK(result == MethodTable::kInsertResultSuccess); non_relative_linker_patch_count_.FetchAndAddRelaxed(non_relative_linker_patch_count); - DCHECK(GetCompiledMethod(method_ref) != nullptr) - << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index); + DCHECK(GetCompiledMethod(method_ref) != nullptr) << method_ref.PrettyMethod(); } -bool CompilerDriver::GetCompiledClass(ClassReference ref, mirror::Class::Status* status) const { +bool CompilerDriver::GetCompiledClass(const ClassReference& ref, + mirror::Class::Status* status) const { DCHECK(status != nullptr); // The table doesn't know if something wasn't inserted. For this case it will return // kStatusNotReady. To handle this, just assume anything we didn't try to verify is not compiled. - if (!compiled_classes_.Get(DexFileReference(ref.first, ref.second), status) || + if (!compiled_classes_.Get(ref, status) || *status < mirror::Class::kStatusRetryVerificationAtRuntime) { return false; } return true; } -mirror::Class::Status CompilerDriver::GetClassStatus(ClassReference ref) const { +mirror::Class::Status CompilerDriver::GetClassStatus(const ClassReference& ref) const { mirror::Class::Status status = ClassStatus::kStatusNotReady; if (!GetCompiledClass(ref, &status)) { - classpath_classes_.Get(DexFileReference(ref.first, ref.second), &status); + classpath_classes_.Get(ref, &status); } return status; } -void CompilerDriver::RecordClassStatus(ClassReference ref, mirror::Class::Status status) { +void CompilerDriver::RecordClassStatus(const ClassReference& ref, mirror::Class::Status status) { switch (status) { case mirror::Class::kStatusErrorResolved: case mirror::Class::kStatusErrorUnresolved: @@ -2921,30 +2918,30 @@ void CompilerDriver::RecordClassStatus(ClassReference ref, mirror::Class::Status break; // Expected states. default: LOG(FATAL) << "Unexpected class status for class " - << PrettyDescriptor(ref.first->GetClassDescriptor(ref.first->GetClassDef(ref.second))) + << PrettyDescriptor( + ref.dex_file->GetClassDescriptor(ref.dex_file->GetClassDef(ref.index))) << " of " << status; } ClassStateTable::InsertResult result; ClassStateTable* table = &compiled_classes_; do { - DexFileReference dex_ref(ref.first, ref.second); mirror::Class::Status existing = mirror::Class::kStatusNotReady; - if (!table->Get(dex_ref, &existing)) { + if (!table->Get(ref, &existing)) { // A classpath class. if (kIsDebugBuild) { // Check to make sure it's not a dex file for an oat file we are compiling since these // should always succeed. These do not include classes in for used libraries. for (const DexFile* dex_file : GetDexFilesForOatFile()) { - CHECK_NE(dex_ref.dex_file, dex_file) << dex_ref.dex_file->GetLocation(); + CHECK_NE(ref.dex_file, dex_file) << ref.dex_file->GetLocation(); } } - if (!classpath_classes_.HaveDexFile(ref.first)) { + if (!classpath_classes_.HaveDexFile(ref.dex_file)) { // Boot classpath dex file. return; } table = &classpath_classes_; - table->Get(dex_ref, &existing); + table->Get(ref, &existing); } if (existing >= status) { // Existing status is already better than we expect, break. @@ -2952,14 +2949,14 @@ void CompilerDriver::RecordClassStatus(ClassReference ref, mirror::Class::Status } // Update the status if we now have a greater one. This happens with vdex, // which records a class is verified, but does not resolve it. - result = table->Insert(dex_ref, existing, status); - CHECK(result != ClassStateTable::kInsertResultInvalidDexFile) << ref.first->GetLocation(); + result = table->Insert(ref, existing, status); + CHECK(result != ClassStateTable::kInsertResultInvalidDexFile) << ref.dex_file->GetLocation(); } while (result != ClassStateTable::kInsertResultSuccess); } CompiledMethod* CompilerDriver::GetCompiledMethod(MethodReference ref) const { CompiledMethod* compiled_method = nullptr; - compiled_methods_.Get(DexFileReference(ref.dex_file, ref.dex_method_index), &compiled_method); + compiled_methods_.Get(ref, &compiled_method); return compiled_method; } diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 5043884836..0d1cce7994 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -154,8 +154,8 @@ class CompilerDriver { std::unique_ptr<const std::vector<uint8_t>> CreateQuickResolutionTrampoline() const; std::unique_ptr<const std::vector<uint8_t>> CreateQuickToInterpreterBridge() const; - bool GetCompiledClass(ClassReference ref, mirror::Class::Status* status) const; - mirror::Class::Status GetClassStatus(ClassReference ref) const; + mirror::Class::Status GetClassStatus(const ClassReference& ref) const; + bool GetCompiledClass(const ClassReference& ref, mirror::Class::Status* status) const; CompiledMethod* GetCompiledMethod(MethodReference ref) const; size_t GetNonRelativeLinkerPatchCount() const; @@ -338,7 +338,7 @@ class CompilerDriver { // according to the profile file. bool ShouldVerifyClassBasedOnProfile(const DexFile& dex_file, uint16_t class_idx) const; - void RecordClassStatus(ClassReference ref, mirror::Class::Status status); + void RecordClassStatus(const ClassReference& ref, mirror::Class::Status status); // Checks if the specified method has been verified without failures. Returns // false if the method is not in the verification results (GetVerificationResults). @@ -489,13 +489,13 @@ class CompilerDriver { std::map<ClassReference, bool> requires_constructor_barrier_ GUARDED_BY(requires_constructor_barrier_lock_); - using ClassStateTable = AtomicDexRefMap<mirror::Class::Status>; // All class references that this compiler has compiled. Indexed by class defs. + using ClassStateTable = AtomicDexRefMap<ClassReference, mirror::Class::Status>; ClassStateTable compiled_classes_; // All class references that are in the classpath. Indexed by class defs. ClassStateTable classpath_classes_; - typedef AtomicDexRefMap<CompiledMethod*> MethodTable; + typedef AtomicDexRefMap<MethodReference, CompiledMethod*> MethodTable; private: // All method references that this compiler has compiled. diff --git a/compiler/linker/arm/relative_patcher_arm_base.cc b/compiler/linker/arm/relative_patcher_arm_base.cc index 6e63bf8990..1b061b31da 100644 --- a/compiler/linker/arm/relative_patcher_arm_base.cc +++ b/compiler/linker/arm/relative_patcher_arm_base.cc @@ -469,8 +469,7 @@ void ArmBaseRelativePatcher::ResolveMethodCalls(uint32_t quick_code_offset, if (!method_call_thunk_->HasReservedOffset() || patch_offset - method_call_thunk_->LastReservedOffset() > max_negative_displacement) { // No previous thunk in range, check if we can reach the target directly. - if (target_method.dex_file == method_ref.dex_file && - target_method.dex_method_index == method_ref.dex_method_index) { + if (target_method == method_ref) { DCHECK_GT(quick_code_offset, patch_offset); if (quick_code_offset - patch_offset > max_positive_displacement) { break; diff --git a/compiler/linker/arm64/relative_patcher_arm64_test.cc b/compiler/linker/arm64/relative_patcher_arm64_test.cc index d6919e9417..8a5b4cc8e5 100644 --- a/compiler/linker/arm64/relative_patcher_arm64_test.cc +++ b/compiler/linker/arm64/relative_patcher_arm64_test.cc @@ -344,7 +344,7 @@ class Arm64RelativePatcherTest : public RelativePatcherTest { uint32_t use_insn) { uint32_t method1_offset = GetMethodOffset(1u); CHECK(!compiled_method_refs_.empty()); - CHECK_EQ(compiled_method_refs_[0].dex_method_index, 1u); + CHECK_EQ(compiled_method_refs_[0].index, 1u); CHECK_EQ(compiled_method_refs_.size(), compiled_methods_.size()); uint32_t method1_size = compiled_methods_[0]->GetQuickCode().size(); uint32_t thunk_offset = CompiledCode::AlignCode(method1_offset + method1_size, kArm64); diff --git a/compiler/linker/multi_oat_relative_patcher.h b/compiler/linker/multi_oat_relative_patcher.h index 1c5c8a09c0..02cd4b0118 100644 --- a/compiler/linker/multi_oat_relative_patcher.h +++ b/compiler/linker/multi_oat_relative_patcher.h @@ -37,8 +37,7 @@ namespace linker { // to the value set by SetAdjustment(). class MultiOatRelativePatcher FINAL { public: - using const_iterator = - SafeMap<MethodReference, uint32_t, MethodReferenceComparator>::const_iterator; + using const_iterator = SafeMap<MethodReference, uint32_t>::const_iterator; MultiOatRelativePatcher(InstructionSet instruction_set, const InstructionSetFeatures* features); @@ -136,7 +135,7 @@ class MultiOatRelativePatcher FINAL { class MethodOffsetMap : public linker::RelativePatcherTargetProvider { public: std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) OVERRIDE; - SafeMap<MethodReference, uint32_t, MethodReferenceComparator> map; + SafeMap<MethodReference, uint32_t> map; }; MethodOffsetMap method_offset_map_; diff --git a/compiler/linker/multi_oat_relative_patcher_test.cc b/compiler/linker/multi_oat_relative_patcher_test.cc index f89fba698c..5c359dc9ca 100644 --- a/compiler/linker/multi_oat_relative_patcher_test.cc +++ b/compiler/linker/multi_oat_relative_patcher_test.cc @@ -26,10 +26,6 @@ namespace linker { static const MethodReference kNullMethodRef = MethodReference(nullptr, 0u); -static bool EqualRef(MethodReference lhs, MethodReference rhs) { - return lhs.dex_file == rhs.dex_file && lhs.dex_method_index == rhs.dex_method_index; -} - class MultiOatRelativePatcherTest : public testing::Test { protected: class MockPatcher : public RelativePatcher { @@ -182,7 +178,7 @@ TEST_F(MultiOatRelativePatcherTest, OffsetsInReserve) { uint32_t method1_offset = 0x100; uint32_t method1_offset_check = patcher_.ReserveSpace(method1_offset, method, ref1); ASSERT_EQ(adjustment1 + method1_offset, mock_->last_reserve_offset_); - ASSERT_TRUE(EqualRef(ref1, mock_->last_reserve_method_)); + ASSERT_TRUE(ref1 == mock_->last_reserve_method_); ASSERT_EQ(method1_offset, method1_offset_check); uint32_t method2_offset = 0x1230; @@ -190,13 +186,13 @@ TEST_F(MultiOatRelativePatcherTest, OffsetsInReserve) { mock_->next_reserve_adjustment_ = method2_reserve_adjustment; uint32_t method2_offset_adjusted = patcher_.ReserveSpace(method2_offset, method, ref2); ASSERT_EQ(adjustment1 + method2_offset, mock_->last_reserve_offset_); - ASSERT_TRUE(EqualRef(ref2, mock_->last_reserve_method_)); + ASSERT_TRUE(ref2 == mock_->last_reserve_method_); ASSERT_EQ(method2_offset + method2_reserve_adjustment, method2_offset_adjusted); uint32_t end1_offset = 0x4320; uint32_t end1_offset_check = patcher_.ReserveSpaceEnd(end1_offset); ASSERT_EQ(adjustment1 + end1_offset, mock_->last_reserve_offset_); - ASSERT_TRUE(EqualRef(kNullMethodRef, mock_->last_reserve_method_)); + ASSERT_TRUE(kNullMethodRef == mock_->last_reserve_method_); ASSERT_EQ(end1_offset, end1_offset_check); uint32_t adjustment2 = 0xd000; @@ -205,7 +201,7 @@ TEST_F(MultiOatRelativePatcherTest, OffsetsInReserve) { uint32_t method3_offset = 0xf00; uint32_t method3_offset_check = patcher_.ReserveSpace(method3_offset, method, ref3); ASSERT_EQ(adjustment2 + method3_offset, mock_->last_reserve_offset_); - ASSERT_TRUE(EqualRef(ref3, mock_->last_reserve_method_)); + ASSERT_TRUE(ref3 == mock_->last_reserve_method_); ASSERT_EQ(method3_offset, method3_offset_check); uint32_t end2_offset = 0x2400; @@ -213,7 +209,7 @@ TEST_F(MultiOatRelativePatcherTest, OffsetsInReserve) { mock_->next_reserve_adjustment_ = end2_reserve_adjustment; uint32_t end2_offset_adjusted = patcher_.ReserveSpaceEnd(end2_offset); ASSERT_EQ(adjustment2 + end2_offset, mock_->last_reserve_offset_); - ASSERT_TRUE(EqualRef(kNullMethodRef, mock_->last_reserve_method_)); + ASSERT_TRUE(kNullMethodRef == mock_->last_reserve_method_); ASSERT_EQ(end2_offset + end2_reserve_adjustment, end2_offset_adjusted); } diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h index bff68080c6..ca8743a561 100644 --- a/compiler/linker/relative_patcher_test.h +++ b/compiler/linker/relative_patcher_test.h @@ -194,8 +194,7 @@ class RelativePatcherTest : public testing::Test { // Sanity check: original code size must match linked_code.size(). size_t idx = 0u; for (auto ref : compiled_method_refs_) { - if (ref.dex_file == method_ref.dex_file && - ref.dex_method_index == method_ref.dex_method_index) { + if (ref == method_ref) { break; } ++idx; @@ -264,7 +263,7 @@ class RelativePatcherTest : public testing::Test { return std::pair<bool, uint32_t>(true, it->second); } } - SafeMap<MethodReference, uint32_t, MethodReferenceComparator> map; + SafeMap<MethodReference, uint32_t> map; }; static const uint32_t kTrampolineSize = 4u; diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 7ae3866bc1..0bd35872ff 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -765,7 +765,7 @@ class OatWriter::InitBssLayoutMethodVisitor : public DexMethodVisitor { Allocator::GetMallocAllocator())); refs_it->second.ClearAllBits(); } - refs_it->second.SetBit(target_method.dex_method_index); + refs_it->second.SetBit(target_method.index); writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u); } else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) { TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex()); @@ -922,7 +922,7 @@ class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { if (relative_patcher_->GetOffset(method_ref) != 0u) { // TODO: Should this be a hard failure? LOG(WARNING) << "Multiple definitions of " - << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index) + << method_ref.PrettyMethod() << " offsets " << relative_patcher_->GetOffset(method_ref) << " " << quick_code_offset; } else { @@ -1526,8 +1526,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { ObjPtr<mirror::DexCache> dex_cache = (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache( Thread::Current(), *ref.dex_file); - ArtMethod* method = - class_linker_->LookupResolvedMethod(ref.dex_method_index, dex_cache, class_loader_); + ArtMethod* method = class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_); CHECK(method != nullptr); return method; } diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 19e5d067a1..c61ef0a0bc 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -4641,7 +4641,7 @@ vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeMethodPatch( MethodReference target_method, vixl::aarch64::Label* adrp_label) { return NewPcRelativePatch(*target_method.dex_file, - target_method.dex_method_index, + target_method.index, adrp_label, &pc_relative_method_patches_); } @@ -4650,7 +4650,7 @@ vixl::aarch64::Label* CodeGeneratorARM64::NewMethodBssEntryPatch( MethodReference target_method, vixl::aarch64::Label* adrp_label) { return NewPcRelativePatch(*target_method.dex_file, - target_method.dex_method_index, + target_method.index, adrp_label, &method_bss_entry_patches_); } diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc index 8b9495d564..6147259bd3 100644 --- a/compiler/optimizing/code_generator_arm_vixl.cc +++ b/compiler/optimizing/code_generator_arm_vixl.cc @@ -9119,14 +9119,14 @@ void CodeGeneratorARMVIXL::GenerateVirtualCall( CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativeMethodPatch( MethodReference target_method) { return NewPcRelativePatch(*target_method.dex_file, - target_method.dex_method_index, + target_method.index, &pc_relative_method_patches_); } CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewMethodBssEntryPatch( MethodReference target_method) { return NewPcRelativePatch(*target_method.dex_file, - target_method.dex_method_index, + target_method.index, &method_bss_entry_patches_); } diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index f0ef0071b6..9db2bd35ca 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -1683,7 +1683,7 @@ CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativeMethodPa MethodReference target_method, const PcRelativePatchInfo* info_high) { return NewPcRelativePatch(*target_method.dex_file, - target_method.dex_method_index, + target_method.index, info_high, &pc_relative_method_patches_); } @@ -1692,7 +1692,7 @@ CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewMethodBssEntryPatc MethodReference target_method, const PcRelativePatchInfo* info_high) { return NewPcRelativePatch(*target_method.dex_file, - target_method.dex_method_index, + target_method.index, info_high, &method_bss_entry_patches_); } diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index 201b1b065f..a27cbce3db 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -1592,7 +1592,7 @@ CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewPcRelativeMeth MethodReference target_method, const PcRelativePatchInfo* info_high) { return NewPcRelativePatch(*target_method.dex_file, - target_method.dex_method_index, + target_method.index, info_high, &pc_relative_method_patches_); } @@ -1601,7 +1601,7 @@ CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewMethodBssEntry MethodReference target_method, const PcRelativePatchInfo* info_high) { return NewPcRelativePatch(*target_method.dex_file, - target_method.dex_method_index, + target_method.index, info_high, &method_bss_entry_patches_); } diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index e45ad0a9a3..c153cf78da 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -4623,7 +4623,7 @@ void CodeGeneratorX86::RecordBootMethodPatch(HInvokeStaticOrDirect* invoke) { invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress(); boot_image_method_patches_.emplace_back(address, *invoke->GetTargetMethod().dex_file, - invoke->GetTargetMethod().dex_method_index); + invoke->GetTargetMethod().index); __ Bind(&boot_image_method_patches_.back().label); } @@ -4633,7 +4633,7 @@ Label* CodeGeneratorX86::NewMethodBssEntryPatch( // Add the patch entry and bind its label at the end of the instruction. method_bss_entry_patches_.emplace_back(method_address, *target_method.dex_file, - target_method.dex_method_index); + target_method.index); return &method_bss_entry_patches_.back().label; } diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 8c4374d71e..bbf05a70d6 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1068,13 +1068,13 @@ void CodeGeneratorX86_64::GenerateVirtualCall( void CodeGeneratorX86_64::RecordBootMethodPatch(HInvokeStaticOrDirect* invoke) { boot_image_method_patches_.emplace_back(*invoke->GetTargetMethod().dex_file, - invoke->GetTargetMethod().dex_method_index); + invoke->GetTargetMethod().index); __ Bind(&boot_image_method_patches_.back().label); } Label* CodeGeneratorX86_64::NewMethodBssEntryPatch(MethodReference target_method) { // Add a patch entry and return the label. - method_bss_entry_patches_.emplace_back(*target_method.dex_file, target_method.dex_method_index); + method_bss_entry_patches_.emplace_back(*target_method.dex_file, target_method.index); return &method_bss_entry_patches_.back().label; } diff --git a/compiler/utils/atomic_dex_ref_map-inl.h b/compiler/utils/atomic_dex_ref_map-inl.h index 14f1f0b981..33d59f9d42 100644 --- a/compiler/utils/atomic_dex_ref_map-inl.h +++ b/compiler/utils/atomic_dex_ref_map-inl.h @@ -19,15 +19,40 @@ #include "atomic_dex_ref_map.h" +#include <type_traits> + #include "dex_file-inl.h" +#include "class_reference.h" +#include "method_reference.h" +#include "type_reference.h" namespace art { -template <typename T> -inline typename AtomicDexRefMap<T>::InsertResult AtomicDexRefMap<T>::Insert( - DexFileReference ref, - const T& expected, - const T& desired) { +template <typename DexFileReferenceType, typename Value> +inline size_t AtomicDexRefMap<DexFileReferenceType, Value>::NumberOfDexIndices( + const DexFile* dex_file) { + // TODO: Use specialization for this? Not sure if worth it. + static_assert(std::is_same<DexFileReferenceType, MethodReference>::value || + std::is_same<DexFileReferenceType, ClassReference>::value || + std::is_same<DexFileReferenceType, TypeReference>::value, + "invalid index type"); + if (std::is_same<DexFileReferenceType, MethodReference>::value) { + return dex_file->NumMethodIds(); + } + if (std::is_same<DexFileReferenceType, ClassReference>::value) { + return dex_file->NumClassDefs(); + } + if (std::is_same<DexFileReferenceType, TypeReference>::value) { + return dex_file->NumTypeIds(); + } + UNREACHABLE(); +} + +template <typename DexFileReferenceType, typename Value> +inline typename AtomicDexRefMap<DexFileReferenceType, Value>::InsertResult + AtomicDexRefMap<DexFileReferenceType, Value>::Insert(const DexFileReferenceType& ref, + const Value& expected, + const Value& desired) { ElementArray* const array = GetArray(ref.dex_file); if (array == nullptr) { return kInsertResultInvalidDexFile; @@ -38,8 +63,9 @@ inline typename AtomicDexRefMap<T>::InsertResult AtomicDexRefMap<T>::Insert( : kInsertResultCASFailure; } -template <typename T> -inline bool AtomicDexRefMap<T>::Get(DexFileReference ref, T* out) const { +template <typename DexFileReferenceType, typename Value> +inline bool AtomicDexRefMap<DexFileReferenceType, Value>::Get(const DexFileReferenceType& ref, + Value* out) const { const ElementArray* const array = GetArray(ref.dex_file); if (array == nullptr) { return false; @@ -48,36 +74,37 @@ inline bool AtomicDexRefMap<T>::Get(DexFileReference ref, T* out) const { return true; } -template <typename T> -inline void AtomicDexRefMap<T>::AddDexFile(const DexFile* dex_file, size_t max_index) { - arrays_.Put(dex_file, std::move(ElementArray(max_index))); +template <typename DexFileReferenceType, typename Value> +inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFile(const DexFile* dex_file) { + arrays_.Put(dex_file, std::move(ElementArray(NumberOfDexIndices(dex_file)))); } -template <typename T> -inline void AtomicDexRefMap<T>::AddDexFiles(const std::vector<const DexFile*>& dex_files) { +template <typename DexFileReferenceType, typename Value> +inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFiles( + const std::vector<const DexFile*>& dex_files) { for (const DexFile* dex_file : dex_files) { if (!HaveDexFile(dex_file)) { - AddDexFile(dex_file, dex_file->NumClassDefs()); + AddDexFile(dex_file); } } } -template <typename T> -inline typename AtomicDexRefMap<T>::ElementArray* AtomicDexRefMap<T>::GetArray( - const DexFile* dex_file) { +template <typename DexFileReferenceType, typename Value> +inline typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray* + AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) { auto it = arrays_.find(dex_file); return (it != arrays_.end()) ? &it->second : nullptr; } -template <typename T> -inline const typename AtomicDexRefMap<T>::ElementArray* AtomicDexRefMap<T>::GetArray( - const DexFile* dex_file) const { +template <typename DexFileReferenceType, typename Value> +inline const typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray* + AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) const { auto it = arrays_.find(dex_file); return (it != arrays_.end()) ? &it->second : nullptr; } -template <typename T> template <typename Visitor> -inline void AtomicDexRefMap<T>::Visit(const Visitor& visitor) { +template <typename DexFileReferenceType, typename Value> template <typename Visitor> +inline void AtomicDexRefMap<DexFileReferenceType, Value>::Visit(const Visitor& visitor) { for (auto& pair : arrays_) { const DexFile* dex_file = pair.first; const ElementArray& elements = pair.second; @@ -87,8 +114,8 @@ inline void AtomicDexRefMap<T>::Visit(const Visitor& visitor) { } } -template <typename T> -inline void AtomicDexRefMap<T>::ClearEntries() { +template <typename DexFileReferenceType, typename Value> +inline void AtomicDexRefMap<DexFileReferenceType, Value>::ClearEntries() { for (auto& it : arrays_) { for (auto& element : it.second) { element.StoreRelaxed(nullptr); diff --git a/compiler/utils/atomic_dex_ref_map.h b/compiler/utils/atomic_dex_ref_map.h index b02c9b634e..fad056c191 100644 --- a/compiler/utils/atomic_dex_ref_map.h +++ b/compiler/utils/atomic_dex_ref_map.h @@ -18,7 +18,7 @@ #define ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_H_ #include "base/dchecked_vector.h" -#include "dex_file.h" +#include "dex_file_reference.h" #include "safe_map.h" namespace art { @@ -26,7 +26,7 @@ namespace art { class DexFile; // Used by CompilerCallbacks to track verification information from the Runtime. -template <typename T> +template <typename DexFileReferenceType, typename Value> class AtomicDexRefMap { public: explicit AtomicDexRefMap() {} @@ -38,14 +38,16 @@ class AtomicDexRefMap { kInsertResultCASFailure, kInsertResultSuccess, }; - InsertResult Insert(DexFileReference ref, const T& expected, const T& desired); + InsertResult Insert(const DexFileReferenceType& ref, + const Value& expected, + const Value& desired); // Retreive an item, returns false if the dex file is not added. - bool Get(DexFileReference ref, T* out) const; + bool Get(const DexFileReferenceType& ref, Value* out) const; // Dex files must be added before method references belonging to them can be used as keys. Not // thread safe. - void AddDexFile(const DexFile* dex_file, size_t max_index); + void AddDexFile(const DexFile* dex_file); void AddDexFiles(const std::vector<const DexFile*>& dex_files); bool HaveDexFile(const DexFile* dex_file) const { @@ -60,12 +62,14 @@ class AtomicDexRefMap { private: // Verified methods. The method array is fixed to avoid needing a lock to extend it. - using ElementArray = dchecked_vector<Atomic<T>>; + using ElementArray = dchecked_vector<Atomic<Value>>; using DexFileArrays = SafeMap<const DexFile*, ElementArray>; const ElementArray* GetArray(const DexFile* dex_file) const; ElementArray* GetArray(const DexFile* dex_file); + static size_t NumberOfDexIndices(const DexFile* dex_file); + DexFileArrays arrays_; }; diff --git a/compiler/utils/atomic_dex_ref_map_test.cc b/compiler/utils/atomic_dex_ref_map_test.cc index ae19a9c6da..8fce36f021 100644 --- a/compiler/utils/atomic_dex_ref_map_test.cc +++ b/compiler/utils/atomic_dex_ref_map_test.cc @@ -31,40 +31,40 @@ TEST_F(AtomicDexRefMapTest, RunTests) { ScopedObjectAccess soa(Thread::Current()); std::unique_ptr<const DexFile> dex(OpenTestDexFile("Interfaces")); ASSERT_TRUE(dex != nullptr); - using Map = AtomicDexRefMap<int>; + using Map = AtomicDexRefMap<MethodReference, int>; Map map; int value = 123; // Error case: Not already inserted. - EXPECT_FALSE(map.Get(DexFileReference(dex.get(), 1), &value)); + EXPECT_FALSE(map.Get(MethodReference(dex.get(), 1), &value)); EXPECT_FALSE(map.HaveDexFile(dex.get())); // Error case: Dex file not registered. - EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 1), 0, 1) == Map::kInsertResultInvalidDexFile); - map.AddDexFile(dex.get(), dex->NumMethodIds()); + EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 1), 0, 1) == Map::kInsertResultInvalidDexFile); + map.AddDexFile(dex.get()); EXPECT_TRUE(map.HaveDexFile(dex.get())); EXPECT_GT(dex->NumMethodIds(), 10u); // After we have added the get should succeed but return the default value. - EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 1), &value)); + EXPECT_TRUE(map.Get(MethodReference(dex.get(), 1), &value)); EXPECT_EQ(value, 0); // Actually insert an item and make sure we can retreive it. static const int kInsertValue = 44; - EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 1), 0, kInsertValue) == + EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 1), 0, kInsertValue) == Map::kInsertResultSuccess); - EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 1), &value)); + EXPECT_TRUE(map.Get(MethodReference(dex.get(), 1), &value)); EXPECT_EQ(value, kInsertValue); static const int kInsertValue2 = 123; - EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 2), 0, kInsertValue2) == + EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 2), 0, kInsertValue2) == Map::kInsertResultSuccess); - EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 1), &value)); + EXPECT_TRUE(map.Get(MethodReference(dex.get(), 1), &value)); EXPECT_EQ(value, kInsertValue); - EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 2), &value)); + EXPECT_TRUE(map.Get(MethodReference(dex.get(), 2), &value)); EXPECT_EQ(value, kInsertValue2); // Error case: Incorrect expected value for CAS. - EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 1), 0, kInsertValue + 1) == + EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 1), 0, kInsertValue + 1) == Map::kInsertResultCASFailure); // Correctly overwrite the value and verify. - EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 1), kInsertValue, kInsertValue + 1) == + EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 1), kInsertValue, kInsertValue + 1) == Map::kInsertResultSuccess); - EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 1), &value)); + EXPECT_TRUE(map.Get(MethodReference(dex.get(), 1), &value)); EXPECT_EQ(value, kInsertValue + 1); } diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc index 5c097da16f..c706370c3d 100644 --- a/compiler/verifier_deps_test.cc +++ b/compiler/verifier_deps_test.cc @@ -97,7 +97,7 @@ class VerifierDepsTest : public CommonCompilerTest { callbacks_->SetVerifierDeps(nullptr); // Clear entries in the verification results to avoid hitting a DCHECK that // we always succeed inserting a new entry after verifying. - AtomicDexRefMap<const VerifiedMethod*>* map = + AtomicDexRefMap<MethodReference, const VerifiedMethod*>* map = &compiler_driver_->GetVerificationResults()->atomic_verified_methods_; map->Visit([](const DexFileReference& ref ATTRIBUTE_UNUSED, const VerifiedMethod* method) { delete method; diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc index 04c2fcdd4c..7ddf1c16ec 100644 --- a/dex2oat/dex2oat_image_test.cc +++ b/dex2oat/dex2oat_image_test.cc @@ -87,16 +87,14 @@ class Dex2oatImageTest : public CommonRuntimeTest { void GenerateClasses(File* out_file, size_t frequency = 1) { VisitLibcoreDexes(VoidFunctor(), [out_file](TypeReference ref) { - WriteLine(out_file, - ref.dex_file->PrettyType(ref.type_index)); + WriteLine(out_file, ref.dex_file->PrettyType(ref.TypeIndex())); }, frequency, frequency); EXPECT_EQ(out_file->Flush(), 0); } void GenerateMethods(File* out_file, size_t frequency = 1) { VisitLibcoreDexes([out_file](MethodReference ref) { - WriteLine(out_file, - ref.dex_file->PrettyMethod(ref.dex_method_index)); + WriteLine(out_file, ref.PrettyMethod()); }, VoidFunctor(), frequency, frequency); EXPECT_EQ(out_file->Flush(), 0); } @@ -315,7 +313,7 @@ TEST_F(Dex2oatImageTest, TestModesAndFilters) { VisitLibcoreDexes([&profile](MethodReference ref) { EXPECT_TRUE(profile.AddMethodIndex(ProfileCompilationInfo::MethodHotness::kFlagHot, ref)); }, [&profile](TypeReference ref) { - EXPECT_TRUE(profile.AddClassesForDex(ref.dex_file, &ref.type_index, &ref.type_index + 1)); + EXPECT_TRUE(profile.AddClassForDex(ref)); }, kMethodFrequency, kTypeFrequency); ScratchFile profile_file; profile.Save(profile_file.GetFile()->Fd()); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 13f7211116..7b11258a89 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -936,7 +936,7 @@ class OatDumper { } // Unique string ids loaded from dex code. - std::set<StringReference, StringReferenceComparator> unique_string_ids_from_code_; + std::set<StringReference> unique_string_ids_from_code_; // Total string ids loaded from dex code. size_t num_string_ids_from_code_ = 0; diff --git a/profman/boot_image_profile.cc b/profman/boot_image_profile.cc index 21de0831b8..4092f6ed98 100644 --- a/profman/boot_image_profile.cc +++ b/profman/boot_image_profile.cc @@ -60,8 +60,7 @@ void GenerateBootImageProfile( if (hotness.IsInProfile()) { ++counter; out_profile->AddMethodHotness(ref, hotness); - inferred_classes.emplace(profile.get(), - dex_file->GetMethodId(ref.dex_method_index).class_idx_); + inferred_classes.emplace(profile.get(), ref.GetMethodId().class_idx_); } } // If the counter is greater or equal to the compile threshold, mark the method as hot. @@ -110,9 +109,9 @@ void GenerateBootImageProfile( // This counter is how many profiles contain the class. size_t counter = 0; for (const std::unique_ptr<const ProfileCompilationInfo>& profile : profiles) { - auto it = inferred_classes.find(std::make_pair(profile.get(), ref.type_index)); + auto it = inferred_classes.find(std::make_pair(profile.get(), ref.TypeIndex())); if (it != inferred_classes.end() || - profile->ContainsClass(*ref.dex_file, ref.type_index)) { + profile->ContainsClass(*ref.dex_file, ref.TypeIndex())) { ++counter; } } @@ -121,10 +120,10 @@ void GenerateBootImageProfile( } if (counter >= options.image_class_theshold) { ++class_count; - out_profile->AddClassesForDex(ref.dex_file, &ref.type_index, &ref.type_index + 1); + out_profile->AddClassForDex(ref); } else if (is_clean && counter >= options.image_class_clean_theshold) { ++clean_class_count; - out_profile->AddClassesForDex(ref.dex_file, &ref.type_index, &ref.type_index + 1); + out_profile->AddClassForDex(ref); } } } diff --git a/profman/profman.cc b/profman/profman.cc index d0c99e0201..5e840e699c 100644 --- a/profman/profman.cc +++ b/profman/profman.cc @@ -634,8 +634,7 @@ class ProfMan FINAL { if (kInvalidTypeIndex >= dex_file->NumTypeIds()) { // The dex file does not contain all possible type ids which leaves us room // to add an "invalid" type id. - class_ref->dex_file = dex_file; - class_ref->type_index = dex::TypeIndex(kInvalidTypeIndex); + *class_ref = TypeReference(dex_file, dex::TypeIndex(kInvalidTypeIndex)); return true; } else { // The dex file contains all possible type ids. We don't have any free type id @@ -653,8 +652,7 @@ class ProfMan FINAL { // Class is only referenced in the current dex file but not defined in it. continue; } - class_ref->dex_file = dex_file; - class_ref->type_index = type_index; + *class_ref = TypeReference(dex_file, type_index); return true; } return false; @@ -698,7 +696,7 @@ class ProfMan FINAL { return DexFile::kDexNoIndex; } const DexFile::MethodId* method_id = dex_file->FindMethodId( - dex_file->GetTypeId(class_ref.type_index), *name_id, *proto_id); + dex_file->GetTypeId(class_ref.TypeIndex()), *name_id, *proto_id); if (method_id == nullptr) { LOG(WARNING) << "Could not find method_id: " << name; return DexFile::kDexNoIndex; @@ -718,7 +716,7 @@ class ProfMan FINAL { /*out*/uint32_t* dex_pc) { const DexFile* dex_file = class_ref.dex_file; uint32_t offset = dex_file->FindCodeItemOffset( - *dex_file->FindClassDef(class_ref.type_index), + *dex_file->FindClassDef(class_ref.TypeIndex()), method_index); const DexFile::CodeItem* code_item = dex_file->GetCodeItem(offset); @@ -799,11 +797,11 @@ class ProfMan FINAL { dex_file->GetBaseLocation(), dex_file->GetLocationChecksum(), dex_file->NumMethodIds()); - dex_resolved_classes.first->AddClass(class_ref.type_index); + dex_resolved_classes.first->AddClass(class_ref.TypeIndex()); std::vector<ProfileMethodInfo> methods; if (method_str == kClassAllMethods) { // Add all of the methods. - const DexFile::ClassDef* class_def = dex_file->FindClassDef(class_ref.type_index); + const DexFile::ClassDef* class_def = dex_file->FindClassDef(class_ref.TypeIndex()); const uint8_t* class_data = dex_file->GetClassData(*class_def); if (class_data != nullptr) { ClassDataItemIterator it(*dex_file, class_data); diff --git a/runtime/class_reference.h b/runtime/class_reference.h index 7b206126d6..2ef9ab8959 100644 --- a/runtime/class_reference.h +++ b/runtime/class_reference.h @@ -20,22 +20,22 @@ #include <stdint.h> #include <utility> +#include "dex_file_reference.h" + namespace art { class DexFile; // A class is uniquely located by its DexFile and the class_defs_ table index into that DexFile -typedef std::pair<const DexFile*, uint32_t> ClassReference; - -inline bool operator<(const ClassReference& lhs, const ClassReference& rhs) { - if (lhs.second < rhs.second) { - return true; - } else if (lhs.second > rhs.second) { - return false; - } else { - return (lhs.first < rhs.first); +class ClassReference : public DexFileReference { + public: + ClassReference(const DexFile* file, uint32_t class_def_idx) + : DexFileReference(file, class_def_idx) {} + + uint32_t ClassDefIdx() const { + return index; } -} +}; } // namespace art diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 5f81b981dd..1061fd3a47 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -1238,12 +1238,6 @@ class DexFile { ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for constructor }; -struct DexFileReference { - DexFileReference(const DexFile* file, uint32_t idx) : dex_file(file), index(idx) { } - const DexFile* dex_file; - uint32_t index; -}; - std::ostream& operator<<(std::ostream& os, const DexFile& dex_file); // Iterate over a dex file's ProtoId's paramters diff --git a/runtime/dex_file_reference.h b/runtime/dex_file_reference.h new file mode 100644 index 0000000000..01a64257a8 --- /dev/null +++ b/runtime/dex_file_reference.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_RUNTIME_DEX_FILE_REFERENCE_H_ +#define ART_RUNTIME_DEX_FILE_REFERENCE_H_ + +#include <cstdint> + +namespace art { + +class DexFile; + +class DexFileReference { + public: + DexFileReference(const DexFile* file, uint32_t idx) : dex_file(file), index(idx) {} + const DexFile* dex_file; + uint32_t index; + + struct Comparator { + bool operator()(const DexFileReference& a, const DexFileReference& b) const { + if (a.dex_file != b.dex_file) { + return a.dex_file < b.dex_file; + } + return a.index < b.index; + } + }; +}; + +// Default comparators, compares the indicies, not the backing data. +inline bool operator<(const DexFileReference& a, const DexFileReference& b) { + return DexFileReference::Comparator()(a, b); +} +inline bool operator==(const DexFileReference& a, const DexFileReference& b) { + return a.dex_file == b.dex_file && a.index == b.index; +} + +} // namespace art + +#endif // ART_RUNTIME_DEX_FILE_REFERENCE_H_ diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index ad65304fe5..7d7c5a5a33 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -1156,34 +1156,33 @@ extern "C" const void* artQuickResolutionTrampoline( LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(nullptr); UNREACHABLE(); } - called_method.dex_method_index = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c(); + called_method.index = (is_range) ? instr->VRegB_3rc() : instr->VRegB_35c(); // Check that the invoke matches what we expected, note that this path only happens for debug // builds. if (found_stack_map) { DCHECK_EQ(stack_map_invoke_type, invoke_type); if (invoke_type != kSuper) { // Super may be sharpened. - DCHECK_EQ(stack_map_dex_method_idx, called_method.dex_method_index) + DCHECK_EQ(stack_map_dex_method_idx, called_method.index) << called_method.dex_file->PrettyMethod(stack_map_dex_method_idx) << " " - << called_method.dex_file->PrettyMethod(called_method.dex_method_index); + << called_method.PrettyMethod(); } } else { VLOG(dex) << "Accessed dex file for invoke " << invoke_type << " " - << called_method.dex_method_index; + << called_method.index; } } else { invoke_type = stack_map_invoke_type; - called_method.dex_method_index = stack_map_dex_method_idx; + called_method.index = stack_map_dex_method_idx; } } else { invoke_type = kStatic; called_method.dex_file = called->GetDexFile(); - called_method.dex_method_index = called->GetDexMethodIndex(); + called_method.index = called->GetDexMethodIndex(); } uint32_t shorty_len; const char* shorty = - called_method.dex_file->GetMethodShorty( - called_method.dex_file->GetMethodId(called_method.dex_method_index), &shorty_len); + called_method.dex_file->GetMethodShorty(called_method.GetMethodId(), &shorty_len); RememberForGcArgumentVisitor visitor(sp, invoke_type == kStatic, shorty, shorty_len, &soa); visitor.VisitArguments(); self->EndAssertNoThreadSuspension(old_cause); @@ -1196,7 +1195,7 @@ extern "C" const void* artQuickResolutionTrampoline( hs.NewHandleWrapper(virtual_or_interface ? &receiver : &dummy)); DCHECK_EQ(caller->GetDexFile(), called_method.dex_file); called = linker->ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>( - self, called_method.dex_method_index, caller, invoke_type); + self, called_method.index, caller, invoke_type); // Update .bss entry in oat file if any. if (called != nullptr && called_method.dex_file->GetOatDexFile() != nullptr) { @@ -1207,10 +1206,10 @@ extern "C" const void* artQuickResolutionTrampoline( mapping->begin(), mapping->end(), [called_method](const MethodBssMappingEntry& entry) { - return entry.method_index < called_method.dex_method_index; + return entry.method_index < called_method.index; }); - if (pp != mapping->end() && pp->CoversIndex(called_method.dex_method_index)) { - size_t bss_offset = pp->GetBssOffset(called_method.dex_method_index, + if (pp != mapping->end() && pp->CoversIndex(called_method.index)) { + size_t bss_offset = pp->GetBssOffset(called_method.index, static_cast<size_t>(kRuntimePointerSize)); DCHECK_ALIGNED(bss_offset, static_cast<size_t>(kRuntimePointerSize)); const OatFile* oat_file = called_method.dex_file->GetOatDexFile()->GetOatFile(); @@ -1250,7 +1249,7 @@ extern "C" const void* artQuickResolutionTrampoline( // TODO Maybe put this into a mirror::Class function. ObjPtr<mirror::Class> ref_class = linker->LookupResolvedType( *dex_cache->GetDexFile(), - dex_cache->GetDexFile()->GetMethodId(called_method.dex_method_index).class_idx_, + dex_cache->GetDexFile()->GetMethodId(called_method.index).class_idx_, dex_cache.Get(), class_loader.Get()); if (ref_class->IsInterface()) { diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc index 1f2163f30d..57fc4976f7 100644 --- a/runtime/jit/profile_compilation_info.cc +++ b/runtime/jit/profile_compilation_info.cc @@ -143,7 +143,7 @@ bool ProfileCompilationInfo::AddMethodIndex(MethodHotness::Flag flags, const Met if (data == nullptr) { return false; } - data->AddMethod(flags, ref.dex_method_index); + data->AddMethod(flags, ref.index); return true; } @@ -683,7 +683,7 @@ bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi) { if (data == nullptr) { // checksum mismatch return false; } - InlineCacheMap* inline_cache = data->FindOrAddMethod(pmi.ref.dex_method_index); + InlineCacheMap* inline_cache = data->FindOrAddMethod(pmi.ref.index); for (const ProfileMethodInfo::ProfileInlineCache& cache : pmi.inline_caches) { if (cache.is_missing_types) { @@ -700,7 +700,7 @@ bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi) { // Don't bother adding classes if we are missing types. break; } - dex_pc_data->AddClass(class_dex_data->profile_index, class_ref.type_index); + dex_pc_data->AddClass(class_dex_data->profile_index, class_ref.TypeIndex()); } } return true; @@ -1333,7 +1333,7 @@ ProfileCompilationInfo::MethodHotness ProfileCompilationInfo::GetMethodHotness( const MethodReference& method_ref) const { const DexFileData* dex_data = FindDexData(method_ref.dex_file); return dex_data != nullptr - ? dex_data->GetHotnessInfo(method_ref.dex_method_index) + ? dex_data->GetHotnessInfo(method_ref.index) : MethodHotness(); } @@ -1342,8 +1342,7 @@ bool ProfileCompilationInfo::AddMethodHotness(const MethodReference& method_ref, DexFileData* dex_data = GetOrAddDexFileData(method_ref.dex_file); if (dex_data != nullptr) { // TODO: Add inline caches. - dex_data->AddMethod(static_cast<MethodHotness::Flag>(hotness.GetFlags()), - method_ref.dex_method_index); + dex_data->AddMethod(static_cast<MethodHotness::Flag>(hotness.GetFlags()), method_ref.index); return true; } return false; diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h index 7fd7a2d049..5c7448fe63 100644 --- a/runtime/jit/profile_compilation_info.h +++ b/runtime/jit/profile_compilation_info.h @@ -254,6 +254,16 @@ class ProfileCompilationInfo { data->class_set.insert(index_begin, index_end); return true; } + // Add a single type id for a dex file. + bool AddClassForDex(const TypeReference& ref) { + DexFileData* data = GetOrAddDexFileData(ref.dex_file); + if (data == nullptr) { + return false; + } + data->class_set.insert(ref.TypeIndex()); + return true; + } + // Add a method index to the profile (without inline caches). The method flags determine if it is // hot, startup, or post startup, or a combination of the previous. diff --git a/runtime/jit/profile_compilation_info_test.cc b/runtime/jit/profile_compilation_info_test.cc index 40d303fc13..2cb8294dbd 100644 --- a/runtime/jit/profile_compilation_info_test.cc +++ b/runtime/jit/profile_compilation_info_test.cc @@ -195,7 +195,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { for (const auto& class_ref : inline_cache.classes) { uint8_t dex_profile_index = dex_map.FindOrAdd(const_cast<DexFile*>(class_ref.dex_file), static_cast<uint8_t>(dex_map.size()))->second; - dex_pc_data.AddClass(dex_profile_index, class_ref.type_index); + dex_pc_data.AddClass(dex_profile_index, class_ref.TypeIndex()); if (dex_profile_index >= offline_pmi.dex_references.size()) { // This is a new dex. const std::string& dex_key = ProfileCompilationInfo::GetProfileDexFileKey( diff --git a/runtime/method_reference.h b/runtime/method_reference.h index 3948ed5bb9..31f3b8e84e 100644 --- a/runtime/method_reference.h +++ b/runtime/method_reference.h @@ -20,27 +20,19 @@ #include <stdint.h> #include <string> #include "dex_file.h" +#include "dex_file_reference.h" namespace art { // A method is uniquely located by its DexFile and the method_ids_ table index into that DexFile -struct MethodReference { - MethodReference(const DexFile* file, uint32_t index) : dex_file(file), dex_method_index(index) { +class MethodReference : public DexFileReference { + public: + MethodReference(const DexFile* file, uint32_t index) : DexFileReference(file, index) {} + std::string PrettyMethod(bool with_signature = true) const { + return dex_file->PrettyMethod(index, with_signature); } - std::string PrettyMethod(bool with_signature = true) { - return dex_file->PrettyMethod(dex_method_index, with_signature); - } - const DexFile* dex_file; - uint32_t dex_method_index; -}; - -struct MethodReferenceComparator { - bool operator()(MethodReference mr1, MethodReference mr2) const { - if (mr1.dex_file == mr2.dex_file) { - return mr1.dex_method_index < mr2.dex_method_index; - } else { - return mr1.dex_file < mr2.dex_file; - } + const DexFile::MethodId& GetMethodId() const { + return dex_file->GetMethodId(index); } }; @@ -48,8 +40,8 @@ struct MethodReferenceComparator { struct MethodReferenceValueComparator { bool operator()(MethodReference mr1, MethodReference mr2) const { if (mr1.dex_file == mr2.dex_file) { - DCHECK_EQ(mr1.dex_method_index < mr2.dex_method_index, SlowCompare(mr1, mr2)); - return mr1.dex_method_index < mr2.dex_method_index; + DCHECK_EQ(mr1.index < mr2.index, SlowCompare(mr1, mr2)); + return mr1.index < mr2.index; } else { return SlowCompare(mr1, mr2); } @@ -58,8 +50,8 @@ struct MethodReferenceValueComparator { bool SlowCompare(MethodReference mr1, MethodReference mr2) const { // The order is the same as for method ids in a single dex file. // Compare the class descriptors first. - const DexFile::MethodId& mid1 = mr1.dex_file->GetMethodId(mr1.dex_method_index); - const DexFile::MethodId& mid2 = mr2.dex_file->GetMethodId(mr2.dex_method_index); + const DexFile::MethodId& mid1 = mr1.GetMethodId(); + const DexFile::MethodId& mid2 = mr2.GetMethodId(); int descriptor_diff = strcmp(mr1.dex_file->StringByTypeIdx(mid1.class_idx_), mr2.dex_file->StringByTypeIdx(mid2.class_idx_)); if (descriptor_diff != 0) { diff --git a/runtime/string_reference.h b/runtime/string_reference.h index 6ba47736ec..d0ab4e40d0 100644 --- a/runtime/string_reference.h +++ b/runtime/string_reference.h @@ -21,37 +21,30 @@ #include "base/logging.h" #include "dex_file-inl.h" +#include "dex_file_reference.h" #include "dex_file_types.h" #include "utf-inl.h" namespace art { // A string is located by its DexFile and the string_ids_ table index into that DexFile. -struct StringReference { +class StringReference : public DexFileReference { + public: StringReference(const DexFile* file, dex::StringIndex index) - : dex_file(file), string_index(index) { } + : DexFileReference(file, index.index_) {} - const char* GetStringData() const { - return dex_file->GetStringData(dex_file->GetStringId(string_index)); + dex::StringIndex StringIndex() const { + return dex::StringIndex(index); } - const DexFile* dex_file; - dex::StringIndex string_index; -}; - -// Compare only the reference and not the string contents. -struct StringReferenceComparator { - bool operator()(const StringReference& a, const StringReference& b) const { - if (a.dex_file != b.dex_file) { - return a.dex_file < b.dex_file; - } - return a.string_index < b.string_index; + const char* GetStringData() const { + return dex_file->GetStringData(dex_file->GetStringId(StringIndex())); } }; // Compare the actual referenced string values. Used for string reference deduplication. struct StringReferenceValueComparator { - bool operator()(StringReference sr1, StringReference sr2) const { + bool operator()(const StringReference& sr1, const StringReference& sr2) const { // Note that we want to deduplicate identical strings even if they are referenced // by different dex files, so we need some (any) total ordering of strings, rather // than references. However, the references should usually be from the same dex file, @@ -60,10 +53,10 @@ struct StringReferenceValueComparator { if (sr1.dex_file == sr2.dex_file) { // Use the string order enforced by the dex file verifier. DCHECK_EQ( - sr1.string_index < sr2.string_index, + sr1.index < sr2.index, CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(sr1.GetStringData(), sr2.GetStringData()) < 0); - return sr1.string_index < sr2.string_index; + return sr1.index < sr2.index; } else { // Cannot compare indexes, so do the string comparison. return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues(sr1.GetStringData(), diff --git a/runtime/type_reference.h b/runtime/type_reference.h index c44019dde3..5ddc9d05d4 100644 --- a/runtime/type_reference.h +++ b/runtime/type_reference.h @@ -28,31 +28,23 @@ namespace art { class DexFile; // A type is located by its DexFile and the string_ids_ table index into that DexFile. -struct TypeReference { +class TypeReference : public DexFileReference { + public: TypeReference(const DexFile* file = nullptr, dex::TypeIndex index = dex::TypeIndex()) - : dex_file(file), - type_index(index) {} + : DexFileReference(file, index.index_) {} - const DexFile* dex_file; - dex::TypeIndex type_index; -}; - -struct TypeReferenceComparator { - bool operator()(TypeReference mr1, TypeReference mr2) const { - if (mr1.dex_file != mr2.dex_file) { - return mr1.dex_file < mr2.dex_file; - } - return mr1.type_index < mr2.type_index; + dex::TypeIndex TypeIndex() const { + return dex::TypeIndex(index); } }; // Compare the actual referenced type names. Used for type reference deduplication. struct TypeReferenceValueComparator { - bool operator()(TypeReference tr1, TypeReference tr2) const { + bool operator()(const TypeReference& tr1, const TypeReference& tr2) const { // Note that we want to deduplicate identical boot image types even if they are // referenced by different dex files, so we simply compare the descriptors. - StringReference sr1(tr1.dex_file, tr1.dex_file->GetTypeId(tr1.type_index).descriptor_idx_); - StringReference sr2(tr2.dex_file, tr2.dex_file->GetTypeId(tr2.type_index).descriptor_idx_); + StringReference sr1(tr1.dex_file, tr1.dex_file->GetTypeId(tr1.TypeIndex()).descriptor_idx_); + StringReference sr2(tr2.dex_file, tr2.dex_file->GetTypeId(tr2.TypeIndex()).descriptor_idx_); return StringReferenceValueComparator()(sr1, sr2); } }; |