summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2015-08-28 14:56:43 -0700
committer Mathieu Chartier <mathieuc@google.com> 2015-08-31 10:58:31 -0700
commit673ed3d8aedc5462a47ded827c99f35d46525457 (patch)
tree83de4690228c9f7772c48c770c5e2e5ba2dac6fe
parentce209462cc1a7ce235e5ac0d0e6db6b402f73441 (diff)
Revert "Revert "Change dex caches to be weak roots""
This reverts commit 81a9087f0df0518c39405b7d18ba5858a6d8b77b. Boot.oat creation time goes from 4.7s to 4.9s on host due to extra locking. Will try to improve this in another CL. Bug: 23602225 Bug: 22720414 Change-Id: I7e25b75cfb63faa196c7b0f60e46cce50bf12021
-rw-r--r--compiler/dex/mir_method_info.cc3
-rw-r--r--compiler/driver/compiler_driver-inl.h9
-rw-r--r--compiler/driver/compiler_driver.cc38
-rw-r--r--compiler/driver/compiler_driver_test.cc2
-rw-r--r--compiler/image_writer.cc77
-rw-r--r--compiler/image_writer.h5
-rw-r--r--compiler/oat_writer.cc12
-rw-r--r--compiler/optimizing/builder.cc14
-rw-r--r--compiler/optimizing/inliner.cc4
-rw-r--r--compiler/optimizing/optimizing_compiler.cc3
-rw-r--r--compiler/optimizing/reference_type_propagation.cc12
-rw-r--r--dex2oat/dex2oat.cc27
-rw-r--r--oatdump/oatdump.cc21
-rw-r--r--runtime/base/mutex.h3
-rw-r--r--runtime/class_linker-inl.h6
-rw-r--r--runtime/class_linker.cc186
-rw-r--r--runtime/class_linker.h27
-rw-r--r--runtime/class_linker_test.cc2
-rw-r--r--runtime/common_runtime_test.cc3
-rw-r--r--runtime/java_vm_ext.cc9
-rw-r--r--runtime/java_vm_ext.h11
-rw-r--r--runtime/native/dalvik_system_DexFile.cc7
-rw-r--r--runtime/native/dalvik_system_VMRuntime.cc21
-rw-r--r--runtime/runtime-inl.h1
-rw-r--r--runtime/runtime.cc15
-rw-r--r--runtime/runtime.h3
-rw-r--r--runtime/trace.cc4
-rw-r--r--runtime/verifier/method_verifier.cc1
28 files changed, 284 insertions, 242 deletions
diff --git a/compiler/dex/mir_method_info.cc b/compiler/dex/mir_method_info.cc
index be913fe634..31c3808197 100644
--- a/compiler/dex/mir_method_info.cc
+++ b/compiler/dex/mir_method_info.cc
@@ -105,7 +105,8 @@ void MirMethodLoweringInfo::Resolve(CompilerDriver* compiler_driver,
// Don't devirt if we are in a different dex file since we can't have direct invokes in
// another dex file unless we always put a direct / patch pointer.
devirt_target = nullptr;
- current_dex_cache.Assign(runtime->GetClassLinker()->FindDexCache(*it->target_dex_file_));
+ current_dex_cache.Assign(runtime->GetClassLinker()->FindDexCache(
+ soa.Self(), *it->target_dex_file_));
CHECK(current_dex_cache.Get() != nullptr);
DexCompilationUnit cu(
mUnit->GetCompilationUnit(), mUnit->GetClassLoader(), mUnit->GetClassLinker(),
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index 80387f2842..8f1987a7db 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(Thread::Current(), *mUnit->GetDexFile(), false);
}
inline mirror::ClassLoader* CompilerDriver::GetClassLoader(ScopedObjectAccess& soa,
@@ -87,7 +87,7 @@ inline ArtField* CompilerDriver::ResolveFieldWithDexFile(
}
inline mirror::DexCache* CompilerDriver::FindDexCache(const DexFile* dex_file) {
- return Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file);
+ return Runtime::Current()->GetClassLinker()->FindDexCache(Thread::Current(), *dex_file, false);
}
inline ArtField* CompilerDriver::ResolveField(
@@ -339,7 +339,8 @@ inline int CompilerDriver::IsFastInvoke(
// 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(
+ soa.Self(), *mUnit->GetDexFile(), false));
CHECK_EQ(referrer_class->GetDexCache()->GetResolvedMethod(
target_method->dex_method_index, pointer_size),
resolved_method) << PrettyMethod(resolved_method);
@@ -369,7 +370,7 @@ inline int CompilerDriver::IsFastInvoke(
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 fb3af2d2b7..6d3a960048 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -940,7 +940,7 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) {
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>())));
@@ -1174,7 +1174,8 @@ bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, u
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(
+ soa.Self(), dex_file, false);
mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class == nullptr) {
// Erroneous class.
@@ -1199,9 +1200,10 @@ bool CompilerDriver::CanAssumeStringIsPresentInDexCache(const DexFile& dex_file,
// 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(
+ soa.Self(), dex_file, false)));
+ class_linker->ResolveString(dex_file, string_idx, dex_cache);
result = true;
}
if (result) {
@@ -1226,7 +1228,8 @@ bool CompilerDriver::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const Dex
*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(
+ soa.Self(), 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) {
@@ -1263,7 +1266,8 @@ bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_id
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(
+ soa.Self(), 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) {
@@ -1292,7 +1296,8 @@ bool CompilerDriver::CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_i
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(
+ soa.Self(), dex_file, false);
mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class == nullptr) {
return false;
@@ -1421,7 +1426,8 @@ ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx,
{
StackHandleScope<2> hs(soa.Self());
Handle<mirror::DexCache> dex_cache_handle(
- hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
+ hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(
+ soa.Self(), *mUnit->GetDexFile(), false)));
Handle<mirror::ClassLoader> class_loader_handle(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
resolved_field =
@@ -1471,7 +1477,8 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila
{
StackHandleScope<2> hs(soa.Self());
Handle<mirror::DexCache> dex_cache_handle(
- hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())));
+ hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(
+ soa.Self(), *mUnit->GetDexFile(), false)));
Handle<mirror::ClassLoader> class_loader_handle(
hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())));
resolved_field =
@@ -1657,7 +1664,8 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui
// 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(
+ soa.Self(), *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;
@@ -1909,7 +1917,8 @@ class ResolveClassFieldsAndMethodsVisitor : public CompilationVisitor {
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(
+ soa.Self(), dex_file, false)));
// Resolve the class.
mirror::Class* klass = class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache,
class_loader);
@@ -2002,7 +2011,7 @@ class ResolveTypeVisitor : public CompilationVisitor {
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);
@@ -2088,7 +2097,8 @@ class VerifyClassVisitor : public CompilationVisitor {
* 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(
+ soa.Self(), 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/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index a5ace0bf42..1107599779 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -108,7 +108,7 @@ TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
ScopedObjectAccess soa(Thread::Current());
ASSERT_TRUE(java_lang_dex_file_ != nullptr);
const DexFile& dex = *java_lang_dex_file_;
- mirror::DexCache* dex_cache = class_linker_->FindDexCache(dex);
+ mirror::DexCache* dex_cache = class_linker_->FindDexCache(soa.Self(), dex);
EXPECT_EQ(dex.NumStringIds(), dex_cache->NumStrings());
for (size_t i = 0; i < dex_cache->NumStrings(); i++) {
const mirror::String* string = dex_cache->GetResolvedString(i);
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 93897aa228..dbd3366c1b 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -70,7 +70,6 @@ namespace art {
// 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 @@ bool ImageWriter::PrepareImageAddressSpace() {
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::SetImageBinSlot(mirror::Object* object, BinSlot bin_slot) {
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 @@ void ImageWriter::ComputeLazyFieldsForImageClasses() {
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 @@ void ImageWriter::PruneNonImageClasses() {
// 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 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const {
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 c8aa82dc32..778521c606 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -225,11 +225,6 @@ class ImageWriter FINAL {
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 64e748776d..fdf904d1f0 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -617,7 +617,8 @@ class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor {
// Unchecked as we hold mutator_lock_ on entry.
ScopedObjectAccessUnchecked soa(Thread::Current());
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(*dex_file_)));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache(
+ Thread::Current(), *dex_file_)));
ArtMethod* method = linker->ResolveMethod(
*dex_file_, it.GetMemberIndex(), dex_cache, NullHandle<mirror::ClassLoader>(), nullptr,
invoke_type);
@@ -668,7 +669,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
SHARED_REQUIRES(Locks::mutator_lock_) {
OatDexMethodVisitor::StartClass(dex_file, class_def_index);
if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) {
- dex_cache_ = class_linker_->FindDexCache(*dex_file);
+ dex_cache_ = class_linker_->FindDexCache(Thread::Current(), *dex_file);
}
return true;
}
@@ -691,6 +692,8 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
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_;
@@ -796,7 +799,8 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
SHARED_REQUIRES(Locks::mutator_lock_) {
MethodReference ref = patch.TargetMethod();
mirror::DexCache* dex_cache =
- (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(*ref.dex_file);
+ (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(
+ Thread::Current(), *ref.dex_file);
ArtMethod* method = dex_cache->GetResolvedMethod(
ref.dex_method_index, class_linker_->GetImagePointerSize());
CHECK(method != nullptr);
@@ -830,7 +834,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor {
mirror::Class* GetTargetType(const LinkerPatch& patch)
SHARED_REQUIRES(Locks::mutator_lock_) {
mirror::DexCache* dex_cache = (dex_file_ == patch.TargetTypeDexFile())
- ? dex_cache_ : class_linker_->FindDexCache(*patch.TargetTypeDexFile());
+ ? dex_cache_ : class_linker_->FindDexCache(Thread::Current(), *patch.TargetTypeDexFile());
mirror::Class* type = dex_cache->GetResolvedType(patch.TargetTypeIndex());
CHECK(type != nullptr);
return type;
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 7b42db8a7f..23ab94e5fe 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -902,7 +902,7 @@ HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(
StackHandleScope<4> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(
dex_compilation_unit_->GetClassLinker()->FindDexCache(
- *dex_compilation_unit_->GetDexFile())));
+ soa.Self(), *dex_compilation_unit_->GetDexFile())));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
ArtMethod* resolved_method = compiler_driver_->ResolveMethod(
@@ -912,7 +912,7 @@ HClinitCheck* HGraphBuilder::ProcessClinitCheckForInvoke(
const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
- outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
+ outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));
Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
// The index at which the method's class is stored in the DexCache's type array.
@@ -1228,7 +1228,7 @@ static mirror::Class* GetClassFrom(CompilerDriver* driver,
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
soa.Decode<mirror::ClassLoader*>(compilation_unit.GetClassLoader())));
Handle<mirror::DexCache> dex_cache(hs.NewHandle(
- compilation_unit.GetClassLinker()->FindDexCache(dex_file)));
+ compilation_unit.GetClassLinker()->FindDexCache(soa.Self(), dex_file)));
return driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, &compilation_unit);
}
@@ -1245,7 +1245,8 @@ bool HGraphBuilder::IsOutermostCompilingClass(uint16_t type_index) const {
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<4> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(
- dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
+ dex_compilation_unit_->GetClassLinker()->FindDexCache(
+ soa.Self(), *dex_compilation_unit_->GetDexFile())));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
Handle<mirror::Class> cls(hs.NewHandle(compiler_driver_->ResolveClass(
@@ -1264,7 +1265,8 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<4> hs(soa.Self());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(
- dex_compilation_unit_->GetClassLinker()->FindDexCache(*dex_compilation_unit_->GetDexFile())));
+ dex_compilation_unit_->GetClassLinker()->FindDexCache(
+ soa.Self(), *dex_compilation_unit_->GetDexFile())));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
ArtField* resolved_field = compiler_driver_->ResolveField(
@@ -1277,7 +1279,7 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction,
const DexFile& outer_dex_file = *outer_compilation_unit_->GetDexFile();
Handle<mirror::DexCache> outer_dex_cache(hs.NewHandle(
- outer_compilation_unit_->GetClassLinker()->FindDexCache(outer_dex_file)));
+ outer_compilation_unit_->GetClassLinker()->FindDexCache(soa.Self(), outer_dex_file)));
Handle<mirror::Class> outer_class(hs.NewHandle(GetOutermostCompilingClass()));
// The index at which the field's class is stored in the DexCache's type array.
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index ff90f32754..112d42e904 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -182,10 +182,10 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) {
ArtMethod* resolved_method;
if (invoke_instruction->IsInvokeStaticOrDirect()) {
MethodReference ref = invoke_instruction->AsInvokeStaticOrDirect()->GetTargetMethod();
- resolved_method = class_linker->FindDexCache(*ref.dex_file)->GetResolvedMethod(
+ resolved_method = class_linker->FindDexCache(soa.Self(), *ref.dex_file)->GetResolvedMethod(
ref.dex_method_index, class_linker->GetImagePointerSize());
} else {
- resolved_method = class_linker->FindDexCache(caller_dex_file)->GetResolvedMethod(
+ resolved_method = class_linker->FindDexCache(soa.Self(), caller_dex_file)->GetResolvedMethod(
method_index, class_linker->GetImagePointerSize());
}
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 1db3063aec..6f251e8e6c 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -714,7 +714,8 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite
ScopedObjectAccess soa(Thread::Current());
StackHandleScope<4> hs(soa.Self());
ClassLinker* class_linker = dex_compilation_unit.GetClassLinker();
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file)));
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(
+ soa.Self(), dex_file)));
Handle<mirror::ClassLoader> loader(hs.NewHandle(
soa.Decode<mirror::ClassLoader*>(class_loader)));
ArtMethod* art_method = compiler_driver->ResolveMethod(
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index d3eec1a9e6..516638b33c 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -363,7 +363,8 @@ void RTPVisitor::SetClassAsTypeInfo(HInstruction* instr,
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(
+ soa.Self(), instr->AsInvoke()->GetDexFile(), false);
ArtMethod* method = dex_cache->GetResolvedMethod(
instr->AsInvoke()->GetDexMethodIndex(), cl->GetImagePointerSize());
DCHECK(method != nullptr);
@@ -394,7 +395,8 @@ void RTPVisitor::UpdateReferenceTypeInfo(HInstruction* instr,
DCHECK_EQ(instr->GetType(), Primitive::kPrimNot);
ScopedObjectAccess soa(Thread::Current());
- mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file);
+ mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(
+ soa.Self(), dex_file, false);
// Get type from dex cache assuming it was populated by the verifier.
SetClassAsTypeInfo(instr, dex_cache->GetResolvedType(type_idx), is_exact);
}
@@ -432,7 +434,7 @@ void RTPVisitor::UpdateFieldAccessTypeInfo(HInstruction* instr,
ScopedObjectAccess soa(Thread::Current());
ClassLinker* cl = Runtime::Current()->GetClassLinker();
- mirror::DexCache* dex_cache = cl->FindDexCache(info.GetDexFile());
+ mirror::DexCache* dex_cache = cl->FindDexCache(soa.Self(), info.GetDexFile(), false);
ArtField* field = cl->GetResolvedField(info.GetFieldIndex(), dex_cache);
// TODO: There are certain cases where we can't resolve the field.
// b/21914925 is open to keep track of a repro case for this issue.
@@ -451,7 +453,7 @@ void RTPVisitor::VisitStaticFieldGet(HStaticFieldGet* instr) {
void RTPVisitor::VisitLoadClass(HLoadClass* instr) {
ScopedObjectAccess soa(Thread::Current());
mirror::DexCache* dex_cache =
- Runtime::Current()->GetClassLinker()->FindDexCache(instr->GetDexFile());
+ Runtime::Current()->GetClassLinker()->FindDexCache(soa.Self(), instr->GetDexFile(), false);
// Get type from dex cache assuming it was populated by the verifier.
mirror::Class* resolved_class = dex_cache->GetResolvedType(instr->GetTypeIndex());
// TODO: investigating why we are still getting unresolved classes: b/22821472.
@@ -634,7 +636,7 @@ void RTPVisitor::VisitInvoke(HInvoke* instr) {
ScopedObjectAccess soa(Thread::Current());
ClassLinker* cl = Runtime::Current()->GetClassLinker();
- mirror::DexCache* dex_cache = cl->FindDexCache(instr->GetDexFile());
+ mirror::DexCache* dex_cache = cl->FindDexCache(soa.Self(), instr->GetDexFile());
ArtMethod* method = dex_cache->GetResolvedMethod(
instr->GetDexMethodIndex(), cl->GetImagePointerSize());
mirror::Class* klass = (method == nullptr) ? nullptr : method->GetReturnType(false);
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 99736e95d0..07cf88c44a 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -1207,6 +1207,14 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
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 @@ class Dex2Oat FINAL {
}
}
}
- // 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 @@ class Dex2Oat FINAL {
// 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 @@ class Dex2Oat FINAL {
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 @@ static int dex2oat(int argc, char** argv) {
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 a2aa77ec4c..c553a18561 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -827,11 +827,15 @@ class OatDumper {
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));
}
@@ -1404,6 +1408,7 @@ class OatDumper {
}
verifier::MethodVerifier* DumpVerifier(VariableIndentationOutputStream* vios,
+ StackHandleScope<1>* hs,
uint32_t dex_method_idx,
const DexFile* dex_file,
const DexFile::ClassDef& class_def,
@@ -1411,9 +1416,8 @@ class OatDumper {
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_,
@@ -1614,10 +1618,13 @@ class ImageDumper {
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 848c904fe6..6bf203c307 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -64,6 +64,8 @@ enum LockLevel {
kJdwpSocketLock,
kRegionSpaceRegionLock,
kTransactionLogLock,
+ kMarkSweepMarkStackLock,
+ kJniWeakGlobalsLock,
kReferenceQueueSoftReferencesLock,
kReferenceQueuePhantomReferencesLock,
kReferenceQueueFinalizerReferencesLock,
@@ -79,7 +81,6 @@ enum LockLevel {
kArenaPoolLock,
kDexFileMethodInlinerLock,
kDexFileToMethodInlinerMapLock,
- kMarkSweepMarkStackLock,
kInternTableLock,
kOatFileSecondaryLookupLock,
kTracingUniqueMethodsLock,
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 11901b3bef..d2dbff634e 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -195,12 +195,6 @@ inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root)
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 b074deccf7..e78914c3a3 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -273,7 +273,6 @@ ClassLinker::ClassLinker(InternTable* intern_table)
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 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
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 @@ void ClassLinker::InitFromImage() {
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 @@ void ClassLinker::InitFromImage() {
// 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 @@ void ClassLinker::InitFromImage() {
}
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 @@ void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) {
// 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 @@ bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable&
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) {
@@ -1845,11 +1834,15 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si
klass.Assign(AllocClass(self, SizeOfClassWithoutEmbeddedTables(dex_file, dex_class_def)));
}
if (UNLIKELY(klass.Get() == nullptr)) {
- CHECK(self->IsExceptionPending()); // Expect an OOME.
+ self->AssertPendingOOMException();
return nullptr;
}
- klass->SetDexCache(FindDexCache(dex_file));
-
+ mirror::DexCache* dex_cache = RegisterDexFile(dex_file);
+ if (dex_cache == nullptr) {
+ self->AssertPendingOOMException();
+ return nullptr;
+ }
+ klass->SetDexCache(dex_cache);
SetupClass(dex_file, dex_class_def, klass, class_loader.Get());
// Mark the string class by setting its access flag.
@@ -2482,58 +2475,54 @@ void ClassLinker::AppendToBootClassPath(const DexFile& dex_file,
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(self, 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)));
+ WriterMutexLock mu(self, dex_lock_);
+ mirror::DexCache* dex_cache = FindDexCacheLocked(self, dex_file, true);
+ if (dex_cache != nullptr) {
+ return dex_cache;
}
+ if (h_dex_cache.Get() == nullptr) {
+ self->AssertPendingOOMException();
+ return nullptr;
+ }
+ RegisterDexFileLocked(dex_file, h_dex_cache);
+ return h_dex_cache.Get();
}
void ClassLinker::RegisterDexFile(const DexFile& dex_file,
@@ -2542,36 +2531,52 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file,
RegisterDexFileLocked(dex_file, dex_cache);
}
-mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) {
- ReaderMutexLock mu(Thread::Current(), dex_lock_);
+mirror::DexCache* ClassLinker::FindDexCache(Thread* self,
+ const DexFile& dex_file,
+ bool allow_failure) {
+ ReaderMutexLock mu(self, dex_lock_);
+ return FindDexCacheLocked(self, dex_file, allow_failure);
+}
+
+mirror::DexCache* ClassLinker::FindDexCacheLocked(Thread* self,
+ const DexFile& dex_file,
+ bool allow_failure) {
// 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) {
- return dex_cache;
+ JavaVMExt* const vm = self->GetJniEnv()->vm;
+ {
+ MutexLock mu(self, vm->WeakGlobalsLock());
+ for (jobject weak_root : dex_caches_) {
+ DCHECK_EQ(GetIndirectRefKind(weak_root), kWeakGlobal);
+ mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(
+ vm->DecodeWeakGlobalLocked(self, weak_root));
+ if (dex_cache != nullptr && dex_cache->GetDexFile() == &dex_file) {
+ return dex_cache;
+ }
}
}
- // Search matching by location name.
- 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;
- }
+ if (allow_failure) {
+ return nullptr;
}
+ std::string location(dex_file.GetLocation());
// 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 +3412,13 @@ ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, ArtMethod
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 +5885,6 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi
// 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 fbf4035842..2a7162b000 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -278,7 +278,7 @@ class ClassLinker {
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,9 @@ class ClassLinker {
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(Thread* self,
+ 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 +471,7 @@ class ClassLinker {
// 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 +561,11 @@ class ClassLinker {
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(Thread* self,
+ 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 +634,9 @@ class ClassLinker {
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 +707,9 @@ class ClassLinker {
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 +742,6 @@ class ClassLinker {
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/class_linker_test.cc b/runtime/class_linker_test.cc
index 0d1c875fdf..c3191fad3f 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -355,7 +355,7 @@ class ClassLinkerTest : public CommonRuntimeTest {
TestRootVisitor visitor;
class_linker_->VisitRoots(&visitor, kVisitRootFlagAllRoots);
// Verify the dex cache has resolution methods in all resolved method slots
- mirror::DexCache* dex_cache = class_linker_->FindDexCache(dex);
+ mirror::DexCache* dex_cache = class_linker_->FindDexCache(Thread::Current(), dex);
auto* resolved_methods = dex_cache->GetResolvedMethods();
for (size_t i = 0; i < static_cast<size_t>(resolved_methods->GetLength()); i++) {
EXPECT_TRUE(resolved_methods->GetElementPtrSize<ArtMethod*>(i, sizeof(void*)) != nullptr)
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 5f9e413ed2..56c5d1a2c3 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -551,7 +551,8 @@ jobject CommonRuntimeTest::LoadDex(const char* dex_name) {
}
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 9d41018c1b..ef7a924c63 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -373,7 +373,7 @@ JavaVMExt::JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options
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_) {
@@ -578,6 +578,13 @@ void JavaVMExt::UpdateGlobal(Thread* self, IndirectRef ref, mirror::Object* resu
mirror::Object* JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) {
MutexLock mu(self, weak_globals_lock_);
+ return DecodeWeakGlobalLocked(self, ref);
+}
+
+mirror::Object* JavaVMExt::DecodeWeakGlobalLocked(Thread* self, IndirectRef ref) {
+ if (kDebugLocking) {
+ weak_globals_lock_.AssertHeld(self);
+ }
while (UNLIKELY((!kUseReadBarrier && !allow_new_weak_globals_) ||
(kUseReadBarrier && !self->GetWeakRefAccessEnabled()))) {
weak_globals_add_condition_.WaitHoldingLocks(self);
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index d70fc47c61..e80266fd5d 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -133,7 +133,16 @@ class JavaVMExt : public JavaVM {
SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!globals_lock_);
mirror::Object* DecodeWeakGlobal(Thread* self, IndirectRef ref)
- SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!weak_globals_lock_);
+ SHARED_REQUIRES(Locks::mutator_lock_)
+ REQUIRES(!weak_globals_lock_);
+
+ mirror::Object* DecodeWeakGlobalLocked(Thread* self, IndirectRef ref)
+ SHARED_REQUIRES(Locks::mutator_lock_)
+ REQUIRES(weak_globals_lock_);
+
+ Mutex& WeakGlobalsLock() RETURN_CAPABILITY(weak_globals_lock_) {
+ return weak_globals_lock_;
+ }
void UpdateWeakGlobal(Thread* self, IndirectRef ref, mirror::Object* result)
SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!weak_globals_lock_);
diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc
index 4f97d20d6c..3b84bfa026 100644
--- a/runtime/native/dalvik_system_DexFile.cc
+++ b/runtime/native/dalvik_system_DexFile.cc
@@ -171,7 +171,7 @@ static jobject DexFile_openDexFileNative(
if (array == nullptr) {
ScopedObjectAccess soa(env);
for (auto& dex_file : dex_files) {
- if (Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) {
+ if (linker->FindDexCache(soa.Self(), *dex_file, true) != nullptr) {
dex_file.release();
}
}
@@ -208,8 +208,9 @@ static void DexFile_closeDexFile(JNIEnv* env, jclass, jobject cookie) {
//
// 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)) {
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+ for (const DexFile* dex_file : *dex_files) {
+ if (class_linker->FindDexCache(soa.Self(), *dex_file, true) == nullptr) {
delete dex_file;
}
}
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 9ea339a6bd..4f957233c4 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -425,14 +425,17 @@ static void PreloadDexCachesStatsTotal(DexCacheStats* total) {
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();
+ Thread* const self = Thread::Current();
+ 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(self, *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 +449,7 @@ static void PreloadDexCachesStatsFilled(DexCacheStats* filled)
}
}
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 +493,11 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) {
}
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 380e72b5dd..bfa8c549bf 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 1912314d17..a9dc16ddd6 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -235,6 +235,9 @@ Runtime::~Runtime() {
self->GetJniEnv()->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons,
WellKnownClasses::java_lang_Daemons_stop);
}
+
+ Trace::Shutdown();
+
if (attach_shutdown_thread) {
DetachCurrentThread();
self = nullptr;
@@ -245,8 +248,6 @@ Runtime::~Runtime() {
BackgroundMethodSamplingProfiler::Shutdown();
}
- Trace::Shutdown();
-
// Make sure to let the GC complete if it is running.
heap_->WaitForGcToComplete(gc::kGcCauseBackground, self);
heap_->DeleteThreadPool();
@@ -791,6 +792,12 @@ static size_t OpenDexFiles(const std::vector<std::string>& dex_filenames,
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 +1061,6 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized)
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 4577b75397..bd21db16c4 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -568,6 +568,9 @@ class Runtime {
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 439343068c..4ab5c0efe7 100644
--- a/runtime/trace.cc
+++ b/runtime/trace.cc
@@ -638,9 +638,11 @@ static void GetVisitedMethodsFromBitSets(
const std::map<const DexFile*, DexIndexBitSet*>& seen_methods,
std::set<ArtMethod*>* visited_methods) SHARED_REQUIRES(Locks::mutator_lock_) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Thread* const self = Thread::Current();
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(self, *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 bba9c5e3c5..4f921bdbc8 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3407,6 +3407,7 @@ const RegType& MethodVerifier::GetCaughtExceptionType() {
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 ");