diff options
| -rw-r--r-- | runtime/art_method-inl.h | 13 | ||||
| -rw-r--r-- | runtime/art_method.h | 15 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 54 | ||||
| -rw-r--r-- | runtime/class_linker.h | 10 | ||||
| -rw-r--r-- | runtime/jit/jit_code_cache.cc | 1 | ||||
| -rw-r--r-- | runtime/jit/jit_code_cache.h | 3 |
6 files changed, 73 insertions, 23 deletions
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index 9780522328..50e91447a9 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -388,8 +388,17 @@ inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(PointerSize pointer_size) if (LIKELY(!IsProxyMethod())) { return this; } - ArtMethod* interface_method = reinterpret_cast<ArtMethod*>(GetDataPtrSize(pointer_size)); - DCHECK(interface_method->GetDeclaringClass()->IsAssignableFrom(GetDeclaringClass())); + uint32_t method_index = GetDexMethodIndex(); + uint32_t slot_idx = method_index % mirror::DexCache::kDexCacheMethodCacheSize; + mirror::MethodDexCachePair pair = mirror::DexCache::GetNativePairPtrSize( + GetDexCacheResolvedMethods(pointer_size), slot_idx, pointer_size); + ArtMethod* interface_method = pair.GetObjectForIndex(method_index); + if (LIKELY(interface_method != nullptr)) { + DCHECK_EQ(interface_method, Runtime::Current()->GetClassLinker()->FindMethodForProxy(this)); + } else { + interface_method = Runtime::Current()->GetClassLinker()->FindMethodForProxy(this); + DCHECK(interface_method != nullptr); + } return interface_method; } diff --git a/runtime/art_method.h b/runtime/art_method.h index 7ffd585f1a..cac40e011a 100644 --- a/runtime/art_method.h +++ b/runtime/art_method.h @@ -458,15 +458,12 @@ class ArtMethod FINAL { SetDataPtrSize(table, pointer_size); } - ProfilingInfo* GetProfilingInfo(PointerSize pointer_size) REQUIRES_SHARED(Locks::mutator_lock_) { + ProfilingInfo* GetProfilingInfo(PointerSize pointer_size) { // Don't do a read barrier in the DCHECK, as GetProfilingInfo is called in places // where the declaring class is treated as a weak reference (accessing it with // a read barrier would either prevent unloading the class, or crash the runtime if // the GC wants to unload it). DCHECK(!IsNative<kWithoutReadBarrier>()); - if (UNLIKELY(IsProxyMethod())) { - return nullptr; - } return reinterpret_cast<ProfilingInfo*>(GetDataPtrSize(pointer_size)); } @@ -729,13 +726,9 @@ class ArtMethod FINAL { // Short cuts to declaring_class_->dex_cache_ member for fast compiled code access. mirror::MethodDexCacheType* dex_cache_resolved_methods_; - // Depending on the method type, the data is - // - native method: pointer to the JNI function registered to this method - // or a function to resolve the JNI function, - // - conflict method: ImtConflictTable, - // - abstract/interface method: the single-implementation if any, - // - proxy method: the original interface method or constructor, - // - other methods: the profiling data. + // Pointer to JNI function registered to this method, or a function to resolve the JNI function, + // or the profiling data for non-native methods, or an ImtConflictTable, or the + // single-implementation of an abstract/interface method. void* data_; // Method dispatch from quick compiled code invokes this pointer which may cause bridging into diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 0efc004b48..845bd6d5ff 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -3552,6 +3552,7 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, DexCacheData data; data.weak_root = dex_cache_jweak; data.dex_file = dex_cache->GetDexFile(); + data.resolved_methods = dex_cache->GetResolvedMethods(); data.class_table = ClassTableForClassLoader(class_loader); DCHECK(data.class_table != nullptr); // Make sure to hold the dex cache live in the class table. This case happens for the boot class @@ -4667,9 +4668,6 @@ void ClassLinker::CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* kAccPublic | kAccCompileDontBother); out->SetDeclaringClass(klass.Get()); - - // Set the original constructor method. - out->SetDataPtrSize(proxy_constructor, image_pointer_size_); } void ClassLinker::CheckProxyConstructor(ArtMethod* constructor) const { @@ -4710,9 +4708,6 @@ void ClassLinker::CreateProxyMethod(Handle<mirror::Class> klass, ArtMethod* prot // method they copy might (if it's a default method). out->SetCodeItemOffset(0); - // Set the original interface method. - out->SetDataPtrSize(prototype, image_pointer_size_); - // At runtime the method looks like a reference and argument saving method, clone the code // related parameters from this method. out->SetEntryPointFromQuickCompiledCode(GetQuickProxyInvokeHandler()); @@ -9036,6 +9031,53 @@ mirror::IfTable* ClassLinker::AllocIfTable(Thread* self, size_t ifcount) { ifcount * mirror::IfTable::kMax)); } +ArtMethod* ClassLinker::FindMethodForProxy(ArtMethod* proxy_method) { + DCHECK(proxy_method->IsProxyMethod()); + { + uint32_t method_index = proxy_method->GetDexMethodIndex(); + PointerSize pointer_size = image_pointer_size_; + Thread* const self = Thread::Current(); + ReaderMutexLock mu(self, *Locks::dex_lock_); + // Locate the dex cache of the original interface/Object + for (const DexCacheData& data : dex_caches_) { + if (!self->IsJWeakCleared(data.weak_root) && + proxy_method->HasSameDexCacheResolvedMethods(data.resolved_methods, pointer_size)) { + ObjPtr<mirror::DexCache> dex_cache = + ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root)); + if (dex_cache != nullptr) { + // Lookup up the method. Instead of going through LookupResolvedMethod() + // and thus LookupResolvedType(), use the ClassTable from the DexCacheData. + ArtMethod* resolved_method = dex_cache->GetResolvedMethod(method_index, pointer_size); + if (resolved_method == nullptr) { + const DexFile::MethodId& method_id = data.dex_file->GetMethodId(method_index); + ObjPtr<mirror::Class> klass = dex_cache->GetResolvedType(method_id.class_idx_); + if (klass == nullptr) { + const char* descriptor = data.dex_file->StringByTypeIdx(method_id.class_idx_); + klass = data.class_table->Lookup(descriptor, ComputeModifiedUtf8Hash(descriptor)); + DCHECK(klass != nullptr); + dex_cache->SetResolvedType(method_id.class_idx_, klass); + } + if (klass->IsInterface()) { + resolved_method = klass->FindInterfaceMethod(dex_cache, method_index, pointer_size); + } else { + DCHECK( + klass == WellKnownClasses::ToClass(WellKnownClasses::java_lang_reflect_Proxy) || + klass == WellKnownClasses::ToClass(WellKnownClasses::java_lang_Object)); + resolved_method = klass->FindClassMethod(dex_cache, method_index, pointer_size); + } + CHECK(resolved_method != nullptr); + dex_cache->SetResolvedMethod(method_index, resolved_method, pointer_size); + } + return resolved_method; + } + } + } + } + // Note: Do not use proxy_method->PrettyMethod() as it can call back here. + LOG(FATAL) << "Didn't find dex cache for " << proxy_method->GetDeclaringClass()->PrettyClass(); + UNREACHABLE(); +} + // Instantiate ResolveMethod. template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>( const DexFile& dex_file, diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 783ec745cf..66bcbe091f 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -479,6 +479,9 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_); std::string GetDescriptorForProxy(ObjPtr<mirror::Class> proxy_class) REQUIRES_SHARED(Locks::mutator_lock_); + ArtMethod* FindMethodForProxy(ArtMethod* proxy_method) + REQUIRES(!Locks::dex_lock_) + REQUIRES_SHARED(Locks::mutator_lock_); // Get the oat code for a method when its class isn't yet initialized. const void* GetQuickOatCodeFor(ArtMethod* method) @@ -672,6 +675,7 @@ class ClassLinker { DexCacheData() : weak_root(nullptr), dex_file(nullptr), + resolved_methods(nullptr), class_table(nullptr) { } // Check if the data is valid. @@ -682,9 +686,11 @@ class ClassLinker { // Weak root to the DexCache. Note: Do not decode this unnecessarily or else class unloading may // not work properly. jweak weak_root; - // The following field caches the DexCache's field here to avoid unnecessary jweak decode that - // triggers read barriers (and marks them alive unnecessarily and messes with class unloading.) + // The following two fields are caches to the DexCache's fields and here to avoid unnecessary + // jweak decode that triggers read barriers (and mark them alive unnecessarily and mess with + // class unloading.) const DexFile* dex_file; + mirror::MethodDexCacheType* resolved_methods; // Identify the associated class loader's class table. This is used to make sure that // the Java call to native DexCache.setResolvedType() inserts the resolved type in that // class table. It is also used to make sure we don't register the same dex cache with diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index 40a5212629..47ace7fa71 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -1169,6 +1169,7 @@ void JitCodeCache::DoCollection(Thread* self, bool collect_profiling_info) { RemoveUnmarkedCode(self); if (collect_profiling_info) { + ScopedThreadSuspension sts(self, kSuspended); MutexLock mu(self, lock_); // Free all profiling infos of methods not compiled nor being compiled. auto profiling_kept_end = std::remove_if(profiling_infos_.begin(), profiling_infos_.end(), diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h index 9790e3aa43..daa1d616a6 100644 --- a/runtime/jit/jit_code_cache.h +++ b/runtime/jit/jit_code_cache.h @@ -323,8 +323,7 @@ class JitCodeCache { REQUIRES_SHARED(Locks::mutator_lock_); bool CheckLiveCompiledCodeHasProfilingInfo() - REQUIRES(lock_) - REQUIRES_SHARED(Locks::mutator_lock_); + REQUIRES(lock_); void FreeCode(uint8_t* code) REQUIRES(lock_); uint8_t* AllocateCode(size_t code_size) REQUIRES(lock_); |