Merge "Change dex caches to be weak roots"
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index 80387f2..83f391d 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -31,7 +31,7 @@
namespace art {
inline mirror::DexCache* CompilerDriver::GetDexCache(const DexCompilationUnit* mUnit) {
- return mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile());
+ return mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false);
}
inline mirror::ClassLoader* CompilerDriver::GetClassLoader(ScopedObjectAccess& soa,
@@ -87,7 +87,7 @@
}
inline mirror::DexCache* CompilerDriver::FindDexCache(const DexFile* dex_file) {
- return Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file);
+ return Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file, false);
}
inline ArtField* CompilerDriver::ResolveField(
@@ -339,7 +339,7 @@
// Sharpen a virtual call into a direct call. The method_idx is into referrer's
// dex cache, check that this resolved method is where we expect it.
CHECK_EQ(target_method->dex_file, mUnit->GetDexFile());
- DCHECK_EQ(dex_cache.Get(), mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()));
+ DCHECK_EQ(dex_cache.Get(), mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false));
CHECK_EQ(referrer_class->GetDexCache()->GetResolvedMethod(
target_method->dex_method_index, pointer_size),
resolved_method) << PrettyMethod(resolved_method);
@@ -369,7 +369,7 @@
nullptr, kVirtual);
} else {
StackHandleScope<1> hs(soa.Self());
- auto target_dex_cache(hs.NewHandle(class_linker->FindDexCache(*devirt_target->dex_file)));
+ auto target_dex_cache(hs.NewHandle(class_linker->RegisterDexFile(*devirt_target->dex_file)));
called_method = class_linker->ResolveMethod(
*devirt_target->dex_file, devirt_target->dex_method_index, target_dex_cache,
class_loader, nullptr, kVirtual);
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index fa25a17..d38677e 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -936,7 +936,7 @@
uint16_t exception_type_idx = exception_type.first;
const DexFile* dex_file = exception_type.second;
StackHandleScope<2> hs2(self);
- Handle<mirror::DexCache> dex_cache(hs2.NewHandle(class_linker->FindDexCache(*dex_file)));
+ Handle<mirror::DexCache> dex_cache(hs2.NewHandle(class_linker->RegisterDexFile(*dex_file)));
Handle<mirror::Class> klass(hs2.NewHandle(
class_linker->ResolveType(*dex_file, exception_type_idx, dex_cache,
NullHandle<mirror::ClassLoader>())));
@@ -1170,7 +1170,8 @@
IsImageClass(dex_file.StringDataByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) {
{
ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
+ mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(
+ dex_file, false);
mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class == nullptr) {
// Erroneous class.
@@ -1195,9 +1196,9 @@
// We resolve all const-string strings when building for the image.
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::DexCache> dex_cache(
- hs.NewHandle(Runtime::Current()->GetClassLinker()->FindDexCache(dex_file)));
- Runtime::Current()->GetClassLinker()->ResolveString(dex_file, string_idx, dex_cache);
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file, false)));
+ class_linker->ResolveString(dex_file, string_idx, dex_cache);
result = true;
}
if (result) {
@@ -1222,7 +1223,7 @@
*equals_referrers_class = false;
}
ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
+ mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file, false);
// Get type from dex cache assuming it was populated by the verifier
mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class == nullptr) {
@@ -1259,7 +1260,8 @@
const DexFile& dex_file,
uint32_t type_idx) {
ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
+ mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(
+ dex_file, false);
// Get type from dex cache assuming it was populated by the verifier.
mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class == nullptr) {
@@ -1288,7 +1290,7 @@
uintptr_t* direct_type_ptr, bool* out_is_finalizable) {
ScopedObjectAccess soa(Thread::Current());
Runtime* runtime = Runtime::Current();
- mirror::DexCache* dex_cache = runtime->GetClassLinker()->FindDexCache(dex_file);
+ mirror::DexCache* dex_cache = runtime->GetClassLinker()->FindDexCache(dex_file, false);
mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class == nullptr) {
return false;
@@ -1417,7 +1419,7 @@
{
StackHandleScope<2> hs(soa.Self());
Handle<mirror::DexCache> dex_cache_handle(
- hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
+ hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false)));
Handle<mirror::ClassLoader> class_loader_handle(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
resolved_field =
@@ -1467,7 +1469,7 @@
{
StackHandleScope<2> hs(soa.Self());
Handle<mirror::DexCache> dex_cache_handle(
- hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
+ hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false)));
Handle<mirror::ClassLoader> class_loader_handle(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
resolved_field =
@@ -1653,7 +1655,7 @@
// Try to resolve the method and compiling method's class.
StackHandleScope<3> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(
- hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
+ hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false)));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
uint32_t method_idx = target_method->dex_method_index;
@@ -1905,7 +1907,7 @@
StackHandleScope<2> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file)));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file, false)));
// Resolve the class.
mirror::Class* klass = class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache,
class_loader);
@@ -1998,7 +2000,7 @@
ClassLinker* class_linker = manager_->GetClassLinker();
const DexFile& dex_file = *manager_->GetDexFile();
StackHandleScope<2> hs(soa.Self());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file)));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->RegisterDexFile(dex_file)));
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(manager_->GetClassLoader())));
mirror::Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
@@ -2084,7 +2086,7 @@
* This is to ensure the class is structurally sound for compilation. An unsound class
* will be rejected by the verifier and later skipped during compilation in the compiler.
*/
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file)));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file, false)));
std::string error_msg;
if (verifier::MethodVerifier::VerifyClass(soa.Self(), &dex_file, dex_cache, class_loader,
&class_def, true, &error_msg) ==
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 93897aa..dbd3366 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -70,7 +70,6 @@
// Separate objects into multiple bins to optimize dirty memory use.
static constexpr bool kBinObjects = true;
-static constexpr bool kComputeEagerResolvedStrings = false;
static void CheckNoDexObjectsCallback(Object* obj, void* arg ATTRIBUTE_UNUSED)
SHARED_REQUIRES(Locks::mutator_lock_) {
@@ -90,11 +89,6 @@
PruneNonImageClasses(); // Remove junk
ComputeLazyFieldsForImageClasses(); // Add useful information
- // Calling this can in theory fill in some resolved strings. However, in practice it seems to
- // never resolve any.
- if (kComputeEagerResolvedStrings) {
- ComputeEagerResolvedStrings();
- }
Thread::Current()->TransitionFromRunnableToSuspended(kNative);
}
gc::Heap* heap = Runtime::Current()->GetHeap();
@@ -302,11 +296,15 @@
void ImageWriter::PrepareDexCacheArraySlots() {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock());
- size_t dex_cache_count = class_linker->GetDexCacheCount();
+ Thread* const self = Thread::Current();
+ ReaderMutexLock mu(self, *class_linker->DexLock());
uint32_t size = 0u;
- for (size_t idx = 0; idx < dex_cache_count; ++idx) {
- DexCache* dex_cache = class_linker->GetDexCache(idx);
+ for (jobject weak_root : class_linker->GetDexCaches()) {
+ mirror::DexCache* dex_cache =
+ down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root));
+ if (dex_cache == nullptr) {
+ continue;
+ }
const DexFile* dex_file = dex_cache->GetDexFile();
dex_cache_array_starts_.Put(dex_file, size);
DexCacheArraysLayout layout(target_ptr_size_, dex_file);
@@ -554,39 +552,6 @@
class_linker->VisitClassesWithoutClassesLock(&visitor);
}
-void ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg ATTRIBUTE_UNUSED) {
- if (!obj->GetClass()->IsStringClass()) {
- return;
- }
- mirror::String* string = obj->AsString();
- const uint16_t* utf16_string = string->GetValue();
- size_t utf16_length = static_cast<size_t>(string->GetLength());
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock());
- size_t dex_cache_count = class_linker->GetDexCacheCount();
- for (size_t i = 0; i < dex_cache_count; ++i) {
- DexCache* dex_cache = class_linker->GetDexCache(i);
- const DexFile& dex_file = *dex_cache->GetDexFile();
- const DexFile::StringId* string_id;
- if (UNLIKELY(utf16_length == 0)) {
- string_id = dex_file.FindStringId("");
- } else {
- string_id = dex_file.FindStringId(utf16_string, utf16_length);
- }
- if (string_id != nullptr) {
- // This string occurs in this dex file, assign the dex cache entry.
- uint32_t string_idx = dex_file.GetIndexForStringId(*string_id);
- if (dex_cache->GetResolvedString(string_idx) == nullptr) {
- dex_cache->SetResolvedString(string_idx, string);
- }
- }
- }
-}
-
-void ImageWriter::ComputeEagerResolvedStrings() {
- Runtime::Current()->GetHeap()->VisitObjects(ComputeEagerResolvedStringsCallback, this);
-}
-
bool ImageWriter::IsImageClass(Class* klass) {
if (klass == nullptr) {
return false;
@@ -631,16 +596,14 @@
// Clear references to removed classes from the DexCaches.
const ArtMethod* resolution_method = runtime->GetResolutionMethod();
- size_t dex_cache_count;
- {
- ReaderMutexLock mu(self, *class_linker->DexLock());
- dex_cache_count = class_linker->GetDexCacheCount();
- }
- for (size_t idx = 0; idx < dex_cache_count; ++idx) {
- DexCache* dex_cache;
- {
- ReaderMutexLock mu(self, *class_linker->DexLock());
- dex_cache = class_linker->GetDexCache(idx);
+
+ ScopedAssertNoThreadSuspension sa(self, __FUNCTION__);
+ ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); // For ClassInClassTable
+ ReaderMutexLock mu2(self, *class_linker->DexLock());
+ for (jobject weak_root : class_linker->GetDexCaches()) {
+ mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root));
+ if (dex_cache == nullptr) {
+ continue;
}
for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
Class* klass = dex_cache->GetResolvedType(i);
@@ -762,8 +725,12 @@
ReaderMutexLock mu(self, *class_linker->DexLock());
CHECK_EQ(dex_cache_count, class_linker->GetDexCacheCount())
<< "The number of dex caches changed.";
- for (size_t i = 0; i < dex_cache_count; ++i) {
- dex_caches->Set<false>(i, class_linker->GetDexCache(i));
+ size_t i = 0;
+ for (jobject weak_root : class_linker->GetDexCaches()) {
+ mirror::DexCache* dex_cache =
+ down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root));
+ dex_caches->Set<false>(i, dex_cache);
+ ++i;
}
}
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index c8aa82d..778521c 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -225,11 +225,6 @@
void ComputeLazyFieldsForImageClasses()
SHARED_REQUIRES(Locks::mutator_lock_);
- // Wire dex cache resolved strings to strings in the image to avoid runtime resolution.
- void ComputeEagerResolvedStrings() SHARED_REQUIRES(Locks::mutator_lock_);
- static void ComputeEagerResolvedStringsCallback(mirror::Object* obj, void* arg)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
// Remove unwanted classes from various roots.
void PruneNonImageClasses() SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 64e7487..0e0b224 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -691,6 +691,8 @@
OatClass* oat_class = writer_->oat_classes_[oat_class_index_];
const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
+ // No thread suspension since dex_cache_ that may get invalidated if that occurs.
+ ScopedAssertNoThreadSuspension tsc(Thread::Current(), __FUNCTION__);
if (compiled_method != nullptr) { // ie. not an abstract method
size_t file_offset = file_offset_;
OutputStream* out = out_;
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 97b9972..824f28e 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -362,7 +362,7 @@
if (kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current());
ClassLinker* cl = Runtime::Current()->GetClassLinker();
- mirror::DexCache* dex_cache = cl->FindDexCache(instr->AsInvoke()->GetDexFile());
+ mirror::DexCache* dex_cache = cl->FindDexCache(instr->AsInvoke()->GetDexFile(), false);
ArtMethod* method = dex_cache->GetResolvedMethod(
instr->AsInvoke()->GetDexMethodIndex(), cl->GetImagePointerSize());
DCHECK(method != nullptr);
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 99736e9..07cf88c 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1207,6 +1207,14 @@
oat_file_.reset();
}
+ void Shutdown() {
+ ScopedObjectAccess soa(Thread::Current());
+ for (jobject dex_cache : dex_caches_) {
+ soa.Env()->DeleteLocalRef(dex_cache);
+ }
+ dex_caches_.clear();
+ }
+
// Set up the environment for compilation. Includes starting the runtime and loading/opening the
// boot class path.
bool Setup() {
@@ -1320,8 +1328,9 @@
compiled_methods_.reset(nullptr); // By default compile everything.
}
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
if (boot_image_option_.empty()) {
- dex_files_ = Runtime::Current()->GetClassLinker()->GetBootClassPath();
+ dex_files_ = class_linker->GetBootClassPath();
} else {
if (dex_filenames_.empty()) {
ATRACE_BEGIN("Opening zip archive from file descriptor");
@@ -1374,11 +1383,15 @@
}
}
}
- // Ensure opened dex files are writable for dex-to-dex transformations.
+ // Ensure opened dex files are writable for dex-to-dex transformations. Also ensure that
+ // the dex caches stay live since we don't want class unloading to occur during compilation.
for (const auto& dex_file : dex_files_) {
if (!dex_file->EnableWrite()) {
PLOG(ERROR) << "Failed to make .dex file writeable '" << dex_file->GetLocation() << "'\n";
}
+ ScopedObjectAccess soa(self);
+ dex_caches_.push_back(soa.AddLocalReference<jobject>(
+ class_linker->RegisterDexFile(*dex_file)));
}
// If we use a swap file, ensure we are above the threshold to make it necessary.
@@ -1423,6 +1436,7 @@
// Handle and ClassLoader creation needs to come after Runtime::Create
jobject class_loader = nullptr;
Thread* self = Thread::Current();
+
if (!boot_image_option_.empty()) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
OpenClassPathFiles(runtime_->GetClassPathString(), dex_files_, &class_path_files_);
@@ -1957,6 +1971,7 @@
bool is_host_;
std::string android_root_;
std::vector<const DexFile*> dex_files_;
+ std::vector<jobject> dex_caches_;
std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
std::unique_ptr<CompilerDriver> driver_;
std::vector<std::string> verbose_methods_;
@@ -2107,11 +2122,15 @@
return EXIT_FAILURE;
}
+ bool result;
if (dex2oat.IsImage()) {
- return CompileImage(dex2oat);
+ result = CompileImage(dex2oat);
} else {
- return CompileApp(dex2oat);
+ result = CompileApp(dex2oat);
}
+
+ dex2oat.Shutdown();
+ return result;
}
} // namespace art
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 44b78ff..1950d56 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -812,11 +812,15 @@
DumpDexCode(vios->Stream(), dex_file, code_item);
}
+ std::unique_ptr<StackHandleScope<1>> hs;
std::unique_ptr<verifier::MethodVerifier> verifier;
if (Runtime::Current() != nullptr) {
+ // We need to have the handle scope stay live until after the verifier since the verifier has
+ // a handle to the dex cache from hs.
+ hs.reset(new StackHandleScope<1>(Thread::Current()));
vios->Stream() << "VERIFIER TYPE ANALYSIS:\n";
ScopedIndentation indent2(vios);
- verifier.reset(DumpVerifier(vios,
+ verifier.reset(DumpVerifier(vios, hs.get(),
dex_method_idx, &dex_file, class_def, code_item,
method_access_flags));
}
@@ -1389,6 +1393,7 @@
}
verifier::MethodVerifier* DumpVerifier(VariableIndentationOutputStream* vios,
+ StackHandleScope<1>* hs,
uint32_t dex_method_idx,
const DexFile* dex_file,
const DexFile::ClassDef& class_def,
@@ -1396,9 +1401,8 @@
uint32_t method_access_flags) {
if ((method_access_flags & kAccNative) == 0) {
ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(
- hs.NewHandle(Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file)));
+ hs->NewHandle(Runtime::Current()->GetClassLinker()->RegisterDexFile(*dex_file)));
DCHECK(options_.class_loader_ != nullptr);
return verifier::MethodVerifier::VerifyMethodAndDump(
soa.Self(), vios, dex_method_idx, dex_file, dex_cache, *options_.class_loader_,
@@ -1599,10 +1603,13 @@
dex_cache_arrays_.clear();
{
ReaderMutexLock mu(self, *class_linker->DexLock());
- for (size_t i = 0; i < class_linker->GetDexCacheCount(); ++i) {
- auto* dex_cache = class_linker->GetDexCache(i);
- dex_cache_arrays_.insert(dex_cache->GetResolvedFields());
- dex_cache_arrays_.insert(dex_cache->GetResolvedMethods());
+ for (jobject weak_root : class_linker->GetDexCaches()) {
+ mirror::DexCache* dex_cache =
+ down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root));
+ if (dex_cache != nullptr) {
+ dex_cache_arrays_.insert(dex_cache->GetResolvedFields());
+ dex_cache_arrays_.insert(dex_cache->GetResolvedMethods());
+ }
}
}
ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 848c904..5f2caef 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -64,6 +64,7 @@
kJdwpSocketLock,
kRegionSpaceRegionLock,
kTransactionLogLock,
+ kJniWeakGlobalsLock,
kReferenceQueueSoftReferencesLock,
kReferenceQueuePhantomReferencesLock,
kReferenceQueueFinalizerReferencesLock,
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 11901b3..d2dbff6 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -195,12 +195,6 @@
return klass;
}
-inline mirror::DexCache* ClassLinker::GetDexCache(size_t idx) {
- dex_lock_.AssertSharedHeld(Thread::Current());
- DCHECK(idx < dex_caches_.size());
- return dex_caches_[idx].Read();
-}
-
} // namespace art
#endif // ART_RUNTIME_CLASS_LINKER_INL_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b074dec..3b505e6 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -273,7 +273,6 @@
array_iftable_(nullptr),
find_array_class_cache_next_victim_(0),
init_done_(false),
- log_new_dex_caches_roots_(false),
log_new_class_table_roots_(false),
intern_table_(intern_table),
quick_resolution_trampoline_(nullptr),
@@ -332,6 +331,12 @@
java_lang_Class->SetSuperClass(java_lang_Object.Get());
mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusLoaded, self);
+ java_lang_Object->SetObjectSize(sizeof(mirror::Object));
+ runtime->SetSentinel(heap->AllocObject<true>(self,
+ java_lang_Object.Get(),
+ java_lang_Object->GetObjectSize(),
+ VoidFunctor()));
+
// Object[] next to hold class roots.
Handle<mirror::Class> object_array_class(hs.NewHandle(
AllocClass(self, java_lang_Class.Get(),
@@ -1143,11 +1148,11 @@
quick_imt_conflict_trampoline_ = oat_file.GetOatHeader().GetQuickImtConflictTrampoline();
quick_generic_jni_trampoline_ = oat_file.GetOatHeader().GetQuickGenericJniTrampoline();
quick_to_interpreter_bridge_trampoline_ = oat_file.GetOatHeader().GetQuickToInterpreterBridge();
+ StackHandleScope<2> hs(self);
mirror::Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
- mirror::ObjectArray<mirror::DexCache>* dex_caches =
- dex_caches_object->AsObjectArray<mirror::DexCache>();
+ Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches(
+ hs.NewHandle(dex_caches_object->AsObjectArray<mirror::DexCache>()));
- StackHandleScope<1> hs(self);
Handle<mirror::ObjectArray<mirror::Class>> class_roots(hs.NewHandle(
space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)->
AsObjectArray<mirror::Class>()));
@@ -1157,6 +1162,13 @@
// as being Strings or not
mirror::String::SetClass(GetClassRoot(kJavaLangString));
+ mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject);
+ java_lang_Object->SetObjectSize(sizeof(mirror::Object));
+ Runtime::Current()->SetSentinel(Runtime::Current()->GetHeap()->AllocObject<true>(self,
+ java_lang_Object,
+ java_lang_Object->GetObjectSize(),
+ VoidFunctor()));
+
CHECK_EQ(oat_file.GetOatHeader().GetDexFileCount(),
static_cast<uint32_t>(dex_caches->GetLength()));
for (int32_t i = 0; i < dex_caches->GetLength(); i++) {
@@ -1250,7 +1262,6 @@
}
bool ClassLinker::ClassInClassTable(mirror::Class* klass) {
- ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
ClassTable* const class_table = ClassTableForClassLoader(klass->GetClassLoader());
return class_table != nullptr && class_table->Contains(klass);
}
@@ -1307,27 +1318,6 @@
// mapped image.
void ClassLinker::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
class_roots_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
- Thread* const self = Thread::Current();
- {
- ReaderMutexLock mu(self, dex_lock_);
- if ((flags & kVisitRootFlagAllRoots) != 0) {
- for (GcRoot<mirror::DexCache>& dex_cache : dex_caches_) {
- dex_cache.VisitRoot(visitor, RootInfo(kRootVMInternal));
- }
- } else if ((flags & kVisitRootFlagNewRoots) != 0) {
- for (size_t index : new_dex_cache_roots_) {
- dex_caches_[index].VisitRoot(visitor, RootInfo(kRootVMInternal));
- }
- }
- if ((flags & kVisitRootFlagClearRootLog) != 0) {
- new_dex_cache_roots_.clear();
- }
- if ((flags & kVisitRootFlagStartLoggingNewRoots) != 0) {
- log_new_dex_caches_roots_ = true;
- } else if ((flags & kVisitRootFlagStopLoggingNewRoots) != 0) {
- log_new_dex_caches_roots_ = false;
- }
- }
VisitClassRoots(visitor, flags);
array_iftable_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
for (GcRoot<mirror::Class>& root : find_array_class_cache_) {
@@ -1702,7 +1692,6 @@
long_array->GetWithoutChecks(j)));
const DexFile::ClassDef* dex_class_def = cp_dex_file->FindClassDef(descriptor, hash);
if (dex_class_def != nullptr) {
- RegisterDexFile(*cp_dex_file);
mirror::Class* klass = DefineClass(self, descriptor, hash, class_loader,
*cp_dex_file, *dex_class_def);
if (klass == nullptr) {
@@ -1848,7 +1837,7 @@
CHECK(self->IsExceptionPending()); // Expect an OOME.
return nullptr;
}
- klass->SetDexCache(FindDexCache(dex_file));
+ klass->SetDexCache(RegisterDexFile(dex_file));
SetupClass(dex_file, dex_class_def, klass, class_loader.Get());
@@ -2482,58 +2471,52 @@
RegisterDexFile(dex_file, dex_cache);
}
-bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) {
- dex_lock_.AssertSharedHeld(Thread::Current());
- for (GcRoot<mirror::DexCache>& root : dex_caches_) {
- mirror::DexCache* dex_cache = root.Read();
- if (dex_cache->GetDexFile() == &dex_file) {
- return true;
- }
- }
- return false;
-}
-
-bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) {
- ReaderMutexLock mu(Thread::Current(), dex_lock_);
- return IsDexFileRegisteredLocked(dex_file);
-}
-
void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
Handle<mirror::DexCache> dex_cache) {
- dex_lock_.AssertExclusiveHeld(Thread::Current());
+ Thread* const self = Thread::Current();
+ dex_lock_.AssertExclusiveHeld(self);
CHECK(dex_cache.Get() != nullptr) << dex_file.GetLocation();
CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()))
<< dex_cache->GetLocation()->ToModifiedUtf8() << " " << dex_file.GetLocation();
- dex_caches_.push_back(GcRoot<mirror::DexCache>(dex_cache.Get()));
- dex_cache->SetDexFile(&dex_file);
- if (log_new_dex_caches_roots_) {
- // TODO: This is not safe if we can remove dex caches.
- new_dex_cache_roots_.push_back(dex_caches_.size() - 1);
+ // Clean up pass to remove null dex caches.
+ // Null dex caches can occur due to class unloading and we are lazily removing null entries.
+ JavaVMExt* const vm = self->GetJniEnv()->vm;
+ for (auto it = dex_caches_.begin(); it != dex_caches_.end();) {
+ mirror::Object* dex_cache_root = self->DecodeJObject(*it);
+ if (dex_cache_root == nullptr) {
+ vm->DeleteWeakGlobalRef(self, *it);
+ it = dex_caches_.erase(it);
+ } else {
+ ++it;
+ }
}
+ dex_caches_.push_back(vm->AddWeakGlobalRef(self, dex_cache.Get()));
+ dex_cache->SetDexFile(&dex_file);
}
-void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
+mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file) {
Thread* self = Thread::Current();
{
ReaderMutexLock mu(self, dex_lock_);
- if (IsDexFileRegisteredLocked(dex_file)) {
- return;
+ mirror::DexCache* dex_cache = FindDexCacheLocked(dex_file, true);
+ if (dex_cache != nullptr) {
+ return dex_cache;
}
}
// Don't alloc while holding the lock, since allocation may need to
// suspend all threads and another thread may need the dex_lock_ to
// get to a suspend point.
StackHandleScope<1> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(AllocDexCache(self, dex_file)));
- CHECK(dex_cache.Get() != nullptr) << "Failed to allocate dex cache for "
- << dex_file.GetLocation();
- {
- WriterMutexLock mu(self, dex_lock_);
- if (IsDexFileRegisteredLocked(dex_file)) {
- return;
- }
- RegisterDexFileLocked(dex_file, dex_cache);
+ Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(AllocDexCache(self, dex_file)));
+ CHECK(h_dex_cache.Get() != nullptr) << "Failed to allocate dex cache for "
+ << dex_file.GetLocation();
+ WriterMutexLock mu(self, dex_lock_);
+ mirror::DexCache* dex_cache = FindDexCacheLocked(dex_file, true);
+ if (dex_cache != nullptr) {
+ return dex_cache;
}
+ RegisterDexFileLocked(dex_file, h_dex_cache);
+ return h_dex_cache.Get();
}
void ClassLinker::RegisterDexFile(const DexFile& dex_file,
@@ -2542,36 +2525,44 @@
RegisterDexFileLocked(dex_file, dex_cache);
}
-mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) {
- ReaderMutexLock mu(Thread::Current(), dex_lock_);
+mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file, bool allow_failure) {
+ Thread* const self = Thread::Current();
+ ReaderMutexLock mu(self, dex_lock_);
+ return FindDexCacheLocked(dex_file, allow_failure);
+}
+
+mirror::DexCache* ClassLinker::FindDexCacheLocked(const DexFile& dex_file, bool allow_failure) {
+ Thread* const self = Thread::Current();
// Search assuming unique-ness of dex file.
- for (size_t i = 0; i != dex_caches_.size(); ++i) {
- mirror::DexCache* dex_cache = GetDexCache(i);
- if (dex_cache->GetDexFile() == &dex_file) {
+ for (jobject weak_root : dex_caches_) {
+ mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root));
+ if (dex_cache != nullptr && dex_cache->GetDexFile() == &dex_file) {
return dex_cache;
}
}
- // Search matching by location name.
+ if (allow_failure) {
+ return nullptr;
+ }
std::string location(dex_file.GetLocation());
- for (size_t i = 0; i != dex_caches_.size(); ++i) {
- mirror::DexCache* dex_cache = GetDexCache(i);
- if (dex_cache->GetDexFile()->GetLocation() == location) {
- return dex_cache;
- }
- }
// Failure, dump diagnostic and abort.
- for (size_t i = 0; i != dex_caches_.size(); ++i) {
- mirror::DexCache* dex_cache = GetDexCache(i);
- LOG(ERROR) << "Registered dex file " << i << " = " << dex_cache->GetDexFile()->GetLocation();
+ for (jobject weak_root : dex_caches_) {
+ mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root));
+ if (dex_cache != nullptr) {
+ LOG(ERROR) << "Registered dex file " << dex_cache->GetDexFile()->GetLocation();
+ }
}
LOG(FATAL) << "Failed to find DexCache for DexFile " << location;
UNREACHABLE();
}
void ClassLinker::FixupDexCaches(ArtMethod* resolution_method) {
- ReaderMutexLock mu(Thread::Current(), dex_lock_);
- for (auto& dex_cache : dex_caches_) {
- dex_cache.Read()->Fixup(resolution_method, image_pointer_size_);
+ Thread* const self = Thread::Current();
+ ReaderMutexLock mu(self, dex_lock_);
+ for (jobject weak_root : dex_caches_) {
+ mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root));
+ if (dex_cache != nullptr) {
+ dex_cache->Fixup(resolution_method, image_pointer_size_);
+ }
}
}
@@ -3407,11 +3398,13 @@
DCHECK(proxy_class->IsProxyClass());
DCHECK(proxy_method->IsProxyMethod());
{
- ReaderMutexLock mu(Thread::Current(), dex_lock_);
+ Thread* const self = Thread::Current();
+ ReaderMutexLock mu(self, dex_lock_);
// Locate the dex cache of the original interface/Object
- for (const GcRoot<mirror::DexCache>& root : dex_caches_) {
- auto* dex_cache = root.Read();
- if (proxy_method->HasSameDexCacheResolvedTypes(dex_cache->GetResolvedTypes())) {
+ for (jobject weak_root : dex_caches_) {
+ mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root));
+ if (dex_cache != nullptr &&
+ proxy_method->HasSameDexCacheResolvedTypes(dex_cache->GetResolvedTypes())) {
ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
proxy_method->GetDexMethodIndex(), image_pointer_size_);
CHECK(resolved_method != nullptr);
@@ -5878,11 +5871,6 @@
// We could move the jobject to the callers, but all call-sites do this...
ScopedObjectAccessUnchecked soa(self);
- // Register the dex files.
- for (const DexFile* dex_file : dex_files) {
- RegisterDexFile(*dex_file);
- }
-
// For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex.
StackHandleScope<10> hs(self);
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index fbf4035..cc56e8b 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -278,7 +278,7 @@
void RunRootClinits() SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!dex_lock_, !Roles::uninterruptible_);
- void RegisterDexFile(const DexFile& dex_file)
+ mirror::DexCache* RegisterDexFile(const DexFile& dex_file)
REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_);
void RegisterDexFile(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache)
REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_);
@@ -309,9 +309,7 @@
void VisitRoots(RootVisitor* visitor, VisitRootFlags flags)
REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_);
- mirror::DexCache* FindDexCache(const DexFile& dex_file)
- REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_);
- bool IsDexFileRegistered(const DexFile& dex_file)
+ mirror::DexCache* FindDexCache(const DexFile& dex_file, bool allow_failure = false)
REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_);
void FixupDexCaches(ArtMethod* resolution_method)
REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_);
@@ -471,7 +469,7 @@
// Used by image writer for checking.
bool ClassInClassTable(mirror::Class* klass)
- REQUIRES(!Locks::classlinker_classes_lock_)
+ REQUIRES(Locks::classlinker_classes_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
ArtMethod* CreateRuntimeMethod();
@@ -561,8 +559,9 @@
void RegisterDexFileLocked(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache)
REQUIRES(dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_);
- bool IsDexFileRegisteredLocked(const DexFile& dex_file)
- SHARED_REQUIRES(dex_lock_, Locks::mutator_lock_);
+ mirror::DexCache* FindDexCacheLocked(const DexFile& dex_file, bool allow_failure)
+ REQUIRES(dex_lock_)
+ SHARED_REQUIRES(Locks::mutator_lock_);
bool InitializeClass(Thread* self, Handle<mirror::Class> klass, bool can_run_clinit,
bool can_init_parents)
@@ -631,7 +630,9 @@
size_t GetDexCacheCount() SHARED_REQUIRES(Locks::mutator_lock_, dex_lock_) {
return dex_caches_.size();
}
- mirror::DexCache* GetDexCache(size_t idx) SHARED_REQUIRES(Locks::mutator_lock_, dex_lock_);
+ const std::list<jobject>& GetDexCaches() SHARED_REQUIRES(Locks::mutator_lock_, dex_lock_) {
+ return dex_caches_;
+ }
const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location)
REQUIRES(!dex_lock_);
@@ -702,8 +703,9 @@
std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
mutable ReaderWriterMutex dex_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
- std::vector<size_t> new_dex_cache_roots_ GUARDED_BY(dex_lock_);
- std::vector<GcRoot<mirror::DexCache>> dex_caches_ GUARDED_BY(dex_lock_);
+ // JNI weak globals to allow dex caches to get unloaded. We lazily delete weak globals when we
+ // register new dex files.
+ std::list<jobject> dex_caches_ GUARDED_BY(dex_lock_);
std::vector<const OatFile*> oat_files_ GUARDED_BY(dex_lock_);
// This contains the class laoders which have class tables. It is populated by
@@ -736,7 +738,6 @@
size_t find_array_class_cache_next_victim_;
bool init_done_;
- bool log_new_dex_caches_roots_ GUARDED_BY(dex_lock_);
bool log_new_class_table_roots_ GUARDED_BY(Locks::classlinker_classes_lock_);
InternTable* intern_table_;
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 5f9e413..56c5d1a 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -551,7 +551,8 @@
}
Thread* self = Thread::Current();
- jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self, class_path);
+ jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self,
+ class_path);
self->SetClassLoaderOverride(class_loader);
return class_loader;
}
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 9d41018..2fd0517 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -373,7 +373,7 @@
globals_(gGlobalsInitial, gGlobalsMax, kGlobal),
libraries_(new Libraries),
unchecked_functions_(&gJniInvokeInterface),
- weak_globals_lock_("JNI weak global reference table lock"),
+ weak_globals_lock_("JNI weak global reference table lock", kJniWeakGlobalsLock),
weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal),
allow_new_weak_globals_(true),
weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) {
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 4f97d20..9bd320c 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -171,7 +171,7 @@
if (array == nullptr) {
ScopedObjectAccess soa(env);
for (auto& dex_file : dex_files) {
- if (Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) {
+ if (Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file, true) != nullptr) {
dex_file.release();
}
}
@@ -209,7 +209,7 @@
// TODO: The Runtime should support unloading of classes and freeing of the
// dex files for those unloaded classes rather than leaking dex files here.
for (auto& dex_file : *dex_files) {
- if (!Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) {
+ if (Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file, true) == nullptr) {
delete dex_file;
}
}
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 9ea339a..5a9c43b 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -425,14 +425,16 @@
static void PreloadDexCachesStatsFilled(DexCacheStats* filled)
SHARED_REQUIRES(Locks::mutator_lock_) {
if (!kPreloadDexCachesCollectStats) {
- return;
+ return;
}
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
- for (size_t i = 0; i< boot_class_path.size(); i++) {
- const DexFile* dex_file = boot_class_path[i];
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+ for (const DexFile* dex_file : class_linker->GetBootClassPath()) {
CHECK(dex_file != nullptr);
- mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file);
+ mirror::DexCache* const dex_cache = class_linker->FindDexCache(*dex_file, true);
+ // If dex cache was deallocated, just continue.
+ if (dex_cache == nullptr) {
+ continue;
+ }
for (size_t j = 0; j < dex_cache->NumStrings(); j++) {
mirror::String* string = dex_cache->GetResolvedString(j);
if (string != nullptr) {
@@ -446,7 +448,7 @@
}
}
for (size_t j = 0; j < dex_cache->NumResolvedFields(); j++) {
- ArtField* field = linker->GetResolvedField(j, dex_cache);
+ ArtField* field = class_linker->GetResolvedField(j, dex_cache);
if (field != nullptr) {
filled->num_fields++;
}
@@ -490,11 +492,11 @@
}
const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath();
- for (size_t i = 0; i< boot_class_path.size(); i++) {
+ for (size_t i = 0; i < boot_class_path.size(); i++) {
const DexFile* dex_file = boot_class_path[i];
CHECK(dex_file != nullptr);
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file)));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->RegisterDexFile(*dex_file)));
if (kPreloadDexCachesStrings) {
for (size_t j = 0; j < dex_cache->NumStrings(); j++) {
diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h
index 380e72b..bfa8c54 100644
--- a/runtime/runtime-inl.h
+++ b/runtime/runtime-inl.h
@@ -20,6 +20,7 @@
#include "runtime.h"
#include "art_method.h"
+#include "class_linker.h"
#include "read_barrier-inl.h"
namespace art {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1912314..49451ad 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -791,6 +791,12 @@
return failure_count;
}
+void Runtime::SetSentinel(mirror::Object* sentinel) {
+ CHECK(sentinel_.Read() == nullptr);
+ CHECK(sentinel != nullptr);
+ sentinel_ = GcRoot<mirror::Object>(sentinel);
+}
+
bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) {
ATRACE_BEGIN("Runtime::Init");
CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize);
@@ -1054,10 +1060,6 @@
CHECK(class_linker_ != nullptr);
- // Initialize the special sentinel_ value early.
- sentinel_ = GcRoot<mirror::Object>(class_linker_->AllocObject(self));
- CHECK(sentinel_.Read() != nullptr);
-
verifier::MethodVerifier::Init();
if (runtime_options.Exists(Opt::MethodTrace)) {
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 4577b75..bd21db1 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -568,6 +568,9 @@
return fingerprint_;
}
+ // Called from class linker.
+ void SetSentinel(mirror::Object* sentinel) SHARED_REQUIRES(Locks::mutator_lock_);
+
private:
static void InitPlatformSignalHandlers();
diff --git a/runtime/trace.cc b/runtime/trace.cc
index 4393430..7579d8d 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -640,7 +640,8 @@
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
for (auto& e : seen_methods) {
DexIndexBitSet* bit_set = e.second;
- mirror::DexCache* dex_cache = class_linker->FindDexCache(*e.first);
+ // TODO: Visit trace methods as roots.
+ mirror::DexCache* dex_cache = class_linker->FindDexCache(*e.first, false);
for (uint32_t i = 0; i < bit_set->size(); ++i) {
if ((*bit_set)[i]) {
visited_methods->insert(dex_cache->GetResolvedMethod(i, sizeof(void*)));
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index efefa8b..5b73f10 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3379,6 +3379,7 @@
ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess(
uint32_t dex_method_idx, MethodType method_type) {
const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx);
+ // LOG(INFO) << dex_file_->NumTypeIds() << " " << dex_file_->NumClassDefs();
const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_);
if (klass_type.IsConflict()) {
std::string append(" in attempt to access method ");