diff options
-rw-r--r-- | runtime/class_linker-inl.h | 11 | ||||
-rw-r--r-- | runtime/mirror/dex_cache-inl.h | 12 | ||||
-rw-r--r-- | runtime/mirror/dex_cache.cc | 41 |
3 files changed, 52 insertions, 12 deletions
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index b79f3f5685..8f3692dd39 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -476,6 +476,11 @@ inline ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx, DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; } + // Look for the method again in case the type resolution updated the cache. + resolved = dex_cache->GetResolvedMethod(method_idx); + if (kResolveMode == ResolveMode::kNoChecks && resolved != nullptr) { + return resolved; + } } // Check if the invoke type matches the class type. @@ -584,6 +589,12 @@ inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, return nullptr; } + // Look for the field again in case the type resolution updated the cache. + resolved = dex_cache->GetResolvedField(field_idx); + if (resolved != nullptr) { + return resolved; + } + resolved = FindResolvedField(klass, dex_cache.Get(), class_loader.Get(), field_idx, is_static); if (resolved == nullptr) { const char* name = dex_file.GetFieldName(field_id); diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h index 5a44fff665..3452f17d70 100644 --- a/runtime/mirror/dex_cache-inl.h +++ b/runtime/mirror/dex_cache-inl.h @@ -164,18 +164,6 @@ inline Class* DexCache::GetResolvedType(dex::TypeIndex type_idx) { return GetResolvedTypesEntry(type_idx.index_); } -inline void DexCache::SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved) { - DCHECK(resolved != nullptr); - DCHECK(resolved->IsResolved()) << resolved->GetStatus(); - // TODO default transaction support. - // Use a release store for SetResolvedType. This is done to prevent other threads from seeing a - // class but not necessarily seeing the loaded members like the static fields array. - // See b/32075261. - SetResolvedTypesEntry(type_idx.index_, resolved.Ptr()); - // TODO: Fine-grained marking, so that we don't need to go through all arrays in full. - WriteBarrier::ForEveryFieldWrite(this); -} - inline void DexCache::ClearResolvedType(dex::TypeIndex type_idx) { DCHECK(Runtime::Current()->IsAotCompiler()); auto* array = GetResolvedTypesArray(); diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index 5e6138c9c6..b0b60126d8 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -215,5 +215,46 @@ void DexCache::UnlinkStartupCaches() { UnlinkResolvedMethodTypesArrayIfStartup(); } +void DexCache::SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved) { + DCHECK(resolved != nullptr); + DCHECK(resolved->IsResolved()) << resolved->GetStatus(); + // TODO default transaction support. + // Use a release store for SetResolvedType. This is done to prevent other threads from seeing a + // class but not necessarily seeing the loaded members like the static fields array. + // See b/32075261. + SetResolvedTypesEntry(type_idx.index_, resolved.Ptr()); + // TODO: Fine-grained marking, so that we don't need to go through all arrays in full. + WriteBarrier::ForEveryFieldWrite(this); + + if (this == resolved->GetDexCache()) { + // If we're updating the dex cache of the class, optimistically update the cache for methods and + // fields if the caches are full arrays. + auto* resolved_methods = GetResolvedMethodsArray(); + if (resolved_methods != nullptr) { + PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); + // Because there could be duplicate method entries, we make sure we only + // update the cache with the first one found to be consistent with method + // resolution. + uint32_t previous_method_index = dex::kDexNoIndex; + for (ArtMethod& current_method : resolved->GetDeclaredMethods(pointer_size)) { + uint32_t new_index = current_method.GetDexMethodIndex(); + if (new_index != previous_method_index) { + resolved_methods->Set(new_index, ¤t_method); + previous_method_index = new_index; + } + } + } + auto* resolved_fields = GetResolvedFieldsArray(); + if (resolved_fields != nullptr) { + for (ArtField& current_field : resolved->GetSFields()) { + resolved_fields->Set(current_field.GetDexFieldIndex(), ¤t_field); + } + for (ArtField& current_field : resolved->GetIFields()) { + resolved_fields->Set(current_field.GetDexFieldIndex(), ¤t_field); + } + } + } +} + } // namespace mirror } // namespace art |