summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/class_linker-inl.h11
-rw-r--r--runtime/mirror/dex_cache-inl.h12
-rw-r--r--runtime/mirror/dex_cache.cc41
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, &current_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(), &current_field);
+ }
+ for (ArtField& current_field : resolved->GetIFields()) {
+ resolved_fields->Set(current_field.GetDexFieldIndex(), &current_field);
+ }
+ }
+ }
+}
+
} // namespace mirror
} // namespace art