diff options
author | 2017-12-11 18:37:36 +0000 | |
---|---|---|
committer | 2017-12-12 13:48:02 +0000 | |
commit | 666ee3d7c6039c80e75287e311895bd6a9b01e9f (patch) | |
tree | 5e65f39ff7cc83af4be3b691c247d7348052f854 /runtime/class_linker-inl.h | |
parent | 890111968fbd3f5ae528d97e42984c12a3dd27bd (diff) |
Do not pass DexFile to ClassLinker::Lookup/ResolveType().
The DexFile can be easily retrieved from the DexCache,
so reduce the number of arguments that need to be passed.
Also refactor the code to avoid doing the DexCache lookup
twice and avoid unnecessary read barriers in the initial
DexCache lookup (also for Lookup/ResolveField()).
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: Idea9aa42b6a5bade947e93e330b1abdb9d11b2da
Diffstat (limited to 'runtime/class_linker-inl.h')
-rw-r--r-- | runtime/class_linker-inl.h | 116 |
1 files changed, 92 insertions, 24 deletions
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index c086dd2676..4b317f886f 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -61,16 +61,27 @@ inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, return array_class.Ptr(); } -inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType( - dex::TypeIndex type_idx, - ObjPtr<mirror::DexCache> dex_cache, - ObjPtr<mirror::ClassLoader> class_loader) { - ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx); - if (type == nullptr) { - type = Runtime::Current()->GetClassLinker()->LookupResolvedType( - *dex_cache->GetDexFile(), type_idx, dex_cache, class_loader); +inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx, + ObjPtr<mirror::Class> referrer) { + if (kObjPtrPoisoning) { + StackHandleScope<1> hs(Thread::Current()); + HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer); + Thread::Current()->PoisonObjectPointers(); } - return type; + if (kIsDebugBuild) { + Thread::Current()->AssertNoPendingException(); + } + // We do not need the read barrier for getting the DexCache for the initial resolved type + // lookup as both from-space and to-space copies point to the same native resolved types array. + ObjPtr<mirror::Class> resolved_type = + referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx); + if (resolved_type == nullptr) { + StackHandleScope<2> hs(Thread::Current()); + Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader())); + resolved_type = DoResolveType(type_idx, h_dex_cache, class_loader); + } + return resolved_type; } inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx, @@ -79,18 +90,67 @@ inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx, if (kIsDebugBuild) { Thread::Current()->AssertNoPendingException(); } - ObjPtr<mirror::Class> resolved_type = referrer->GetDexCache()->GetResolvedType(type_idx); + // We do not need the read barrier for getting the DexCache for the initial resolved type + // lookup as both from-space and to-space copies point to the same native resolved types array. + ObjPtr<mirror::Class> resolved_type = + referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx); if (UNLIKELY(resolved_type == nullptr)) { StackHandleScope<2> hs(Thread::Current()); - ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass(); + ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass(); Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader())); - const DexFile& dex_file = *dex_cache->GetDexFile(); - resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader())); + resolved_type = DoResolveType(type_idx, dex_cache, class_loader); } return resolved_type; } +inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx, + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader) { + DCHECK(dex_cache != nullptr); + Thread::PoisonObjectPointersIfDebug(); + ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx); + if (resolved == nullptr) { + resolved = DoResolveType(type_idx, dex_cache, class_loader); + } + return resolved; +} + +inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx, + ObjPtr<mirror::Class> referrer) { + // We do not need the read barrier for getting the DexCache for the initial resolved type + // lookup as both from-space and to-space copies point to the same native resolved types array. + ObjPtr<mirror::Class> type = + referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader()); + } + return type; +} + +inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx, + ArtMethod* referrer) { + // We do not need the read barrier for getting the DexCache for the initial resolved type + // lookup as both from-space and to-space copies point to the same native resolved types array. + ObjPtr<mirror::Class> type = + referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader()); + } + return type; +} + +inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType( + dex::TypeIndex type_idx, + ObjPtr<mirror::DexCache> dex_cache, + ObjPtr<mirror::ClassLoader> class_loader) { + ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx); + if (type == nullptr) { + type = DoLookupResolvedType(type_idx, dex_cache, class_loader); + } + return type; +} + template <bool kThrowOnError, typename ClassGetter> inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache, InvokeType type, @@ -148,10 +208,9 @@ inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_c dex_cache, type, [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) { - const DexFile& dex_file = *dex_cache->GetDexFile(); - const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx); + const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx); ObjPtr<mirror::Class> klass = - LookupResolvedType(dex_file, method_id.class_idx_, dex_cache, class_loader); + LookupResolvedType(method_id.class_idx_, dex_cache, class_loader); DCHECK(klass != nullptr); return klass; }); @@ -187,6 +246,8 @@ inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* // lookup in the context of the original method from where it steals the code. // However, we delay the GetInterfaceMethodIfProxy() until needed. DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor()); + // We do not need the read barrier for getting the DexCache for the initial resolved method + // lookup as both from-space and to-space copies point to the same native resolved methods array. ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod( method_idx, image_pointer_size_); if (resolved_method == nullptr) { @@ -228,6 +289,8 @@ inline ArtMethod* ClassLinker::ResolveMethod(Thread* self, // However, we delay the GetInterfaceMethodIfProxy() until needed. DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor()); Thread::PoisonObjectPointersIfDebug(); + // We do not need the read barrier for getting the DexCache for the initial resolved method + // lookup as both from-space and to-space copies point to the same native resolved methods array. ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod( method_idx, image_pointer_size_); DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod()); @@ -278,10 +341,13 @@ inline ArtMethod* ClassLinker::ResolveMethod(Thread* self, inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx, ArtMethod* referrer, bool is_static) { - ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache(); - ArtField* field = dex_cache->GetResolvedField(field_idx, image_pointer_size_); + // We do not need the read barrier for getting the DexCache for the initial resolved field + // lookup as both from-space and to-space copies point to the same native resolved fields array. + ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField( + field_idx, image_pointer_size_); if (field == nullptr) { - field = LookupResolvedField(field_idx, dex_cache, referrer->GetClassLoader(), is_static); + ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader(); + field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static); } return field; } @@ -290,13 +356,15 @@ inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, ArtMethod* referrer, bool is_static) { Thread::PoisonObjectPointersIfDebug(); - ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass(); - ArtField* resolved_field = - referrer->GetDexCache()->GetResolvedField(field_idx, image_pointer_size_); + // We do not need the read barrier for getting the DexCache for the initial resolved field + // lookup as both from-space and to-space copies point to the same native resolved fields array. + ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField( + field_idx, image_pointer_size_); if (UNLIKELY(resolved_field == nullptr)) { StackHandleScope<2> hs(Thread::Current()); + ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass(); Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader())); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader())); resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static); // Note: We cannot check here to see whether we added the field to the cache. The type // might be an erroneous class, which results in it being hidden from us. |