summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc247
1 files changed, 41 insertions, 206 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b611aa2132..bbf06e1874 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -58,7 +58,6 @@
#include "gc/heap.h"
#include "gc/scoped_gc_critical_section.h"
#include "gc/space/image_space.h"
-#include "gc/space/space-inl.h"
#include "handle_scope-inl.h"
#include "image-inl.h"
#include "imt_conflict_table.h"
@@ -1147,35 +1146,6 @@ class VerifyClassInTableArtMethodVisitor : public ArtMethodVisitor {
ClassTable* const table_;
};
-class VerifyDirectInterfacesInTableClassVisitor {
- public:
- explicit VerifyDirectInterfacesInTableClassVisitor(ObjPtr<mirror::ClassLoader> class_loader)
- : class_loader_(class_loader), self_(Thread::Current()) { }
-
- bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
- if (!klass->IsPrimitive() && klass->GetClassLoader() == class_loader_) {
- classes_.push_back(klass);
- }
- return true;
- }
-
- void Check() const REQUIRES_SHARED(Locks::mutator_lock_) {
- for (ObjPtr<mirror::Class> klass : classes_) {
- for (uint32_t i = 0, num = klass->NumDirectInterfaces(); i != num; ++i) {
- CHECK(klass->GetDirectInterface(self_, klass, i) != nullptr)
- << klass->PrettyDescriptor() << " iface #" << i
- << klass->GetDexFile().StringByTypeIdx(klass->GetDirectInterfaceTypeIdx(i))
- << " Bug: 34839984";
- }
- }
- }
-
- private:
- ObjPtr<mirror::ClassLoader> class_loader_;
- Thread* self_;
- std::vector<ObjPtr<mirror::Class>> classes_;
-};
-
class VerifyDeclaringClassVisitor : public ArtMethodVisitor {
public:
VerifyDeclaringClassVisitor() REQUIRES_SHARED(Locks::mutator_lock_, Locks::heap_bitmap_lock_)
@@ -1207,23 +1177,6 @@ static void CopyNonNull(const T* src, size_t count, T* dst, const NullPred& pred
}
}
-template <typename T>
-static void CopyDexCachePairs(const std::atomic<mirror::DexCachePair<T>>* src,
- size_t count,
- std::atomic<mirror::DexCachePair<T>>* dst) {
- DCHECK_NE(count, 0u);
- DCHECK(!src[0].load(std::memory_order_relaxed).object.IsNull() ||
- src[0].load(std::memory_order_relaxed).index != 0u);
- for (size_t i = 0; i < count; ++i) {
- DCHECK_EQ(dst[i].load(std::memory_order_relaxed).index, 0u);
- DCHECK(dst[i].load(std::memory_order_relaxed).object.IsNull());
- mirror::DexCachePair<T> source = src[i].load(std::memory_order_relaxed);
- if (source.index != 0u || !source.object.IsNull()) {
- dst[i].store(source, std::memory_order_relaxed);
- }
- }
-}
-
bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
@@ -1277,10 +1230,7 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
if (dex_file->NumStringIds() < num_strings) {
num_strings = dex_file->NumStringIds();
}
- size_t num_types = mirror::DexCache::kDexCacheTypeCacheSize;
- if (dex_file->NumTypeIds() < num_types) {
- num_types = dex_file->NumTypeIds();
- }
+ const size_t num_types = dex_file->NumTypeIds();
const size_t num_methods = dex_file->NumMethodIds();
const size_t num_fields = dex_file->NumFieldIds();
size_t num_method_types = mirror::DexCache::kDexCacheMethodTypeCacheSize;
@@ -1300,14 +1250,28 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
mirror::StringDexCacheType* const image_resolved_strings = dex_cache->GetStrings();
mirror::StringDexCacheType* const strings =
reinterpret_cast<mirror::StringDexCacheType*>(raw_arrays + layout.StringsOffset());
- CopyDexCachePairs(image_resolved_strings, num_strings, strings);
+ for (size_t j = 0; j < num_strings; ++j) {
+ DCHECK_EQ(strings[j].load(std::memory_order_relaxed).index, 0u);
+ DCHECK(strings[j].load(std::memory_order_relaxed).object.IsNull());
+ strings[j].store(image_resolved_strings[j].load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+ }
+ mirror::StringDexCachePair::Initialize(strings);
dex_cache->SetStrings(strings);
}
if (num_types != 0u) {
- mirror::TypeDexCacheType* const image_resolved_types = dex_cache->GetResolvedTypes();
- mirror::TypeDexCacheType* const types =
- reinterpret_cast<mirror::TypeDexCacheType*>(raw_arrays + layout.TypesOffset());
- CopyDexCachePairs(image_resolved_types, num_types, types);
+ GcRoot<mirror::Class>* const image_resolved_types = dex_cache->GetResolvedTypes();
+ GcRoot<mirror::Class>* const types =
+ reinterpret_cast<GcRoot<mirror::Class>*>(raw_arrays + layout.TypesOffset());
+ for (size_t j = 0; kIsDebugBuild && j < num_types; ++j) {
+ DCHECK(types[j].IsNull());
+ }
+ CopyNonNull(image_resolved_types,
+ num_types,
+ types,
+ [](const GcRoot<mirror::Class>& elem) {
+ return elem.IsNull();
+ });
dex_cache->SetResolvedTypes(types);
}
if (num_methods != 0u) {
@@ -1348,7 +1312,15 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
mirror::MethodTypeDexCacheType* const method_types =
reinterpret_cast<mirror::MethodTypeDexCacheType*>(
raw_arrays + layout.MethodTypesOffset());
- CopyDexCachePairs(image_resolved_method_types, num_method_types, method_types);
+ for (size_t j = 0; j < num_method_types; ++j) {
+ DCHECK_EQ(method_types[j].load(std::memory_order_relaxed).index, 0u);
+ DCHECK(method_types[j].load(std::memory_order_relaxed).object.IsNull());
+ method_types[j].store(
+ image_resolved_method_types[j].load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+ }
+
+ mirror::MethodTypeDexCachePair::Initialize(method_types);
dex_cache->SetResolvedMethodTypes(method_types);
}
if (num_call_sites != 0u) {
@@ -1378,11 +1350,11 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
}
if (kIsDebugBuild) {
CHECK(new_class_set != nullptr);
- mirror::TypeDexCacheType* const types = dex_cache->GetResolvedTypes();
+ GcRoot<mirror::Class>* const types = dex_cache->GetResolvedTypes();
const size_t num_types = dex_cache->NumResolvedTypes();
- for (size_t j = 0; j != num_types; ++j) {
+ for (int32_t j = 0; j < static_cast<int32_t>(num_types); j++) {
// The image space is not yet added to the heap, avoid read barriers.
- ObjPtr<mirror::Class> klass = types[j].load(std::memory_order_relaxed).object.Read();
+ ObjPtr<mirror::Class> klass = types[j].Read();
if (space->HasAddress(klass.Ptr())) {
DCHECK(!klass->IsErroneous()) << klass->GetStatus();
auto it = new_class_set->Find(ClassTable::TableSlot(klass));
@@ -1741,9 +1713,9 @@ bool ClassLinker::AddImageSpace(
// The current dex file field is bogus, overwrite it so that we can get the dex file in the
// loop below.
dex_cache->SetDexFile(dex_file.get());
- mirror::TypeDexCacheType* const types = dex_cache->GetResolvedTypes();
+ GcRoot<mirror::Class>* const types = dex_cache->GetResolvedTypes();
for (int32_t j = 0, num_types = dex_cache->NumResolvedTypes(); j < num_types; j++) {
- ObjPtr<mirror::Class> klass = types[j].load(std::memory_order_relaxed).object.Read();
+ ObjPtr<mirror::Class> klass = types[j].Read();
if (klass != nullptr) {
DCHECK(!klass->IsErroneous()) << klass->GetStatus();
}
@@ -1914,12 +1886,6 @@ bool ClassLinker::AddImageSpace(
VerifyClassInTableArtMethodVisitor visitor2(class_table);
header.VisitPackedArtMethods(&visitor2, space->Begin(), kRuntimePointerSize);
}
- if (app_image) {
- // TODO: Restrict this check to debug builds. Bug: 34839984
- VerifyDirectInterfacesInTableClassVisitor visitor(class_loader.Get());
- class_table->Visit(visitor);
- visitor.Check();
- }
VLOG(class_linker) << "Adding image space took " << PrettyDuration(NanoTime() - start_time);
return true;
}
@@ -4538,108 +4504,6 @@ bool ClassLinker::CanWeInitializeClass(ObjPtr<mirror::Class> klass, bool can_ini
return CanWeInitializeClass(super_class, can_init_statics, can_init_parents);
}
-std::string DescribeSpace(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
- std::ostringstream oss;
- gc::Heap* heap = Runtime::Current()->GetHeap();
- gc::space::ContinuousSpace* cs = heap->FindContinuousSpaceFromAddress(klass.Ptr());
- if (cs != nullptr) {
- if (cs->IsImageSpace()) {
- oss << "image/" << cs->GetName() << "/" << cs->AsImageSpace()->GetImageFilename();
- } else {
- oss << "continuous/" << cs->GetName();
- }
- } else {
- gc::space::DiscontinuousSpace* ds =
- heap->FindDiscontinuousSpaceFromObject(klass, /* fail_ok */ true);
- if (ds != nullptr) {
- oss << "discontinuous/" << ds->GetName();
- } else {
- oss << "invalid";
- }
- }
- return oss.str();
-}
-
-std::string DescribeLoaders(ObjPtr<mirror::Class> klass, const char* iface_descriptor)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- std::ostringstream oss;
- uint32_t hash = ComputeModifiedUtf8Hash(iface_descriptor);
- ScopedObjectAccessUnchecked soa(Thread::Current());
- ObjPtr<mirror::Class> path_class_loader =
- soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader);
- ObjPtr<mirror::Class> dex_class_loader =
- soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_DexClassLoader);
-
- // Print the class loader chain.
- bool found_iface;
- const char* loader_separator = "";
- for (ObjPtr<mirror::ClassLoader> loader = klass->GetClassLoader();
- loader != nullptr;
- loader = loader->GetParent()) {
- oss << loader_separator << loader->GetClass()->PrettyDescriptor();
- loader_separator = ";";
- // If we didn't find the interface yet, try to find it in the current class loader.
- if (!found_iface) {
- ClassTable* table = Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(loader);
- ObjPtr<mirror::Class> iface =
- (table != nullptr) ? table->Lookup(iface_descriptor, hash) : nullptr;
- if (iface != nullptr) {
- found_iface = true;
- oss << "[hit:" << DescribeSpace(iface) << "]";
- }
- }
-
- // For PathClassLoader or DexClassLoader also dump the dex file locations.
- if (loader->GetClass() == path_class_loader || loader->GetClass() == dex_class_loader) {
- ArtField* const cookie_field =
- jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
- ArtField* const dex_file_field =
- jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
- ObjPtr<mirror::Object> dex_path_list =
- jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)->
- GetObject(loader);
- if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) {
- ObjPtr<mirror::Object> dex_elements_obj =
- jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
- GetObject(dex_path_list);
- if (dex_elements_obj != nullptr) {
- ObjPtr<mirror::ObjectArray<mirror::Object>> dex_elements =
- dex_elements_obj->AsObjectArray<mirror::Object>();
- oss << "(";
- const char* path_separator = "";
- for (int32_t i = 0; i != dex_elements->GetLength(); ++i) {
- ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i);
- ObjPtr<mirror::Object> dex_file =
- (element != nullptr) ? dex_file_field->GetObject(element) : nullptr;
- ObjPtr<mirror::LongArray> long_array =
- (dex_file != nullptr) ? cookie_field->GetObject(dex_file)->AsLongArray() : nullptr;
- if (long_array != nullptr) {
- int32_t long_array_size = long_array->GetLength();
- // First element is the oat file.
- for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) {
- const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(
- static_cast<uintptr_t>(long_array->GetWithoutChecks(j)));
- oss << path_separator << cp_dex_file->GetLocation();
- path_separator = ":";
- }
- }
- }
- oss << ")";
- }
- }
- }
- }
-
- // Do a paranoid check that the `klass` itself is in the class table.
- ClassTable* table =
- Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(klass->GetClassLoader());
- ObjPtr<mirror::Class> k = (table != nullptr) ? table->LookupByDescriptor(klass) : nullptr;
- if (k != klass) {
- oss << "{FAIL:" << k.Ptr() << "!=" << klass.Ptr() << "}";
- }
- return oss.str();
-}
-
bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
bool can_init_statics, bool can_init_parents) {
// see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
@@ -4787,15 +4651,7 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
MutableHandle<mirror::Class> handle_scope_iface(hs_iface.NewHandle<mirror::Class>(nullptr));
for (size_t i = 0; i < num_direct_interfaces; i++) {
handle_scope_iface.Assign(mirror::Class::GetDirectInterface(self, klass.Get(), i));
- if (UNLIKELY(handle_scope_iface == nullptr)) {
- const char* iface_descriptor =
- klass->GetDexFile().StringByTypeIdx(klass->GetDirectInterfaceTypeIdx(i));
- LOG(FATAL) << "Check failed: handle_scope_iface != nullptr "
- << "Debug data for bug 34839984: "
- << klass->PrettyDescriptor() << " iface #" << i << " " << iface_descriptor
- << " space: " << DescribeSpace(klass.Get())
- << " loaders: " << DescribeLoaders(klass.Get(), iface_descriptor);
- }
+ CHECK(handle_scope_iface != nullptr);
CHECK(handle_scope_iface->IsInterface());
if (handle_scope_iface->HasBeenRecursivelyInitialized()) {
// We have already done this for this interface. Skip it.
@@ -4931,15 +4787,7 @@ bool ClassLinker::InitializeDefaultInterfaceRecursive(Thread* self,
// First we initialize all of iface's super-interfaces recursively.
for (size_t i = 0; i < num_direct_ifaces; i++) {
ObjPtr<mirror::Class> super_iface = mirror::Class::GetDirectInterface(self, iface.Get(), i);
- if (UNLIKELY(super_iface == nullptr)) {
- const char* iface_descriptor =
- iface->GetDexFile().StringByTypeIdx(iface->GetDirectInterfaceTypeIdx(i));
- LOG(FATAL) << "Check failed: super_iface != nullptr "
- << "Debug data for bug 34839984: "
- << iface->PrettyDescriptor() << " iface #" << i << " " << iface_descriptor
- << " space: " << DescribeSpace(iface.Get())
- << " loaders: " << DescribeLoaders(iface.Get(), iface_descriptor);
- }
+ DCHECK(super_iface != nullptr);
if (!super_iface->HasBeenRecursivelyInitialized()) {
// Recursive step
handle_super_iface.Assign(super_iface);
@@ -7914,9 +7762,7 @@ mirror::String* ClassLinker::ResolveString(const DexFile& dex_file,
uint32_t utf16_length;
const char* utf8_data = dex_file.StringDataAndUtf16LengthByIdx(string_idx, &utf16_length);
ObjPtr<mirror::String> string = intern_table_->InternStrong(utf16_length, utf8_data);
- if (string != nullptr) {
- dex_cache->SetResolvedString(string_idx, string);
- }
+ dex_cache->SetResolvedString(string_idx, string);
return string.Ptr();
}
@@ -7957,16 +7803,11 @@ ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(const DexFile& dex_file,
// Find the class in the loaded classes table.
type = LookupClass(self, descriptor, hash, class_loader.Ptr());
}
- if (type != nullptr) {
- if (type->IsResolved()) {
- dex_cache->SetResolvedType(type_idx, type);
- } else {
- type = nullptr;
- }
- }
}
- DCHECK(type == nullptr || type->IsResolved());
- return type;
+ if (type != nullptr && type->IsResolved()) {
+ return type.Ptr();
+ }
+ return nullptr;
}
mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file,
@@ -7986,12 +7827,6 @@ mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file,
Thread::PoisonObjectPointersIfDebug();
ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
if (resolved == nullptr) {
- // TODO: Avoid this lookup as it duplicates work done in FindClass(). It is here
- // as a workaround for FastNative JNI to avoid AssertNoPendingException() when
- // trying to resolve annotations while an exception may be pending. Bug: 34659969
- resolved = LookupResolvedType(dex_file, type_idx, dex_cache.Get(), class_loader.Get());
- }
- if (resolved == nullptr) {
Thread* self = Thread::Current();
const char* descriptor = dex_file.StringByTypeIdx(type_idx);
resolved = FindClass(self, descriptor, class_loader);