summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2013-11-26 12:00:11 -0800
committerMathieu Chartier <mathieuc@google.com>2013-12-10 16:00:58 -0800
commitc528dba35b5faece51ca658fc008b688f8b690ad (patch)
treed95c113a639d07f7e3b88e8a6caa9b5f6e044801 /runtime
parent76f552307ee980221626d1dff0ada56c989d24ca (diff)
downloadart-c528dba35b5faece51ca658fc008b688f8b690ad.zip
art-c528dba35b5faece51ca658fc008b688f8b690ad.tar.gz
art-c528dba35b5faece51ca658fc008b688f8b690ad.tar.bz2
Enable moving classes.
Slight reduction in Zygote size, memory savings are in the noise. Before: Zygote size: 8739224 After: Zygote size: 8733568 Fixed a bug where we didn't set the concurrent start bytes after switching the allocator from bump pointer to ROSAlloc in the zygote. This caused excessive memory usage. Added the method verifiers as roots to fix an issue caused by RegTypes holding a Class*. Added logic to clear card table in the SemiSpace collector, this reduces DalvikOther from ~2400k -> ~1760k when using the SemiSpace collector. Added a missing lock to the timing loggers which caused a rare one time crash in std::set. Bug: 11771255 Bug: 8499494 Bug: 10802951 Change-Id: I99d2b528cd51c1c5ed7012e3220b3aefded680ae
Diffstat (limited to 'runtime')
-rw-r--r--runtime/base/timing_logger.cc2
-rw-r--r--runtime/base/timing_logger.h7
-rw-r--r--runtime/class_linker.cc313
-rw-r--r--runtime/class_linker.h98
-rw-r--r--runtime/class_linker_test.cc103
-rw-r--r--runtime/debugger.cc18
-rw-r--r--runtime/entrypoints/entrypoint_utils.h22
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.cc6
-rw-r--r--runtime/entrypoints/portable/portable_trampoline_entrypoints.cc6
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc6
-rw-r--r--runtime/exception_test.cc8
-rw-r--r--runtime/gc/accounting/card_table.cc4
-rw-r--r--runtime/gc/accounting/mod_union_table.cc2
-rw-r--r--runtime/gc/collector/mark_sweep-inl.h7
-rw-r--r--runtime/gc/collector/mark_sweep.h8
-rw-r--r--runtime/gc/collector/semi_space.cc11
-rw-r--r--runtime/gc/heap-inl.h41
-rw-r--r--runtime/gc/heap.cc14
-rw-r--r--runtime/gc/heap.h21
-rw-r--r--runtime/globals.h2
-rw-r--r--runtime/interpreter/interpreter.cc7
-rw-r--r--runtime/interpreter/interpreter_common.h7
-rw-r--r--runtime/jni_internal.cc54
-rw-r--r--runtime/mirror/array-inl.h7
-rw-r--r--runtime/mirror/array.h3
-rw-r--r--runtime/mirror/art_field.cc7
-rw-r--r--runtime/mirror/art_field.h2
-rw-r--r--runtime/mirror/art_method.cc7
-rw-r--r--runtime/mirror/art_method.h4
-rw-r--r--runtime/mirror/class.cc6
-rw-r--r--runtime/mirror/class.h2
-rw-r--r--runtime/mirror/object.h10
-rw-r--r--runtime/mirror/stack_trace_element.cc7
-rw-r--r--runtime/mirror/stack_trace_element.h3
-rw-r--r--runtime/mirror/string.cc27
-rw-r--r--runtime/mirror/string.h15
-rw-r--r--runtime/mirror/throwable.cc6
-rw-r--r--runtime/mirror/throwable.h3
-rw-r--r--runtime/native/java_lang_Class.cc14
-rw-r--r--runtime/native/java_lang_reflect_Constructor.cc12
-rw-r--r--runtime/native/java_lang_reflect_Field.cc22
-rw-r--r--runtime/object_utils.h18
-rw-r--r--runtime/reflection.cc8
-rw-r--r--runtime/runtime.cc73
-rw-r--r--runtime/runtime.h18
-rw-r--r--runtime/thread.cc17
-rw-r--r--runtime/throw_location.cc7
-rw-r--r--runtime/verifier/method_verifier.cc6
-rw-r--r--runtime/verifier/method_verifier.h2
-rw-r--r--runtime/verifier/reg_type.cc6
-rw-r--r--runtime/verifier/reg_type.h5
-rw-r--r--runtime/verifier/reg_type_cache.cc6
-rw-r--r--runtime/verifier/reg_type_cache.h3
53 files changed, 658 insertions, 435 deletions
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index c8dee6d..bb32b2d 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -43,6 +43,7 @@ CumulativeLogger::~CumulativeLogger() {
}
void CumulativeLogger::SetName(const std::string& name) {
+ MutexLock mu(Thread::Current(), lock_);
name_.assign(name);
}
@@ -61,6 +62,7 @@ void CumulativeLogger::Reset() {
}
uint64_t CumulativeLogger::GetTotalNs() const {
+ MutexLock mu(Thread::Current(), lock_);
return GetTotalTime() * kAdjust;
}
diff --git a/runtime/base/timing_logger.h b/runtime/base/timing_logger.h
index c1ff0a3..b0bcf10 100644
--- a/runtime/base/timing_logger.h
+++ b/runtime/base/timing_logger.h
@@ -31,16 +31,15 @@ class TimingLogger;
class CumulativeLogger {
public:
explicit CumulativeLogger(const std::string& name);
- void prepare_stats();
~CumulativeLogger();
void Start();
- void End();
- void Reset();
+ void End() LOCKS_EXCLUDED(lock_);
+ void Reset() LOCKS_EXCLUDED(lock_);
void Dump(std::ostream& os) LOCKS_EXCLUDED(lock_);
uint64_t GetTotalNs() const;
// Allow the name to be modified, particularly when the cumulative logger is a field within a
// parent class that is unable to determine the "name" of a sub-class.
- void SetName(const std::string& name);
+ void SetName(const std::string& name) LOCKS_EXCLUDED(lock_);
void AddLogger(const TimingLogger& logger) LOCKS_EXCLUDED(lock_);
size_t GetIterations() const;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 500cb59..3e5d90d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -530,7 +530,8 @@ void ClassLinker::RunRootClinits() {
for (size_t i = 0; i < ClassLinker::kClassRootsMax; ++i) {
mirror::Class* c = GetClassRoot(ClassRoot(i));
if (!c->IsArrayClass() && !c->IsPrimitive()) {
- EnsureInitialized(GetClassRoot(ClassRoot(i)), true, true);
+ SirtRef<mirror::Class> sirt_class(self, GetClassRoot(ClassRoot(i)));
+ EnsureInitialized(sirt_class, true, true);
self->AssertNoPendingException();
}
}
@@ -1133,7 +1134,7 @@ void ClassLinker::VisitRoots(RootVisitor* visitor, void* arg, bool only_dirty, b
}
{
- ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
+ WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
if (!only_dirty || class_table_dirty_) {
for (std::pair<const size_t, mirror::Class*>& it : class_table_) {
it.second = down_cast<mirror::Class*>(visitor(it.second, arg));
@@ -1156,7 +1157,7 @@ void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) {
if (dex_cache_image_class_lookup_required_) {
MoveImageClassesToClassTable();
}
- ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
+ WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
for (const std::pair<size_t, mirror::Class*>& it : class_table_) {
if (!visitor(it.second, arg)) {
return;
@@ -1249,7 +1250,10 @@ mirror::Class* ClassLinker::AllocClass(Thread* self, mirror::Class* java_lang_Cl
size_t class_size) {
DCHECK_GE(class_size, sizeof(mirror::Class));
gc::Heap* heap = Runtime::Current()->GetHeap();
- mirror::Object* k = heap->AllocNonMovableObject<true>(self, java_lang_Class, class_size);
+ mirror::Object* k =
+ kMovingClasses ?
+ heap->AllocObject<true>(self, java_lang_Class, class_size) :
+ heap->AllocNonMovableObject<true>(self, java_lang_Class, class_size);
if (UNLIKELY(k == NULL)) {
CHECK(self->IsExceptionPending()); // OOME.
return NULL;
@@ -1287,21 +1291,23 @@ static mirror::Class* EnsureResolved(Thread* self, mirror::Class* klass)
DCHECK(klass != NULL);
// Wait for the class if it has not already been linked.
if (!klass->IsResolved() && !klass->IsErroneous()) {
- ObjectLock lock(self, klass);
+ SirtRef<mirror::Class> sirt_class(self, klass);
+ ObjectLock<mirror::Class> lock(self, &sirt_class);
// Check for circular dependencies between classes.
- if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
- ThrowClassCircularityError(klass);
- klass->SetStatus(mirror::Class::kStatusError, self);
- return NULL;
+ if (!sirt_class->IsResolved() && sirt_class->GetClinitThreadId() == self->GetTid()) {
+ ThrowClassCircularityError(sirt_class.get());
+ sirt_class->SetStatus(mirror::Class::kStatusError, self);
+ return nullptr;
}
// Wait for the pending initialization to complete.
- while (!klass->IsResolved() && !klass->IsErroneous()) {
+ while (!sirt_class->IsResolved() && !sirt_class->IsErroneous()) {
lock.WaitIgnoringInterrupts();
}
+ klass = sirt_class.get();
}
if (klass->IsErroneous()) {
ThrowEarlierClassFailure(klass);
- return NULL;
+ return nullptr;
}
// Return the loaded class. No exceptions should be pending.
CHECK(klass->IsResolved()) << PrettyClass(klass);
@@ -1320,7 +1326,7 @@ mirror::Class* ClassLinker::FindSystemClass(const char* descriptor) {
}
mirror::Class* ClassLinker::FindClass(const char* descriptor,
- SirtRef<mirror::ClassLoader>& class_loader) {
+ const SirtRef<mirror::ClassLoader>& class_loader) {
DCHECK_NE(*descriptor, '\0') << "descriptor is empty string";
Thread* self = Thread::Current();
DCHECK(self != NULL);
@@ -1403,7 +1409,7 @@ mirror::Class* ClassLinker::FindClass(const char* descriptor,
}
mirror::Class* ClassLinker::DefineClass(const char* descriptor,
- SirtRef<mirror::ClassLoader>& class_loader,
+ const SirtRef<mirror::ClassLoader>& class_loader,
const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def) {
Thread* self = Thread::Current();
@@ -1440,7 +1446,7 @@ mirror::Class* ClassLinker::DefineClass(const char* descriptor,
klass->SetStatus(mirror::Class::kStatusError, self);
return NULL;
}
- ObjectLock lock(self, klass.get());
+ ObjectLock<mirror::Class> lock(self, &klass);
klass->SetClinitThreadId(self->GetTid());
// Add the newly loaded class to the loaded classes table.
mirror::Class* existing = InsertClass(descriptor, klass.get(), Hash(descriptor));
@@ -1695,7 +1701,7 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
// Ignore virtual methods on the iterator.
}
-static void LinkCode(SirtRef<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
+static void LinkCode(const SirtRef<mirror::ArtMethod>& method, const OatFile::OatClass* oat_class,
uint32_t method_index)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
// Method shouldn't have already been linked.
@@ -1741,7 +1747,7 @@ static void LinkCode(SirtRef<mirror::ArtMethod>& method, const OatFile::OatClass
void ClassLinker::LoadClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
- SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::Class>& klass,
mirror::ClassLoader* class_loader) {
CHECK(klass.get() != NULL);
CHECK(klass->GetDexCache() != NULL);
@@ -1861,7 +1867,8 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
}
void ClassLinker::LoadField(const DexFile& /*dex_file*/, const ClassDataItemIterator& it,
- SirtRef<mirror::Class>& klass, SirtRef<mirror::ArtField>& dst) {
+ const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ArtField>& dst) {
uint32_t field_idx = it.GetMemberIndex();
dst->SetDexFieldIndex(field_idx);
dst->SetDeclaringClass(klass.get());
@@ -1870,7 +1877,7 @@ void ClassLinker::LoadField(const DexFile& /*dex_file*/, const ClassDataItemIter
mirror::ArtMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file,
const ClassDataItemIterator& it,
- SirtRef<mirror::Class>& klass) {
+ const SirtRef<mirror::Class>& klass) {
uint32_t dex_method_idx = it.GetMemberIndex();
const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
@@ -1941,7 +1948,8 @@ void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
AppendToBootClassPath(dex_file, dex_cache);
}
-void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
+void ClassLinker::AppendToBootClassPath(const DexFile& dex_file,
+ const SirtRef<mirror::DexCache>& dex_cache) {
CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
boot_class_path_.push_back(&dex_file);
RegisterDexFile(dex_file, dex_cache);
@@ -1962,7 +1970,8 @@ bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) const {
return IsDexFileRegisteredLocked(dex_file);
}
-void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
+void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
+ const SirtRef<mirror::DexCache>& dex_cache) {
dex_lock_.AssertExclusiveHeld(Thread::Current());
CHECK(dex_cache.get() != NULL) << dex_file.GetLocation();
CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation()))
@@ -1994,7 +2003,8 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
}
}
-void ClassLinker::RegisterDexFile(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache) {
+void ClassLinker::RegisterDexFile(const DexFile& dex_file,
+ const SirtRef<mirror::DexCache>& dex_cache) {
WriterMutexLock mu(Thread::Current(), dex_lock_);
RegisterDexFileLocked(dex_file, dex_cache);
}
@@ -2040,11 +2050,13 @@ mirror::Class* ClassLinker::CreatePrimitiveClass(Thread* self, Primitive::Type t
return InitializePrimitiveClass(klass, type);
}
-mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class, Primitive::Type type) {
+mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_class,
+ Primitive::Type type) {
CHECK(primitive_class != NULL);
// Must hold lock on object when initializing.
Thread* self = Thread::Current();
- ObjectLock lock(self, primitive_class);
+ SirtRef<mirror::Class> sirt_class(self, primitive_class);
+ ObjectLock<mirror::Class> lock(self, &sirt_class);
primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
primitive_class->SetPrimitiveType(type);
primitive_class->SetStatus(mirror::Class::kStatusInitialized, self);
@@ -2068,7 +2080,7 @@ mirror::Class* ClassLinker::InitializePrimitiveClass(mirror::Class* primitive_cl
//
// Returns NULL with an exception raised on failure.
mirror::Class* ClassLinker::CreateArrayClass(const char* descriptor,
- SirtRef<mirror::ClassLoader>& class_loader) {
+ const SirtRef<mirror::ClassLoader>& class_loader) {
// Identify the underlying component type
CHECK_EQ('[', descriptor[0]);
mirror::Class* component_type = FindClass(descriptor + 1, class_loader);
@@ -2138,7 +2150,7 @@ mirror::Class* ClassLinker::CreateArrayClass(const char* descriptor,
}
new_class->SetComponentType(component_type);
}
- ObjectLock lock(self, new_class.get()); // Must hold lock on object when initializing.
+ ObjectLock<mirror::Class> lock(self, &new_class); // Must hold lock on object when initializing.
DCHECK(new_class->GetComponentType() != NULL);
mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject);
new_class->SetSuperClass(java_lang_Object);
@@ -2421,10 +2433,10 @@ void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Clas
}
}
-void ClassLinker::VerifyClass(mirror::Class* klass) {
+void ClassLinker::VerifyClass(const SirtRef<mirror::Class>& klass) {
// TODO: assert that the monitor on the Class is held
Thread* self = Thread::Current();
- ObjectLock lock(self, klass);
+ ObjectLock<mirror::Class> lock(self, &klass);
// Don't attempt to re-verify if already sufficiently verified.
if (klass->IsVerified() ||
@@ -2435,7 +2447,7 @@ void ClassLinker::VerifyClass(mirror::Class* klass) {
// The class might already be erroneous, for example at compile time if we attempted to verify
// this class as a parent to another.
if (klass->IsErroneous()) {
- ThrowEarlierClassFailure(klass);
+ ThrowEarlierClassFailure(klass.get());
return;
}
@@ -2443,7 +2455,7 @@ void ClassLinker::VerifyClass(mirror::Class* klass) {
klass->SetStatus(mirror::Class::kStatusVerifying, self);
} else {
CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime)
- << PrettyClass(klass);
+ << PrettyClass(klass.get());
CHECK(!Runtime::Current()->IsCompiler());
klass->SetStatus(mirror::Class::kStatusVerifyingAtRuntime, self);
}
@@ -2452,23 +2464,23 @@ void ClassLinker::VerifyClass(mirror::Class* klass) {
SirtRef<mirror::Class> super(self, klass->GetSuperClass());
if (super.get() != NULL) {
// Acquire lock to prevent races on verifying the super class.
- ObjectLock lock(self, super.get());
+ ObjectLock<mirror::Class> lock(self, &super);
if (!super->IsVerified() && !super->IsErroneous()) {
- VerifyClass(super.get());
+ VerifyClass(super);
}
if (!super->IsCompileTimeVerified()) {
std::string error_msg(StringPrintf("Rejecting class %s that attempts to sub-class erroneous class %s",
- PrettyDescriptor(klass).c_str(),
+ PrettyDescriptor(klass.get()).c_str(),
PrettyDescriptor(super.get()).c_str()));
LOG(ERROR) << error_msg << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
SirtRef<mirror::Throwable> cause(self, self->GetException(NULL));
- if (cause.get() != NULL) {
+ if (cause.get() != nullptr) {
self->ClearException();
}
- ThrowVerifyError(klass, "%s", error_msg.c_str());
- if (cause.get() != NULL) {
- self->GetException(NULL)->SetCause(cause.get());
+ ThrowVerifyError(klass.get(), "%s", error_msg.c_str());
+ if (cause.get() != nullptr) {
+ self->GetException(nullptr)->SetCause(cause.get());
}
klass->SetStatus(mirror::Class::kStatusError, self);
return;
@@ -2478,26 +2490,26 @@ void ClassLinker::VerifyClass(mirror::Class* klass) {
// Try to use verification information from the oat file, otherwise do runtime verification.
const DexFile& dex_file = *klass->GetDexCache()->GetDexFile();
mirror::Class::Status oat_file_class_status(mirror::Class::kStatusNotReady);
- bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
+ bool preverified = VerifyClassUsingOatFile(dex_file, klass.get(), oat_file_class_status);
if (oat_file_class_status == mirror::Class::kStatusError) {
VLOG(class_linker) << "Skipping runtime verification of erroneous class "
- << PrettyDescriptor(klass) << " in "
+ << PrettyDescriptor(klass.get()) << " in "
<< klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
- ThrowVerifyError(klass, "Rejecting class %s because it failed compile-time verification",
- PrettyDescriptor(klass).c_str());
+ ThrowVerifyError(klass.get(), "Rejecting class %s because it failed compile-time verification",
+ PrettyDescriptor(klass.get()).c_str());
klass->SetStatus(mirror::Class::kStatusError, self);
return;
}
verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
std::string error_msg;
if (!preverified) {
- verifier_failure = verifier::MethodVerifier::VerifyClass(klass,
+ verifier_failure = verifier::MethodVerifier::VerifyClass(klass.get(),
Runtime::Current()->IsCompiler(),
&error_msg);
}
if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) {
- VLOG(class_linker) << "Soft verification failure in class " << PrettyDescriptor(klass)
+ VLOG(class_linker) << "Soft verification failure in class " << PrettyDescriptor(klass.get())
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
<< " because: " << error_msg;
}
@@ -2527,11 +2539,11 @@ void ClassLinker::VerifyClass(mirror::Class* klass) {
}
}
} else {
- LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(klass)
+ LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(klass.get())
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
<< " because: " << error_msg;
self->AssertNoPendingException();
- ThrowVerifyError(klass, "%s", error_msg.c_str());
+ ThrowVerifyError(klass.get(), "%s", error_msg.c_str());
klass->SetStatus(mirror::Class::kStatusError, self);
}
if (preverified || verifier_failure == verifier::MethodVerifier::kNoFailure) {
@@ -2625,7 +2637,8 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class
return false;
}
-void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file, mirror::Class* klass) {
+void ClassLinker::ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
+ const SirtRef<mirror::Class>& klass) {
for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
ResolveMethodExceptionHandlerTypes(dex_file, klass->GetDirectMethod(i));
}
@@ -2763,13 +2776,13 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccess& soa, jstring na
self->AssertNoPendingException();
{
- ObjectLock lock(self, klass.get()); // Must hold lock on object when resolved.
+ ObjectLock<mirror::Class> lock(self, &klass); // Must hold lock on object when resolved.
// Link the fields and virtual methods, creating vtable and iftables
SirtRef<mirror::ObjectArray<mirror::Class> > sirt_interfaces(
self, soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
if (!LinkClass(self, klass, sirt_interfaces)) {
klass->SetStatus(mirror::Class::kStatusError, self);
- return NULL;
+ return nullptr;
}
interfaces_sfield->SetObject(klass.get(), soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
@@ -2840,7 +2853,7 @@ mirror::ArtMethod* ClassLinker::FindMethodForProxy(const mirror::Class* proxy_cl
mirror::ArtMethod* ClassLinker::CreateProxyConstructor(Thread* self,
- SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::Class>& klass,
mirror::Class* proxy_class) {
// Create constructor for Proxy that must initialize h
mirror::ObjectArray<mirror::ArtMethod>* proxy_direct_methods =
@@ -2870,8 +2883,9 @@ static void CheckProxyConstructor(mirror::ArtMethod* constructor)
DCHECK(constructor->IsPublic());
}
-mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<mirror::Class>& klass,
- SirtRef<mirror::ArtMethod>& prototype) {
+mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self,
+ const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ArtMethod>& prototype) {
// Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
// prototype method
prototype->GetDeclaringClass()->GetDexCache()->SetResolvedMethod(prototype->GetDexMethodIndex(),
@@ -2966,7 +2980,7 @@ bool ClassLinker::IsInitialized() const {
return init_done_;
}
-bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
+bool ClassLinker::InitializeClass(const SirtRef<mirror::Class>& klass, bool can_init_statics,
bool can_init_parents) {
// see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
@@ -2978,14 +2992,14 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
}
// Fast fail if initialization requires a full runtime. Not part of the JLS.
- if (!CanWeInitializeClass(klass, can_init_statics, can_init_parents)) {
+ if (!CanWeInitializeClass(klass.get(), can_init_statics, can_init_parents)) {
return false;
}
Thread* self = Thread::Current();
uint64_t t0;
{
- ObjectLock lock(self, klass);
+ ObjectLock<mirror::Class> lock(self, &klass);
// Re-check under the lock in case another thread initialized ahead of us.
if (klass->IsInitialized()) {
@@ -2994,11 +3008,11 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
// Was the class already found to be erroneous? Done under the lock to match the JLS.
if (klass->IsErroneous()) {
- ThrowEarlierClassFailure(klass);
+ ThrowEarlierClassFailure(klass.get());
return false;
}
- CHECK(klass->IsResolved()) << PrettyClass(klass) << ": state=" << klass->GetStatus();
+ CHECK(klass->IsResolved()) << PrettyClass(klass.get()) << ": state=" << klass->GetStatus();
if (!klass->IsVerified()) {
VerifyClass(klass);
@@ -3035,7 +3049,7 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
return false;
}
- CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass);
+ CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusVerified) << PrettyClass(klass.get());
// From here out other threads may observe that we're initializing and so changes of state
// require the a notification.
@@ -3051,16 +3065,17 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
if (!super_class->IsInitialized()) {
CHECK(!super_class->IsInterface());
CHECK(can_init_parents);
- bool super_initialized = InitializeClass(super_class, can_init_statics, true);
+ SirtRef<mirror::Class> sirt_super(self, super_class);
+ bool super_initialized = InitializeClass(sirt_super, can_init_statics, true);
if (!super_initialized) {
// The super class was verified ahead of entering initializing, we should only be here if
// the super class became erroneous due to initialization.
- CHECK(super_class->IsErroneous() && self->IsExceptionPending())
- << "Super class initialization failed for " << PrettyDescriptor(super_class)
- << " that has unexpected status " << super_class->GetStatus()
+ CHECK(sirt_super->IsErroneous() && self->IsExceptionPending())
+ << "Super class initialization failed for " << PrettyDescriptor(sirt_super.get())
+ << " that has unexpected status " << sirt_super->GetStatus()
<< "\nPending exception:\n"
<< (self->GetException(NULL) != NULL ? self->GetException(NULL)->Dump() : "");
- ObjectLock lock(self, klass);
+ ObjectLock<mirror::Class> lock(self, &klass);
// Initialization failed because the super-class is erroneous.
klass->SetStatus(mirror::Class::kStatusError, self);
return false;
@@ -3069,7 +3084,7 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
}
if (klass->NumStaticFields() > 0) {
- ClassHelper kh(klass);
+ ClassHelper kh(klass.get());
const DexFile::ClassDef* dex_class_def = kh.GetClassDef();
CHECK(dex_class_def != NULL);
const DexFile& dex_file = kh.GetDexFile();
@@ -3081,7 +3096,7 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
CHECK(can_init_statics);
// We reordered the fields, so we need to be able to map the field indexes to the right fields.
SafeMap<uint32_t, mirror::ArtField*> field_map;
- ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
+ ConstructFieldMap(dex_file, *dex_class_def, klass.get(), field_map);
for (size_t i = 0; it.HasNext(); i++, it.Next()) {
it.ReadValueToField(field_map.Get(i));
}
@@ -3100,13 +3115,13 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
}
// Opportunistically set static method trampolines to their destination.
- FixupStaticTrampolines(klass);
+ FixupStaticTrampolines(klass.get());
uint64_t t1 = NanoTime();
bool success = true;
{
- ObjectLock lock(self, klass);
+ ObjectLock<mirror::Class> lock(self, &klass);
if (self->IsExceptionPending()) {
WrapExceptionInInitializer();
@@ -3122,7 +3137,7 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
// Set the class as initialized except if failed to initialize static fields.
klass->SetStatus(mirror::Class::kStatusInitialized, self);
if (VLOG_IS_ON(class_linker)) {
- ClassHelper kh(klass);
+ ClassHelper kh(klass.get());
LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
}
}
@@ -3130,7 +3145,8 @@ bool ClassLinker::InitializeClass(mirror::Class* klass, bool can_init_statics,
return success;
}
-bool ClassLinker::WaitForInitializeClass(mirror::Class* klass, Thread* self, ObjectLock& lock)
+bool ClassLinker::WaitForInitializeClass(const SirtRef<mirror::Class>& klass, Thread* self,
+ ObjectLock<mirror::Class>& lock)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
while (true) {
self->AssertNoPendingException();
@@ -3157,47 +3173,49 @@ bool ClassLinker::WaitForInitializeClass(mirror::Class* klass, Thread* self, Obj
// The caller wants an exception, but it was thrown in a
// different thread. Synthesize one here.
ThrowNoClassDefFoundError("<clinit> failed for class %s; see exception in other thread",
- PrettyDescriptor(klass).c_str());
+ PrettyDescriptor(klass.get()).c_str());
return false;
}
if (klass->IsInitialized()) {
return true;
}
- LOG(FATAL) << "Unexpected class status. " << PrettyClass(klass) << " is " << klass->GetStatus();
+ LOG(FATAL) << "Unexpected class status. " << PrettyClass(klass.get()) << " is "
+ << klass->GetStatus();
}
- LOG(FATAL) << "Not Reached" << PrettyClass(klass);
+ LOG(FATAL) << "Not Reached" << PrettyClass(klass.get());
}
-bool ClassLinker::ValidateSuperClassDescriptors(const mirror::Class* klass) {
+bool ClassLinker::ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& klass) {
if (klass->IsInterface()) {
return true;
}
+ Thread* self = Thread::Current();
// begin with the methods local to the superclass
if (klass->HasSuperClass() &&
klass->GetClassLoader() != klass->GetSuperClass()->GetClassLoader()) {
- const mirror::Class* super = klass->GetSuperClass();
+ SirtRef<mirror::Class> super(self, klass->GetSuperClass());
for (int i = super->GetVTable()->GetLength() - 1; i >= 0; --i) {
const mirror::ArtMethod* method = klass->GetVTable()->Get(i);
if (method != super->GetVTable()->Get(i) &&
- !IsSameMethodSignatureInDifferentClassContexts(method, super, klass)) {
- ThrowLinkageError(klass, "Class %s method %s resolves differently in superclass %s",
- PrettyDescriptor(klass).c_str(), PrettyMethod(method).c_str(),
- PrettyDescriptor(super).c_str());
+ !IsSameMethodSignatureInDifferentClassContexts(method, super.get(), klass.get())) {
+ ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in superclass %s",
+ PrettyDescriptor(klass.get()).c_str(), PrettyMethod(method).c_str(),
+ PrettyDescriptor(super.get()).c_str());
return false;
}
}
}
for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
- mirror::Class* interface = klass->GetIfTable()->GetInterface(i);
+ SirtRef<mirror::Class> interface(self, klass->GetIfTable()->GetInterface(i));
if (klass->GetClassLoader() != interface->GetClassLoader()) {
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
const mirror::ArtMethod* method = klass->GetIfTable()->GetMethodArray(i)->Get(j);
- if (!IsSameMethodSignatureInDifferentClassContexts(method, interface,
+ if (!IsSameMethodSignatureInDifferentClassContexts(method, interface.get(),
method->GetDeclaringClass())) {
- ThrowLinkageError(klass, "Class %s method %s resolves differently in interface %s",
+ ThrowLinkageError(klass.get(), "Class %s method %s resolves differently in interface %s",
PrettyDescriptor(method->GetDeclaringClass()).c_str(),
PrettyMethod(method).c_str(),
- PrettyDescriptor(interface).c_str());
+ PrettyDescriptor(interface.get()).c_str());
return false;
}
}
@@ -3214,17 +3232,22 @@ bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const mirror::Ar
if (klass1 == klass2) {
return true;
}
+ Thread* self = Thread::Current();
+ CHECK(klass1 != nullptr);
+ CHECK(klass2 != nullptr);
+ SirtRef<mirror::ClassLoader> loader1(self, klass1->GetClassLoader());
+ SirtRef<mirror::ClassLoader> loader2(self, klass2->GetClassLoader());
const DexFile& dex_file = *method->GetDeclaringClass()->GetDexCache()->GetDexFile();
const DexFile::ProtoId& proto_id =
dex_file.GetMethodPrototype(dex_file.GetMethodId(method->GetDexMethodIndex()));
for (DexFileParameterIterator it(dex_file, proto_id); it.HasNext(); it.Next()) {
const char* descriptor = it.GetDescriptor();
- if (descriptor == NULL) {
+ if (descriptor == nullptr) {
break;
}
if (descriptor[0] == 'L' || descriptor[0] == '[') {
// Found a non-primitive type.
- if (!IsSameDescriptorInDifferentClassContexts(descriptor, klass1, klass2)) {
+ if (!IsSameDescriptorInDifferentClassContexts(descriptor, loader1, loader2)) {
return false;
}
}
@@ -3232,47 +3255,42 @@ bool ClassLinker::IsSameMethodSignatureInDifferentClassContexts(const mirror::Ar
// Check the return type
const char* descriptor = dex_file.GetReturnTypeDescriptor(proto_id);
if (descriptor[0] == 'L' || descriptor[0] == '[') {
- if (!IsSameDescriptorInDifferentClassContexts(descriptor, klass1, klass2)) {
+ if (!IsSameDescriptorInDifferentClassContexts(descriptor, loader1, loader2)) {
return false;
}
}
return true;
}
-// Returns true if the descriptor resolves to the same class in the context of klass1 and klass2.
+// Returns true if the descriptor resolves to the same class in the context of loader1 and loader2.
bool ClassLinker::IsSameDescriptorInDifferentClassContexts(const char* descriptor,
- const mirror::Class* klass1,
- const mirror::Class* klass2) {
- CHECK(descriptor != NULL);
- CHECK(klass1 != NULL);
- CHECK(klass2 != NULL);
- if (klass1 == klass2) {
- return true;
- }
+ SirtRef<mirror::ClassLoader>& loader1,
+ SirtRef<mirror::ClassLoader>& loader2) {
+ CHECK(descriptor != nullptr);
Thread* self = Thread::Current();
- SirtRef<mirror::ClassLoader> class_loader1(self, klass1->GetClassLoader());
- mirror::Class* found1 = FindClass(descriptor, class_loader1);
- if (found1 == NULL) {
- Thread::Current()->ClearException();
+ SirtRef<mirror::Class> found1(self, FindClass(descriptor, loader1));
+ if (found1.get() == nullptr) {
+ self->ClearException();
}
- SirtRef<mirror::ClassLoader> class_loader2(self, klass2->GetClassLoader());
- mirror::Class* found2 = FindClass(descriptor, class_loader2);
- if (found2 == NULL) {
- Thread::Current()->ClearException();
+ mirror::Class* found2 = FindClass(descriptor, loader2);
+ if (found2 == nullptr) {
+ self->ClearException();
}
- return found1 == found2;
+ return found1.get() == found2;
}
-bool ClassLinker::EnsureInitialized(mirror::Class* c, bool can_init_fields, bool can_init_parents) {
- DCHECK(c != NULL);
+bool ClassLinker::EnsureInitialized(const SirtRef<mirror::Class>& c, bool can_init_fields,
+ bool can_init_parents) {
+ DCHECK(c.get() != NULL);
if (c->IsInitialized()) {
return true;
}
bool success = InitializeClass(c, can_init_fields, can_init_parents);
if (!success) {
- Thread* self = Thread::Current();
- CHECK(self->IsExceptionPending() || !can_init_fields || !can_init_parents) << PrettyClass(c);
+ if (can_init_fields && can_init_parents) {
+ CHECK(Thread::Current()->IsExceptionPending()) << PrettyClass(c.get());
+ }
}
return success;
}
@@ -3285,13 +3303,14 @@ void ClassLinker::ConstructFieldMap(const DexFile& dex_file, const DexFile::Clas
Thread* self = Thread::Current();
SirtRef<mirror::DexCache> dex_cache(self, c->GetDexCache());
SirtRef<mirror::ClassLoader> class_loader(self, c->GetClassLoader());
+ CHECK(!kMovingFields);
for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
field_map.Put(i, ResolveField(dex_file, it.GetMemberIndex(), dex_cache, class_loader, true));
}
}
-bool ClassLinker::LinkClass(Thread* self, SirtRef<mirror::Class>& klass,
- SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
+bool ClassLinker::LinkClass(Thread* self, const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
CHECK_EQ(mirror::Class::kStatusLoaded, klass->GetStatus());
if (!LinkSuperClass(klass)) {
return false;
@@ -3312,7 +3331,8 @@ bool ClassLinker::LinkClass(Thread* self, SirtRef<mirror::Class>& klass,
return true;
}
-bool ClassLinker::LoadSuperAndInterfaces(SirtRef<mirror::Class>& klass, const DexFile& dex_file) {
+bool ClassLinker::LoadSuperAndInterfaces(const SirtRef<mirror::Class>& klass,
+ const DexFile& dex_file) {
CHECK_EQ(mirror::Class::kStatusIdx, klass->GetStatus());
const DexFile::ClassDef& class_def = dex_file.GetClassDef(klass->GetDexClassDefIndex());
uint16_t super_class_idx = class_def.superclass_idx_;
@@ -3355,7 +3375,7 @@ bool ClassLinker::LoadSuperAndInterfaces(SirtRef<mirror::Class>& klass, const De
return true;
}
-bool ClassLinker::LinkSuperClass(SirtRef<mirror::Class>& klass) {
+bool ClassLinker::LinkSuperClass(const SirtRef<mirror::Class>& klass) {
CHECK(!klass->IsPrimitive());
mirror::Class* super = klass->GetSuperClass();
if (klass.get() == GetClassRoot(kJavaLangObject)) {
@@ -3414,8 +3434,8 @@ bool ClassLinker::LinkSuperClass(SirtRef<mirror::Class>& klass) {
}
// Populate the class vtable and itable. Compute return type indices.
-bool ClassLinker::LinkMethods(SirtRef<mirror::Class>& klass,
- SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
+bool ClassLinker::LinkMethods(const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
if (klass->IsInterface()) {
// No vtable.
size_t count = klass->NumVirtualMethods();
@@ -3435,7 +3455,7 @@ bool ClassLinker::LinkMethods(SirtRef<mirror::Class>& klass,
return true;
}
-bool ClassLinker::LinkVirtualMethods(SirtRef<mirror::Class>& klass) {
+bool ClassLinker::LinkVirtualMethods(const SirtRef<mirror::Class>& klass) {
Thread* self = Thread::Current();
if (klass->HasSuperClass()) {
uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->GetVTable()->GetLength();
@@ -3518,8 +3538,8 @@ bool ClassLinker::LinkVirtualMethods(SirtRef<mirror::Class>& klass) {
return true;
}
-bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
- SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
+bool ClassLinker::LinkInterfaceMethods(const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces) {
// Set the imt table to be all conflicts by default.
klass->SetImTable(Runtime::Current()->GetDefaultImt());
size_t super_ifcount;
@@ -3529,14 +3549,17 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
super_ifcount = 0;
}
size_t ifcount = super_ifcount;
- ClassHelper kh(klass.get());
- uint32_t num_interfaces =
- interfaces.get() == nullptr ? kh.NumDirectInterfaces() : interfaces->GetLength();
- ifcount += num_interfaces;
- for (size_t i = 0; i < num_interfaces; i++) {
- mirror::Class* interface =
- interfaces.get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
- ifcount += interface->GetIfTableCount();
+ uint32_t num_interfaces;
+ {
+ ClassHelper kh(klass.get());
+ num_interfaces =
+ interfaces.get() == nullptr ? kh.NumDirectInterfaces() : interfaces->GetLength();
+ ifcount += num_interfaces;
+ for (size_t i = 0; i < num_interfaces; i++) {
+ mirror::Class* interface =
+ interfaces.get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
+ ifcount += interface->GetIfTableCount();
+ }
}
if (ifcount == 0) {
// Class implements no interfaces.
@@ -3576,6 +3599,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
// Flatten the interface inheritance hierarchy.
size_t idx = super_ifcount;
for (size_t i = 0; i < num_interfaces; i++) {
+ ClassHelper kh(klass.get());
mirror::Class* interface =
interfaces.get() == nullptr ? kh.GetDirectInterface(i) : interfaces->Get(i);
DCHECK(interface != NULL);
@@ -3640,11 +3664,8 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
return false;
}
std::vector<mirror::ArtMethod*> miranda_list;
- MethodHelper vtable_mh(NULL);
- MethodHelper interface_mh(NULL);
for (size_t i = 0; i < ifcount; ++i) {
- mirror::Class* interface = iftable->GetInterface(i);
- size_t num_methods = interface->NumVirtualMethods();
+ size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods();
if (num_methods > 0) {
SirtRef<mirror::ObjectArray<mirror::ArtMethod> >
method_array(self, AllocArtMethodArray(self, num_methods));
@@ -3656,8 +3677,8 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
SirtRef<mirror::ObjectArray<mirror::ArtMethod> > vtable(self,
klass->GetVTableDuringLinking());
for (size_t j = 0; j < num_methods; ++j) {
- mirror::ArtMethod* interface_method = interface->GetVirtualMethod(j);
- interface_mh.ChangeMethod(interface_method);
+ mirror::ArtMethod* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j);
+ MethodHelper interface_mh(interface_method);
int32_t k;
// For each method listed in the interface's method list, find the
// matching method in our class's method list. We want to favor the
@@ -3669,7 +3690,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
// matter which direction we go. We walk it backward anyway.)
for (k = vtable->GetLength() - 1; k >= 0; --k) {
mirror::ArtMethod* vtable_method = vtable->Get(k);
- vtable_mh.ChangeMethod(vtable_method);
+ MethodHelper vtable_mh(vtable_method);
if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
ThrowIllegalAccessError(klass.get(),
@@ -3694,7 +3715,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
SirtRef<mirror::ArtMethod> miranda_method(self, NULL);
for (size_t mir = 0; mir < miranda_list.size(); mir++) {
mirror::ArtMethod* mir_method = miranda_list[mir];
- vtable_mh.ChangeMethod(mir_method);
+ MethodHelper vtable_mh(mir_method);
if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
miranda_method.reset(miranda_list[mir]);
break;
@@ -3772,12 +3793,12 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
return true;
}
-bool ClassLinker::LinkInstanceFields(SirtRef<mirror::Class>& klass) {
+bool ClassLinker::LinkInstanceFields(const SirtRef<mirror::Class>& klass) {
CHECK(klass.get() != NULL);
return LinkFields(klass, false);
}
-bool ClassLinker::LinkStaticFields(SirtRef<mirror::Class>& klass) {
+bool ClassLinker::LinkStaticFields(const SirtRef<mirror::Class>& klass) {
CHECK(klass.get() != NULL);
size_t allocated_class_size = klass->GetClassSize();
bool success = LinkFields(klass, true);
@@ -3813,7 +3834,7 @@ struct LinkFieldsComparator {
}
};
-bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) {
+bool ClassLinker::LinkFields(const SirtRef<mirror::Class>& klass, bool is_static) {
size_t num_fields =
is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
@@ -3972,7 +3993,7 @@ bool ClassLinker::LinkFields(SirtRef<mirror::Class>& klass, bool is_static) {
// Set the bitmap of reference offsets, refOffsets, from the ifields
// list.
-void ClassLinker::CreateReferenceInstanceOffsets(SirtRef<mirror::Class>& klass) {
+void ClassLinker::CreateReferenceInstanceOffsets(const SirtRef<mirror::Class>& klass) {
uint32_t reference_offsets = 0;
mirror::Class* super_class = klass->GetSuperClass();
if (super_class != NULL) {
@@ -3986,11 +4007,11 @@ void ClassLinker::CreateReferenceInstanceOffsets(SirtRef<mirror::Class>& klass)
CreateReferenceOffsets(klass, false, reference_offsets);
}
-void ClassLinker::CreateReferenceStaticOffsets(SirtRef<mirror::Class>& klass) {
+void ClassLinker::CreateReferenceStaticOffsets(const SirtRef<mirror::Class>& klass) {
CreateReferenceOffsets(klass, true, 0);
}
-void ClassLinker::CreateReferenceOffsets(SirtRef<mirror::Class>& klass, bool is_static,
+void ClassLinker::CreateReferenceOffsets(const SirtRef<mirror::Class>& klass, bool is_static,
uint32_t reference_offsets) {
size_t num_reference_fields =
is_static ? klass->NumReferenceStaticFieldsDuringLinking()
@@ -4023,7 +4044,7 @@ void ClassLinker::CreateReferenceOffsets(SirtRef<mirror::Class>& klass, bool is_
}
mirror::String* ClassLinker::ResolveString(const DexFile& dex_file, uint32_t string_idx,
- SirtRef<mirror::DexCache>& dex_cache) {
+ const SirtRef<mirror::DexCache>& dex_cache) {
DCHECK(dex_cache.get() != nullptr);
mirror::String* resolved = dex_cache->GetResolvedString(string_idx);
if (resolved != NULL) {
@@ -4045,8 +4066,8 @@ mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_i
}
mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_idx,
- SirtRef<mirror::DexCache>& dex_cache,
- SirtRef<mirror::ClassLoader>& class_loader) {
+ const SirtRef<mirror::DexCache>& dex_cache,
+ const SirtRef<mirror::ClassLoader>& class_loader) {
DCHECK(dex_cache.get() != NULL);
mirror::Class* resolved = dex_cache->GetResolvedType(type_idx);
if (resolved == NULL) {
@@ -4064,9 +4085,11 @@ mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_i
// Convert a ClassNotFoundException to a NoClassDefFoundError.
SirtRef<mirror::Throwable> cause(self, self->GetException(NULL));
if (cause->InstanceOf(GetClassRoot(kJavaLangClassNotFoundException))) {
+ SirtRef<mirror::Class> sirt_resolved(self, resolved);
Thread::Current()->ClearException();
ThrowNoClassDefFoundError("Failed resolution of: %s", descriptor);
self->GetException(NULL)->SetCause(cause.get());
+ resolved = sirt_resolved.get();
}
}
}
@@ -4077,8 +4100,8 @@ mirror::Class* ClassLinker::ResolveType(const DexFile& dex_file, uint16_t type_i
mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
uint32_t method_idx,
- SirtRef<mirror::DexCache>& dex_cache,
- SirtRef<mirror::ClassLoader>& class_loader,
+ const SirtRef<mirror::DexCache>& dex_cache,
+ const SirtRef<mirror::ClassLoader>& class_loader,
const mirror::ArtMethod* referrer,
InvokeType type) {
DCHECK(dex_cache.get() != NULL);
@@ -4223,8 +4246,8 @@ mirror::ArtMethod* ClassLinker::ResolveMethod(const DexFile& dex_file,
}
mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t field_idx,
- SirtRef<mirror::DexCache>& dex_cache,
- SirtRef<mirror::ClassLoader>& class_loader,
+ const SirtRef<mirror::DexCache>& dex_cache,
+ const SirtRef<mirror::ClassLoader>& class_loader,
bool is_static) {
DCHECK(dex_cache.get() != nullptr);
mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
@@ -4263,8 +4286,8 @@ mirror::ArtField* ClassLinker::ResolveField(const DexFile& dex_file, uint32_t fi
mirror::ArtField* ClassLinker::ResolveFieldJLS(const DexFile& dex_file,
uint32_t field_idx,
- SirtRef<mirror::DexCache>& dex_cache,
- SirtRef<mirror::ClassLoader>& class_loader) {
+ const SirtRef<mirror::DexCache>& dex_cache,
+ const SirtRef<mirror::ClassLoader>& class_loader) {
DCHECK(dex_cache.get() != nullptr);
mirror::ArtField* resolved = dex_cache->GetResolvedField(field_idx);
if (resolved != NULL) {
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 4e2cc06..c0b5e81 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -45,7 +45,7 @@ namespace mirror {
} // namespace mirror
class InternTable;
-class ObjectLock;
+template<class T> class ObjectLock;
class ScopedObjectAccess;
template<class T> class SirtRef;
@@ -72,7 +72,7 @@ class ClassLinker {
// Finds a class by its descriptor, loading it if necessary.
// If class_loader is null, searches boot_class_path_.
- mirror::Class* FindClass(const char* descriptor, SirtRef<mirror::ClassLoader>& class_loader)
+ mirror::Class* FindClass(const char* descriptor, const SirtRef<mirror::ClassLoader>& class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Class* FindSystemClass(const char* descriptor)
@@ -82,7 +82,8 @@ class ClassLinker {
bool IsInitialized() const;
// Define a new a class based on a ClassDef from a DexFile
- mirror::Class* DefineClass(const char* descriptor, SirtRef<mirror::ClassLoader>& class_loader,
+ mirror::Class* DefineClass(const char* descriptor,
+ const SirtRef<mirror::ClassLoader>& class_loader,
const DexFile& dex_file, const DexFile::ClassDef& dex_class_def)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -126,7 +127,7 @@ class ClassLinker {
// Resolve a String with the given index from the DexFile, storing the
// result in the DexCache.
mirror::String* ResolveString(const DexFile& dex_file, uint32_t string_idx,
- SirtRef<mirror::DexCache>& dex_cache)
+ const SirtRef<mirror::DexCache>& dex_cache)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Resolve a Type with the given index from the DexFile, storing the
@@ -150,8 +151,8 @@ class ClassLinker {
// type, since it may be referenced from but not contained within
// the given DexFile.
mirror::Class* ResolveType(const DexFile& dex_file, uint16_t type_idx,
- SirtRef<mirror::DexCache>& dex_cache,
- SirtRef<mirror::ClassLoader>& class_loader)
+ const SirtRef<mirror::DexCache>& dex_cache,
+ const SirtRef<mirror::ClassLoader>& class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Resolve a method with a given ID from the DexFile, storing the
@@ -161,8 +162,8 @@ class ClassLinker {
// virtual method.
mirror::ArtMethod* ResolveMethod(const DexFile& dex_file,
uint32_t method_idx,
- SirtRef<mirror::DexCache>& dex_cache,
- SirtRef<mirror::ClassLoader>& class_loader,
+ const SirtRef<mirror::DexCache>& dex_cache,
+ const SirtRef<mirror::ClassLoader>& class_loader,
const mirror::ArtMethod* referrer,
InvokeType type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -182,8 +183,8 @@ class ClassLinker {
// field.
mirror::ArtField* ResolveField(const DexFile& dex_file,
uint32_t field_idx,
- SirtRef<mirror::DexCache>& dex_cache,
- SirtRef<mirror::ClassLoader>& class_loader,
+ const SirtRef<mirror::DexCache>& dex_cache,
+ const SirtRef<mirror::ClassLoader>& class_loader,
bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -193,8 +194,8 @@ class ClassLinker {
// field resolution semantics are followed.
mirror::ArtField* ResolveFieldJLS(const DexFile& dex_file,
uint32_t field_idx,
- SirtRef<mirror::DexCache>& dex_cache,
- SirtRef<mirror::ClassLoader>& class_loader)
+ const SirtRef<mirror::DexCache>& dex_cache,
+ const SirtRef<mirror::ClassLoader>& class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Get shorty from method index without resolution. Used to do handlerization.
@@ -204,7 +205,8 @@ class ClassLinker {
// Returns true on success, false if there's an exception pending.
// can_run_clinit=false allows the compiler to attempt to init a class,
// given the restriction that no <clinit> execution is possible.
- bool EnsureInitialized(mirror::Class* c, bool can_run_clinit, bool can_init_fields)
+ bool EnsureInitialized(const SirtRef<mirror::Class>& c,
+ bool can_init_fields, bool can_init_parents)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Initializes classes that have instances in the image but that have
@@ -214,7 +216,7 @@ class ClassLinker {
void RegisterDexFile(const DexFile& dex_file)
LOCKS_EXCLUDED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void RegisterDexFile(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache)
+ void RegisterDexFile(const DexFile& dex_file, const SirtRef<mirror::DexCache>& dex_cache)
LOCKS_EXCLUDED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -303,11 +305,12 @@ class ClassLinker {
size_t length)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void VerifyClass(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void VerifyClass(const SirtRef<mirror::Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class* klass,
mirror::Class::Status& oat_file_class_status)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void ResolveClassExceptionHandlerTypes(const DexFile& dex_file, mirror::Class* klass)
+ void ResolveClassExceptionHandlerTypes(const DexFile& dex_file,
+ const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void ResolveMethodExceptionHandlerTypes(const DexFile& dex_file, mirror::ArtMethod* klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -380,7 +383,8 @@ class ClassLinker {
// Alloc* convenience functions to avoid needing to pass in mirror::Class*
// values that are known to the ClassLinker such as
// kObjectArrayClass and kJavaLangString etc.
- mirror::Class* AllocClass(Thread* self, size_t class_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ mirror::Class* AllocClass(Thread* self, size_t class_size)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::DexCache* AllocDexCache(Thread* self, const DexFile& dex_file)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::ArtField* AllocArtField(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -392,12 +396,12 @@ class ClassLinker {
mirror::Class* CreateArrayClass(const char* descriptor,
- SirtRef<mirror::ClassLoader>& class_loader)
+ const SirtRef<mirror::ClassLoader>& class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void AppendToBootClassPath(const DexFile& dex_file)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void AppendToBootClassPath(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache)
+ void AppendToBootClassPath(const DexFile& dex_file, const SirtRef<mirror::DexCache>& dex_cache)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void ConstructFieldMap(const DexFile& dex_file, const DexFile::ClassDef& dex_class_def,
@@ -409,17 +413,17 @@ class ClassLinker {
void LoadClass(const DexFile& dex_file,
const DexFile::ClassDef& dex_class_def,
- SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::Class>& klass,
mirror::ClassLoader* class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it,
- SirtRef<mirror::Class>& klass, SirtRef<mirror::ArtField>& dst)
+ const SirtRef<mirror::Class>& klass, const SirtRef<mirror::ArtField>& dst)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::ArtMethod* LoadMethod(Thread* self, const DexFile& dex_file,
const ClassDataItemIterator& dex_method,
- SirtRef<mirror::Class>& klass)
+ const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void FixupStaticTrampolines(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -428,20 +432,22 @@ class ClassLinker {
const OatFile::OatClass* GetOatClass(const DexFile& dex_file, uint16_t class_def_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void RegisterDexFileLocked(const DexFile& dex_file, SirtRef<mirror::DexCache>& dex_cache)
+ void RegisterDexFileLocked(const DexFile& dex_file, const SirtRef<mirror::DexCache>& dex_cache)
EXCLUSIVE_LOCKS_REQUIRED(dex_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsDexFileRegisteredLocked(const DexFile& dex_file) const SHARED_LOCKS_REQUIRED(dex_lock_);
- bool InitializeClass(mirror::Class* klass, bool can_run_clinit, bool can_init_parents)
+ bool InitializeClass(const SirtRef<mirror::Class>& klass, bool can_run_clinit,
+ bool can_init_parents)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool WaitForInitializeClass(mirror::Class* klass, Thread* self, ObjectLock& lock);
- bool ValidateSuperClassDescriptors(const mirror::Class* klass)
+ bool WaitForInitializeClass(const SirtRef<mirror::Class>& klass, Thread* self,
+ ObjectLock<mirror::Class>& lock);
+ bool ValidateSuperClassDescriptors(const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsSameDescriptorInDifferentClassContexts(const char* descriptor,
- const mirror::Class* klass1,
- const mirror::Class* klass2)
+ SirtRef<mirror::ClassLoader>& class_loader1,
+ SirtRef<mirror::ClassLoader>& class_loader2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsSameMethodSignatureInDifferentClassContexts(const mirror::ArtMethod* method,
@@ -449,40 +455,40 @@ class ClassLinker {
const mirror::Class* klass2)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LinkClass(Thread* self, SirtRef<mirror::Class>& klass,
- SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
+ bool LinkClass(Thread* self, const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LinkSuperClass(SirtRef<mirror::Class>& klass)
+ bool LinkSuperClass(const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LoadSuperAndInterfaces(SirtRef<mirror::Class>& klass, const DexFile& dex_file)
+ bool LoadSuperAndInterfaces(const SirtRef<mirror::Class>& klass, const DexFile& dex_file)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LinkMethods(SirtRef<mirror::Class>& klass,
- SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
+ bool LinkMethods(const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LinkVirtualMethods(SirtRef<mirror::Class>& klass)
+ bool LinkVirtualMethods(const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LinkInterfaceMethods(SirtRef<mirror::Class>& klass,
- SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
+ bool LinkInterfaceMethods(const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ObjectArray<mirror::Class> >& interfaces)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LinkStaticFields(SirtRef<mirror::Class>& klass)
+ bool LinkStaticFields(const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LinkInstanceFields(SirtRef<mirror::Class>& klass)
+ bool LinkInstanceFields(const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool LinkFields(SirtRef<mirror::Class>& klass, bool is_static)
+ bool LinkFields(const SirtRef<mirror::Class>& klass, bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CreateReferenceInstanceOffsets(SirtRef<mirror::Class>& klass)
+ void CreateReferenceInstanceOffsets(const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CreateReferenceStaticOffsets(SirtRef<mirror::Class>& klass)
+ void CreateReferenceStaticOffsets(const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void CreateReferenceOffsets(SirtRef<mirror::Class>& klass, bool is_static,
+ void CreateReferenceOffsets(const SirtRef<mirror::Class>& klass, bool is_static,
uint32_t reference_offsets)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -511,11 +517,11 @@ class ClassLinker {
bool* open_failed)
LOCKS_EXCLUDED(dex_lock_);
- mirror::ArtMethod* CreateProxyConstructor(Thread* self, SirtRef<mirror::Class>& klass,
+ mirror::ArtMethod* CreateProxyConstructor(Thread* self, const SirtRef<mirror::Class>& klass,
mirror::Class* proxy_class)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ArtMethod* CreateProxyMethod(Thread* self, SirtRef<mirror::Class>& klass,
- SirtRef<mirror::ArtMethod>& prototype)
+ mirror::ArtMethod* CreateProxyMethod(Thread* self, const SirtRef<mirror::Class>& klass,
+ const SirtRef<mirror::ArtMethod>& prototype)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::vector<const DexFile*> boot_class_path_;
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index b8bc474..34134fa 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -95,8 +95,10 @@ class ClassLinkerTest : public CommonTest {
const std::string& component_type,
mirror::ClassLoader* class_loader)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- SirtRef<mirror::ClassLoader> loader(Thread::Current(), class_loader);
- mirror::Class* array = class_linker_->FindClass(array_descriptor.c_str(), loader);
+ Thread* self = Thread::Current();
+ SirtRef<mirror::ClassLoader> loader(self, class_loader);
+ SirtRef<mirror::Class> array(self,
+ class_linker_->FindClass(array_descriptor.c_str(), loader));
ClassHelper array_component_ch(array->GetComponentType());
EXPECT_STREQ(component_type.c_str(), array_component_ch.GetDescriptor());
EXPECT_EQ(class_loader, array->GetClassLoader());
@@ -104,10 +106,10 @@ class ClassLinkerTest : public CommonTest {
AssertArrayClass(array_descriptor, array);
}
- void AssertArrayClass(const std::string& array_descriptor, mirror::Class* array)
+ void AssertArrayClass(const std::string& array_descriptor, const SirtRef<mirror::Class>& array)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper kh(array);
- ASSERT_TRUE(array != NULL);
+ ClassHelper kh(array.get());
+ ASSERT_TRUE(array.get() != NULL);
ASSERT_TRUE(array->GetClass() != NULL);
ASSERT_EQ(array->GetClass(), array->GetClass()->GetClass());
EXPECT_TRUE(array->GetClass()->GetSuperClass() != NULL);
@@ -135,15 +137,14 @@ class ClassLinkerTest : public CommonTest {
EXPECT_EQ(0U, array->NumVirtualMethods());
EXPECT_EQ(0U, array->NumInstanceFields());
EXPECT_EQ(0U, array->NumStaticFields());
- kh.ChangeClass(array);
+ kh.ChangeClass(array.get());
EXPECT_EQ(2U, kh.NumDirectInterfaces());
EXPECT_TRUE(array->GetVTable() != NULL);
EXPECT_EQ(2, array->GetIfTableCount());
- mirror::IfTable* iftable = array->GetIfTable();
- ASSERT_TRUE(iftable != NULL);
+ ASSERT_TRUE(array->GetIfTable() != NULL);
kh.ChangeClass(kh.GetDirectInterface(0));
EXPECT_STREQ(kh.GetDescriptor(), "Ljava/lang/Cloneable;");
- kh.ChangeClass(array);
+ kh.ChangeClass(array.get());
kh.ChangeClass(kh.GetDirectInterface(1));
EXPECT_STREQ(kh.GetDescriptor(), "Ljava/io/Serializable;");
}
@@ -179,9 +180,9 @@ class ClassLinkerTest : public CommonTest {
EXPECT_TRUE(fh.GetType() != NULL);
}
- void AssertClass(const std::string& descriptor, mirror::Class* klass)
+ void AssertClass(const std::string& descriptor, const SirtRef<mirror::Class>& klass)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ClassHelper kh(klass);
+ ClassHelper kh(klass.get());
EXPECT_STREQ(descriptor.c_str(), kh.GetDescriptor());
if (descriptor == "Ljava/lang/Object;") {
EXPECT_FALSE(klass->HasSuperClass());
@@ -197,7 +198,7 @@ class ClassLinkerTest : public CommonTest {
EXPECT_FALSE(klass->IsErroneous());
EXPECT_FALSE(klass->IsArrayClass());
EXPECT_TRUE(klass->GetComponentType() == NULL);
- EXPECT_TRUE(klass->IsInSamePackage(klass));
+ EXPECT_TRUE(klass->IsInSamePackage(klass.get()));
EXPECT_TRUE(mirror::Class::IsInSamePackage(kh.GetDescriptor(), kh.GetDescriptor()));
if (klass->IsInterface()) {
EXPECT_TRUE(klass->IsAbstract());
@@ -239,31 +240,31 @@ class ClassLinkerTest : public CommonTest {
}
EXPECT_FALSE(klass->IsPrimitive());
- EXPECT_TRUE(klass->CanAccess(klass));
+ EXPECT_TRUE(klass->CanAccess(klass.get()));
for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
mirror::ArtMethod* method = klass->GetDirectMethod(i);
AssertMethod(method);
EXPECT_TRUE(method->IsDirect());
- EXPECT_EQ(klass, method->GetDeclaringClass());
+ EXPECT_EQ(klass.get(), method->GetDeclaringClass());
}
for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
mirror::ArtMethod* method = klass->GetVirtualMethod(i);
AssertMethod(method);
EXPECT_FALSE(method->IsDirect());
- EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass));
+ EXPECT_TRUE(method->GetDeclaringClass()->IsAssignableFrom(klass.get()));
}
for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
mirror::ArtField* field = klass->GetInstanceField(i);
- AssertField(klass, field);
+ AssertField(klass.get(), field);
EXPECT_FALSE(field->IsStatic());
}
for (size_t i = 0; i < klass->NumStaticFields(); i++) {
mirror::ArtField* field = klass->GetStaticField(i);
- AssertField(klass, field);
+ AssertField(klass.get(), field);
EXPECT_TRUE(field->IsStatic());
}
@@ -291,24 +292,24 @@ class ClassLinkerTest : public CommonTest {
}
size_t total_num_reference_instance_fields = 0;
- mirror::Class* k = klass;
+ mirror::Class* k = klass.get();
while (k != NULL) {
total_num_reference_instance_fields += k->NumReferenceInstanceFields();
k = k->GetSuperClass();
}
- EXPECT_EQ(klass->GetReferenceInstanceOffsets() == 0,
- total_num_reference_instance_fields == 0);
+ EXPECT_EQ(klass->GetReferenceInstanceOffsets() == 0, total_num_reference_instance_fields == 0);
}
void AssertDexFileClass(mirror::ClassLoader* class_loader, const std::string& descriptor)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ASSERT_TRUE(descriptor != NULL);
- mirror::Class* klass = class_linker_->FindSystemClass(descriptor.c_str());
- ASSERT_TRUE(klass != NULL);
- EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass).GetDescriptor());
+ SirtRef<mirror::Class> klass(Thread::Current(),
+ class_linker_->FindSystemClass(descriptor.c_str()));
+ ASSERT_TRUE(klass.get() != nullptr);
+ EXPECT_STREQ(descriptor.c_str(), ClassHelper(klass.get()).GetDescriptor());
EXPECT_EQ(class_loader, klass->GetClassLoader());
if (klass->IsPrimitive()) {
- AssertPrimitiveClass(descriptor, klass);
+ AssertPrimitiveClass(descriptor, klass.get());
} else if (klass->IsArrayClass()) {
AssertArrayClass(descriptor, klass);
} else {
@@ -852,7 +853,7 @@ TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
TEST_F(ClassLinkerTest, StaticFields) {
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Statics")));
- mirror::Class* statics = class_linker_->FindClass("LStatics;", class_loader);
+ SirtRef<mirror::Class> statics(soa.Self(), class_linker_->FindClass("LStatics;", class_loader));
class_linker_->EnsureInitialized(statics, true, true);
// Static final primitives that are initialized by a compile-time constant
@@ -867,68 +868,68 @@ TEST_F(ClassLinkerTest, StaticFields) {
FieldHelper fh(s0);
EXPECT_STREQ(ClassHelper(s0->GetClass()).GetDescriptor(), "Ljava/lang/reflect/ArtField;");
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimBoolean);
- EXPECT_EQ(true, s0->GetBoolean(statics));
- s0->SetBoolean(statics, false);
+ EXPECT_EQ(true, s0->GetBoolean(statics.get()));
+ s0->SetBoolean(statics.get(), false);
mirror::ArtField* s1 = statics->FindStaticField("s1", "B");
fh.ChangeField(s1);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimByte);
- EXPECT_EQ(5, s1->GetByte(statics));
- s1->SetByte(statics, 6);
+ EXPECT_EQ(5, s1->GetByte(statics.get()));
+ s1->SetByte(statics.get(), 6);
mirror::ArtField* s2 = statics->FindStaticField("s2", "C");
fh.ChangeField(s2);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimChar);
- EXPECT_EQ('a', s2->GetChar(statics));
- s2->SetChar(statics, 'b');
+ EXPECT_EQ('a', s2->GetChar(statics.get()));
+ s2->SetChar(statics.get(), 'b');
mirror::ArtField* s3 = statics->FindStaticField("s3", "S");
fh.ChangeField(s3);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimShort);
- EXPECT_EQ(-536, s3->GetShort(statics));
- s3->SetShort(statics, -535);
+ EXPECT_EQ(-536, s3->GetShort(statics.get()));
+ s3->SetShort(statics.get(), -535);
mirror::ArtField* s4 = statics->FindStaticField("s4", "I");
fh.ChangeField(s4);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimInt);
- EXPECT_EQ(2000000000, s4->GetInt(statics));
- s4->SetInt(statics, 2000000001);
+ EXPECT_EQ(2000000000, s4->GetInt(statics.get()));
+ s4->SetInt(statics.get(), 2000000001);
mirror::ArtField* s5 = statics->FindStaticField("s5", "J");
fh.ChangeField(s5);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimLong);
- EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics));
- s5->SetLong(statics, 0x34567890abcdef12LL);
+ EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics.get()));
+ s5->SetLong(statics.get(), 0x34567890abcdef12LL);
mirror::ArtField* s6 = statics->FindStaticField("s6", "F");
fh.ChangeField(s6);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimFloat);
- EXPECT_EQ(0.5, s6->GetFloat(statics));
- s6->SetFloat(statics, 0.75);
+ EXPECT_EQ(0.5, s6->GetFloat(statics.get()));
+ s6->SetFloat(statics.get(), 0.75);
mirror::ArtField* s7 = statics->FindStaticField("s7", "D");
fh.ChangeField(s7);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimDouble);
- EXPECT_EQ(16777217, s7->GetDouble(statics));
- s7->SetDouble(statics, 16777219);
+ EXPECT_EQ(16777217, s7->GetDouble(statics.get()));
+ s7->SetDouble(statics.get(), 16777219);
mirror::ArtField* s8 = statics->FindStaticField("s8", "Ljava/lang/String;");
fh.ChangeField(s8);
EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimNot);
- EXPECT_TRUE(s8->GetObject(statics)->AsString()->Equals("android"));
+ EXPECT_TRUE(s8->GetObject(statics.get())->AsString()->Equals("android"));
s8->SetObject(s8->GetDeclaringClass(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "robot"));
// TODO: Remove EXPECT_FALSE when GCC can handle EXPECT_EQ
// http://code.google.com/p/googletest/issues/detail?id=322
- EXPECT_FALSE(s0->GetBoolean(statics));
- EXPECT_EQ(6, s1->GetByte(statics));
- EXPECT_EQ('b', s2->GetChar(statics));
- EXPECT_EQ(-535, s3->GetShort(statics));
- EXPECT_EQ(2000000001, s4->GetInt(statics));
- EXPECT_EQ(0x34567890abcdef12LL, s5->GetLong(statics));
- EXPECT_EQ(0.75, s6->GetFloat(statics));
- EXPECT_EQ(16777219, s7->GetDouble(statics));
- EXPECT_TRUE(s8->GetObject(statics)->AsString()->Equals("robot"));
+ EXPECT_FALSE(s0->GetBoolean(statics.get()));
+ EXPECT_EQ(6, s1->GetByte(statics.get()));
+ EXPECT_EQ('b', s2->GetChar(statics.get()));
+ EXPECT_EQ(-535, s3->GetShort(statics.get()));
+ EXPECT_EQ(2000000001, s4->GetInt(statics.get()));
+ EXPECT_EQ(0x34567890abcdef12LL, s5->GetLong(statics.get()));
+ EXPECT_EQ(0.75, s6->GetFloat(statics.get()));
+ EXPECT_EQ(16777219, s7->GetDouble(statics.get()));
+ EXPECT_TRUE(s8->GetObject(statics.get())->AsString()->Equals("robot"));
}
TEST_F(ClassLinkerTest, Interfaces) {
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 52a2141..0b572b0 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -2816,30 +2816,30 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) {
}
// Translate the method through the vtable, unless the debugger wants to suppress it.
- mirror::ArtMethod* m = pReq->method;
+ SirtRef<mirror::ArtMethod> m(soa.Self(), pReq->method);
if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver != NULL) {
mirror::ArtMethod* actual_method = pReq->klass->FindVirtualMethodForVirtualOrInterface(pReq->method);
- if (actual_method != m) {
- VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m) << " to " << PrettyMethod(actual_method);
- m = actual_method;
+ if (actual_method != m.get()) {
+ VLOG(jdwp) << "ExecuteMethod translated " << PrettyMethod(m.get()) << " to " << PrettyMethod(actual_method);
+ m.reset(actual_method);
}
}
- VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m)
+ VLOG(jdwp) << "ExecuteMethod " << PrettyMethod(m.get())
<< " receiver=" << pReq->receiver
<< " arg_count=" << pReq->arg_count;
- CHECK(m != NULL);
+ CHECK(m.get() != nullptr);
CHECK_EQ(sizeof(jvalue), sizeof(uint64_t));
- MethodHelper mh(m);
+ MethodHelper mh(m.get());
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, pReq->receiver, reinterpret_cast<jvalue*>(pReq->arg_values));
- InvokeWithArgArray(soa, m, &arg_array, &pReq->result_value, mh.GetShorty()[0]);
+ InvokeWithArgArray(soa, m.get(), &arg_array, &pReq->result_value, mh.GetShorty()[0]);
mirror::Throwable* exception = soa.Self()->GetException(NULL);
soa.Self()->ClearException();
pReq->exception = gRegistry->Add(exception);
- pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m).GetShorty());
+ pReq->result_tag = BasicTagFromDescriptor(MethodHelper(m.get()).GetShorty());
if (pReq->exception != 0) {
VLOG(jdwp) << " JDWP invocation returning with exception=" << exception
<< " " << exception->Dump();
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 747dd56..bfdbd74 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -72,7 +72,7 @@ ALWAYS_INLINE static inline mirror::Class* CheckObjectAlloc(uint32_t type_idx,
if (UNLIKELY(!klass->IsInitialized())) {
SirtRef<mirror::Class> sirt_klass(self, klass);
// The class initializer might cause a GC.
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(klass, true, true)) {
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
DCHECK(self->IsExceptionPending());
return nullptr; // Failure
}
@@ -246,12 +246,15 @@ static inline mirror::ArtField* FindFieldFromCode(uint32_t field_idx, const mirr
// If the class is initialized we're done.
if (LIKELY(fields_class->IsInitialized())) {
return resolved_field;
- } else if (LIKELY(class_linker->EnsureInitialized(fields_class, true, true))) {
- // Otherwise let's ensure the class is initialized before resolving the field.
- return resolved_field;
} else {
- DCHECK(self->IsExceptionPending()); // Throw exception and unwind
- return nullptr; // failure
+ SirtRef<mirror::Class> sirt_class(self, fields_class);
+ if (LIKELY(class_linker->EnsureInitialized(sirt_class, true, true))) {
+ // Otherwise let's ensure the class is initialized before resolving the field.
+ return resolved_field;
+ } else {
+ DCHECK(self->IsExceptionPending()); // Throw exception and unwind
+ return nullptr; // failure
+ }
}
}
}
@@ -535,12 +538,13 @@ static inline mirror::Class* ResolveVerifyAndClinit(uint32_t type_idx,
if (klass == referring_class && referrer->IsConstructor() && referrer->IsStatic()) {
return klass;
}
- if (!class_linker->EnsureInitialized(klass, true, true)) {
+ SirtRef<mirror::Class> sirt_class(self, klass);
+ if (!class_linker->EnsureInitialized(sirt_class, true, true)) {
CHECK(self->IsExceptionPending());
return NULL; // Failure - Indicate to caller to deliver exception
}
- referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
- return klass;
+ referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, sirt_class.get());
+ return sirt_class.get();
}
extern void ThrowStackOverflowError(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index df4ec3a..0df00c2 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -34,14 +34,14 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& m
mirror::Class* declaringClass = method->GetDeclaringClass();
if (UNLIKELY(!declaringClass->IsInitializing())) {
self->PushShadowFrame(shadow_frame);
- if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass,
- true, true))) {
+ SirtRef<mirror::Class> sirt_c(self, declaringClass);
+ if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true))) {
self->PopShadowFrame();
DCHECK(self->IsExceptionPending());
return;
}
self->PopShadowFrame();
- CHECK(declaringClass->IsInitializing());
+ CHECK(sirt_c->IsInitializing());
}
}
uint16_t arg_offset = (code_item == NULL) ? 0 : code_item->registers_size_ - code_item->ins_size_;
diff --git a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
index 61f7440..2162dcc 100644
--- a/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/portable/portable_trampoline_entrypoints.cc
@@ -208,8 +208,8 @@ extern "C" uint64_t artPortableToInterpreterBridge(mirror::ArtMethod* method, Th
if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
// Ensure static method's class is initialized.
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
- true, true)) {
+ SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true)) {
DCHECK(Thread::Current()->IsExceptionPending());
self->PopManagedStackFragment(fragment);
return 0;
@@ -390,7 +390,7 @@ extern "C" const void* artPortableResolutionTrampoline(mirror::ArtMethod* called
const void* code = NULL;
if (LIKELY(!thread->IsExceptionPending())) {
// Ensure that the called method's class is initialized.
- mirror::Class* called_class = called->GetDeclaringClass();
+ SirtRef<mirror::Class> called_class(thread, called->GetDeclaringClass());
linker->EnsureInitialized(called_class, true, true);
if (LIKELY(called_class->IsInitialized())) {
code = called->GetEntryPointFromCompiledCode();
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 8ba08ee..b589384 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -298,8 +298,8 @@ extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Threa
if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
// Ensure static method's class is initialized.
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
- true, true)) {
+ SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true)) {
DCHECK(Thread::Current()->IsExceptionPending());
self->PopManagedStackFragment(fragment);
return 0;
@@ -564,7 +564,7 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called,
}
}
// Ensure that the called method's class is initialized.
- mirror::Class* called_class = called->GetDeclaringClass();
+ SirtRef<mirror::Class> called_class(soa.Self(), called->GetDeclaringClass());
linker->EnsureInitialized(called_class, true, true);
if (LIKELY(called_class->IsInitialized())) {
code = called->GetEntryPointFromCompiledCode();
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index 8f542d8..978faeb 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -37,11 +37,13 @@ class ExceptionTest : public CommonTest {
CommonTest::SetUp();
ScopedObjectAccess soa(Thread::Current());
- SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
- soa.Decode<mirror::ClassLoader*>(LoadDex("ExceptionHandle")));
+ SirtRef<mirror::ClassLoader> class_loader(
+ soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("ExceptionHandle")));
my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader);
ASSERT_TRUE(my_klass_ != NULL);
- class_linker_->EnsureInitialized(my_klass_, true, true);
+ SirtRef<mirror::Class> sirt_klass(soa.Self(), my_klass_);
+ class_linker_->EnsureInitialized(sirt_klass, true, true);
+ my_klass_ = sirt_klass.get();
dex_ = my_klass_->GetDexCache()->GetDexFile();
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index 7818bc8..e099137 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -95,8 +95,8 @@ void CardTable::ClearSpaceCards(space::ContinuousSpace* space) {
}
void CardTable::ClearCardTable() {
- // TODO: clear just the range of the table that has been modified
- memset(mem_map_->Begin(), kCardClean, mem_map_->Size());
+ COMPILE_ASSERT(kCardClean == 0, clean_card_must_be_0);
+ madvise(mem_map_->Begin(), mem_map_->Size(), MADV_DONTNEED);
}
bool CardTable::AddrIsInCardTable(const void* addr) const {
diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc
index faa198a..b428e74 100644
--- a/runtime/gc/accounting/mod_union_table.cc
+++ b/runtime/gc/accounting/mod_union_table.cc
@@ -82,7 +82,7 @@ class ModUnionUpdateObjectReferencesVisitor {
if (ref != nullptr) {
Object* new_ref = visitor_(ref, arg_);
if (new_ref != ref) {
- obj->SetFieldObject(offset, new_ref, true);
+ obj->SetFieldPtr(offset, new_ref, true);
}
}
}
diff --git a/runtime/gc/collector/mark_sweep-inl.h b/runtime/gc/collector/mark_sweep-inl.h
index 7a51553..9c1c5dc 100644
--- a/runtime/gc/collector/mark_sweep-inl.h
+++ b/runtime/gc/collector/mark_sweep-inl.h
@@ -69,15 +69,14 @@ inline void MarkSweep::VisitObjectReferences(mirror::Object* obj, const Visitor&
DCHECK(obj->GetClass() != NULL);
mirror::Class* klass = obj->GetClass();
DCHECK(klass != NULL);
- if (visit_class) {
- visitor(obj, klass, mirror::Object::ClassOffset(), false);
- }
if (klass == mirror::Class::GetJavaLangClass()) {
DCHECK_EQ(klass->GetClass(), mirror::Class::GetJavaLangClass());
VisitClassReferences(klass, obj, visitor);
} else {
if (klass->IsArrayClass()) {
- visitor(obj, klass, mirror::Object::ClassOffset(), false);
+ if (visit_class) {
+ visitor(obj, klass, mirror::Object::ClassOffset(), false);
+ }
if (klass->IsObjectArrayClass()) {
VisitObjectArrayReferences(obj->AsObjectArray<mirror::Object>(), visitor);
}
diff --git a/runtime/gc/collector/mark_sweep.h b/runtime/gc/collector/mark_sweep.h
index 53d85b0..62991bb 100644
--- a/runtime/gc/collector/mark_sweep.h
+++ b/runtime/gc/collector/mark_sweep.h
@@ -89,10 +89,12 @@ class MarkSweep : public GarbageCollector {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void MarkNonThreadRoots()
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void MarkConcurrentRoots();
- EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_);
+ void MarkConcurrentRoots()
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void MarkRootsCheckpoint(Thread* self)
EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
diff --git a/runtime/gc/collector/semi_space.cc b/runtime/gc/collector/semi_space.cc
index 3939354..63e0cfa 100644
--- a/runtime/gc/collector/semi_space.cc
+++ b/runtime/gc/collector/semi_space.cc
@@ -173,6 +173,10 @@ void SemiSpace::MarkingPhase() {
BindBitmaps();
// Process dirty cards and add dirty cards to mod-union tables.
heap_->ProcessCards(timings_);
+ // Clear the whole card table since we can not get any additional dirty cards during the
+ // paused GC. This saves memory but only works for pause the world collectors.
+ timings_.NewSplit("ClearCardTable");
+ heap_->GetCardTable()->ClearCardTable();
// Need to do this before the checkpoint since we don't want any threads to add references to
// the live stack during the recursive mark.
timings_.NewSplit("SwapStacks");
@@ -318,8 +322,6 @@ Object* SemiSpace::MarkObject(Object* obj) {
memcpy(reinterpret_cast<void*>(forward_address), obj, object_size);
// Make sure to only update the forwarding address AFTER you copy the object so that the
// monitor word doesn't get stomped over.
- COMPILE_ASSERT(sizeof(uint32_t) == sizeof(mirror::Object*),
- monitor_size_must_be_same_as_object);
obj->SetLockWord(LockWord::FromForwardingAddress(reinterpret_cast<size_t>(forward_address)));
MarkStackPush(forward_address);
}
@@ -508,7 +510,10 @@ void SemiSpace::ScanObject(Object* obj) {
mirror::Object* new_address = MarkObject(ref);
if (new_address != ref) {
DCHECK(new_address != nullptr);
- obj->SetFieldObject(offset, new_address, false);
+ // Don't need to mark the card since we updating the object address and not changing the
+ // actual objects its pointing to. Using SetFieldPtr is better in this case since it does not
+ // dirty cards and use additional memory.
+ obj->SetFieldPtr(offset, new_address, false);
}
}, kMovingClasses);
mirror::Class* klass = obj->GetClass();
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 08ab6b8..99f084a 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -41,24 +41,20 @@ inline mirror::Object* Heap::AllocObjectWithAllocator(Thread* self, mirror::Clas
// done in the runnable state where suspension is expected.
DCHECK_EQ(self->GetState(), kRunnable);
self->AssertThreadSuspensionIsAllowable();
+ // Need to check that we arent the large object allocator since the large object allocation code
+ // path this function. If we didn't check we would have an infinite loop.
+ if (allocator != kAllocatorTypeLOS && UNLIKELY(ShouldAllocLargeObject(klass, byte_count))) {
+ return AllocLargeObject<kInstrumented, PreFenceVisitor>(self, klass, byte_count,
+ pre_fence_visitor);
+ }
mirror::Object* obj;
size_t bytes_allocated;
AllocationTimer alloc_timer(this, &obj);
- if (UNLIKELY(ShouldAllocLargeObject(klass, byte_count))) {
- obj = TryToAllocate<kInstrumented>(self, kAllocatorTypeLOS, byte_count, false,
- &bytes_allocated);
- allocator = kAllocatorTypeLOS;
- } else {
- obj = TryToAllocate<kInstrumented>(self, allocator, byte_count, false, &bytes_allocated);
- }
-
+ obj = TryToAllocate<kInstrumented, false>(self, allocator, byte_count, &bytes_allocated);
if (UNLIKELY(obj == nullptr)) {
- SirtRef<mirror::Class> sirt_c(self, klass);
- obj = AllocateInternalWithGc(self, allocator, byte_count, &bytes_allocated);
+ obj = AllocateInternalWithGc(self, allocator, byte_count, &bytes_allocated, &klass);
if (obj == nullptr) {
return nullptr;
- } else {
- klass = sirt_c.get();
}
}
obj->SetClass(klass);
@@ -105,11 +101,19 @@ inline mirror::Object* Heap::AllocObjectWithAllocator(Thread* self, mirror::Clas
return obj;
}
-template <const bool kInstrumented>
+template <bool kInstrumented, typename PreFenceVisitor>
+inline mirror::Object* Heap::AllocLargeObject(Thread* self, mirror::Class* klass,
+ size_t byte_count,
+ const PreFenceVisitor& pre_fence_visitor) {
+ return AllocObjectWithAllocator<kInstrumented, PreFenceVisitor>(self, klass, byte_count,
+ kAllocatorTypeLOS,
+ pre_fence_visitor);
+}
+
+template <const bool kInstrumented, const bool kGrow>
inline mirror::Object* Heap::TryToAllocate(Thread* self, AllocatorType allocator_type,
- size_t alloc_size, bool grow,
- size_t* bytes_allocated) {
- if (UNLIKELY(IsOutOfMemoryOnAllocation(alloc_size, grow))) {
+ size_t alloc_size, size_t* bytes_allocated) {
+ if (UNLIKELY(IsOutOfMemoryOnAllocation<kGrow>(alloc_size))) {
return nullptr;
}
if (kInstrumented) {
@@ -190,14 +194,15 @@ inline bool Heap::ShouldAllocLargeObject(mirror::Class* c, size_t byte_count) co
return byte_count >= kLargeObjectThreshold && have_zygote_space_ && c->IsPrimitiveArray();
}
-inline bool Heap::IsOutOfMemoryOnAllocation(size_t alloc_size, bool grow) {
+template <const bool kGrow>
+inline bool Heap::IsOutOfMemoryOnAllocation(size_t alloc_size) {
size_t new_footprint = num_bytes_allocated_ + alloc_size;
if (UNLIKELY(new_footprint > max_allowed_footprint_)) {
if (UNLIKELY(new_footprint > growth_limit_)) {
return true;
}
if (!concurrent_gc_) {
- if (!grow) {
+ if (!kGrow) {
return true;
}
// TODO: Grow for allocation is racy, fix it.
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index f92a821..11acd33 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -881,14 +881,17 @@ void Heap::RecordFree(size_t freed_objects, size_t freed_bytes) {
}
mirror::Object* Heap::AllocateInternalWithGc(Thread* self, AllocatorType allocator,
- size_t alloc_size, size_t* bytes_allocated) {
+ size_t alloc_size, size_t* bytes_allocated,
+ mirror::Class** klass) {
mirror::Object* ptr = nullptr;
+ DCHECK(klass != nullptr);
+ SirtRef<mirror::Class> sirt_klass(self, *klass);
// The allocation failed. If the GC is running, block until it completes, and then retry the
// allocation.
collector::GcType last_gc = WaitForGcToComplete(self);
if (last_gc != collector::kGcTypeNone) {
// A GC was in progress and we blocked, retry allocation now that memory has been freed.
- ptr = TryToAllocate<true>(self, allocator, alloc_size, false, bytes_allocated);
+ ptr = TryToAllocate<true, false>(self, allocator, alloc_size, bytes_allocated);
}
// Loop through our different Gc types and try to Gc until we get enough free memory.
@@ -899,13 +902,13 @@ mirror::Object* Heap::AllocateInternalWithGc(Thread* self, AllocatorType allocat
// Attempt to run the collector, if we succeed, re-try the allocation.
if (CollectGarbageInternal(gc_type, kGcCauseForAlloc, false) != collector::kGcTypeNone) {
// Did we free sufficient memory for the allocation to succeed?
- ptr = TryToAllocate<true>(self, allocator, alloc_size, false, bytes_allocated);
+ ptr = TryToAllocate<true, false>(self, allocator, alloc_size, bytes_allocated);
}
}
// Allocations have failed after GCs; this is an exceptional state.
if (ptr == nullptr) {
// Try harder, growing the heap if necessary.
- ptr = TryToAllocate<true>(self, allocator, alloc_size, true, bytes_allocated);
+ ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated);
}
if (ptr == nullptr) {
// Most allocations should have succeeded by now, so the heap is really full, really fragmented,
@@ -918,11 +921,12 @@ mirror::Object* Heap::AllocateInternalWithGc(Thread* self, AllocatorType allocat
// We don't need a WaitForGcToComplete here either.
DCHECK(!gc_plan_.empty());
CollectGarbageInternal(gc_plan_.back(), kGcCauseForAlloc, true);
- ptr = TryToAllocate<true>(self, allocator, alloc_size, true, bytes_allocated);
+ ptr = TryToAllocate<true, true>(self, allocator, alloc_size, bytes_allocated);
if (ptr == nullptr) {
ThrowOutOfMemoryError(self, alloc_size, false);
}
}
+ *klass = sirt_klass.get();
return ptr;
}
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 3bff3f9..9788064 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -126,11 +126,6 @@ enum ProcessState {
kProcessStateJankImperceptible = 1,
};
-// If true, measure the total allocation time.
-static constexpr bool kMeasureAllocationTime = false;
-// Primitive arrays larger than this size are put in the large object space.
-static constexpr size_t kLargeObjectThreshold = 3 * kPageSize;
-
class Heap {
public:
// If true, measure the total allocation time.
@@ -522,10 +517,16 @@ class Heap {
ALWAYS_INLINE void CheckConcurrentGC(Thread* self, size_t new_num_bytes_allocated,
mirror::Object* obj);
+ // We don't force this to be inline since it is a slow path.
+ template <bool kInstrumented, typename PreFenceVisitor>
+ mirror::Object* AllocLargeObject(Thread* self, mirror::Class* klass, size_t byte_count,
+ const PreFenceVisitor& pre_fence_visitor)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Handles Allocate()'s slow allocation path with GC involved after
// an initial allocation attempt failed.
mirror::Object* AllocateInternalWithGc(Thread* self, AllocatorType allocator, size_t num_bytes,
- size_t* bytes_allocated)
+ size_t* bytes_allocated, mirror::Class** klass)
LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -536,15 +537,15 @@ class Heap {
// Try to allocate a number of bytes, this function never does any GCs. Needs to be inlined so
// that the switch statement is constant optimized in the entrypoints.
- template <const bool kInstrumented>
+ template <const bool kInstrumented, const bool kGrow>
ALWAYS_INLINE mirror::Object* TryToAllocate(Thread* self, AllocatorType allocator_type,
- size_t alloc_size, bool grow,
- size_t* bytes_allocated)
+ size_t alloc_size, size_t* bytes_allocated)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void ThrowOutOfMemoryError(Thread* self, size_t byte_count, bool large_object_allocation)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsOutOfMemoryOnAllocation(size_t alloc_size, bool grow);
+ template <const bool kGrow>
+ bool IsOutOfMemoryOnAllocation(size_t alloc_size);
// Pushes a list of cleared references out to the managed heap.
void SetReferenceReferent(mirror::Object* reference, mirror::Object* referent)
diff --git a/runtime/globals.h b/runtime/globals.h
index c2fe67e..a0d7e48 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -82,7 +82,7 @@ static constexpr bool kUsePortableCompiler = false;
// Garbage collector constants.
static constexpr bool kMovingCollector = true && !kUsePortableCompiler;
// True if we allow moving classes.
-static constexpr bool kMovingClasses = false;
+static constexpr bool kMovingClasses = true;
// True if we allow moving fields.
static constexpr bool kMovingFields = false;
// True if we allow moving methods.
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 9938478..02c9012 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -343,12 +343,13 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive
++cur_reg;
} else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (UNLIKELY(!class_linker->EnsureInitialized(method->GetDeclaringClass(), true, true))) {
+ SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
+ if (UNLIKELY(!class_linker->EnsureInitialized(sirt_c, true, true))) {
CHECK(self->IsExceptionPending());
self->PopShadowFrame();
return;
}
- CHECK(method->GetDeclaringClass()->IsInitializing());
+ CHECK(sirt_c->IsInitializing());
}
const char* shorty = mh.GetShorty();
for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
@@ -428,7 +429,7 @@ extern "C" void artInterpreterToInterpreterBridge(Thread* self, MethodHelper& mh
ArtMethod* method = shadow_frame->GetMethod();
// Ensure static methods are initialized.
if (method->IsStatic()) {
- Class* declaringClass = method->GetDeclaringClass();
+ SirtRef<Class> declaringClass(self, method->GetDeclaringClass());
if (UNLIKELY(!declaringClass->IsInitializing())) {
if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass, true,
true))) {
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 0bc834c..3b8d50b 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -334,13 +334,14 @@ static inline bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instructio
// java.lang.String class is initialized.
static inline String* ResolveString(Thread* self, MethodHelper& mh, uint32_t string_idx)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ CHECK(!kMovingMethods);
Class* java_lang_string_class = String::GetJavaLangString();
if (UNLIKELY(!java_lang_string_class->IsInitialized())) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- if (UNLIKELY(!class_linker->EnsureInitialized(java_lang_string_class,
- true, true))) {
+ SirtRef<mirror::Class> sirt_class(self, java_lang_string_class);
+ if (UNLIKELY(!class_linker->EnsureInitialized(sirt_class, true, true))) {
DCHECK(self->IsExceptionPending());
- return NULL;
+ return nullptr;
}
}
return mh.ResolveString(string_idx);
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 466edeb..3300279 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -225,13 +225,24 @@ static void ThrowNoSuchMethodError(ScopedObjectAccess& soa, Class* c,
kind, ClassHelper(c).GetDescriptor(), name, sig);
}
+static mirror::Class* EnsureInitialized(Thread* self, mirror::Class* klass)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (LIKELY(klass->IsInitialized())) {
+ return klass;
+ }
+ SirtRef<mirror::Class> sirt_klass(self, klass);
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
+ return nullptr;
+ }
+ return sirt_klass.get();
+}
+
static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class,
const char* name, const char* sig, bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Class* c = soa.Decode<Class*>(jni_class);
- DCHECK(c != nullptr);
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
- return NULL;
+ Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(jni_class));
+ if (c == nullptr) {
+ return nullptr;
}
ArtMethod* method = NULL;
@@ -284,9 +295,9 @@ static ClassLoader* GetClassLoader(const ScopedObjectAccess& soa)
static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, const char* name,
const char* sig, bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Class* c = soa.Decode<Class*>(jni_class);
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
- return NULL;
+ Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(jni_class));
+ if (c == nullptr) {
+ return nullptr;
}
ArtField* field = NULL;
@@ -910,9 +921,9 @@ class JNI {
static jobject AllocObject(JNIEnv* env, jclass java_class) {
CHECK_NON_NULL_ARGUMENT(AllocObject, java_class);
ScopedObjectAccess soa(env);
- Class* c = soa.Decode<Class*>(java_class);
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
- return NULL;
+ Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(java_class));
+ if (c == nullptr) {
+ return nullptr;
}
return soa.AddLocalReference<jobject>(c->AllocObject(soa.Self()));
}
@@ -931,20 +942,20 @@ class JNI {
CHECK_NON_NULL_ARGUMENT(NewObjectV, java_class);
CHECK_NON_NULL_ARGUMENT(NewObjectV, mid);
ScopedObjectAccess soa(env);
- Class* c = soa.Decode<Class*>(java_class);
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
- return NULL;
+ Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(java_class));
+ if (c == nullptr) {
+ return nullptr;
}
Object* result = c->AllocObject(soa.Self());
- if (result == NULL) {
- return NULL;
+ if (result == nullptr) {
+ return nullptr;
}
jobject local_result = soa.AddLocalReference<jobject>(result);
CallNonvirtualVoidMethodV(env, local_result, java_class, mid, args);
if (!soa.Self()->IsExceptionPending()) {
return local_result;
} else {
- return NULL;
+ return nullptr;
}
}
@@ -952,9 +963,9 @@ class JNI {
CHECK_NON_NULL_ARGUMENT(NewObjectA, java_class);
CHECK_NON_NULL_ARGUMENT(NewObjectA, mid);
ScopedObjectAccess soa(env);
- Class* c = soa.Decode<Class*>(java_class);
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
- return NULL;
+ Class* c = EnsureInitialized(soa.Self(), soa.Decode<Class*>(java_class));
+ if (c == nullptr) {
+ return nullptr;
}
Object* result = c->AllocObject(soa.Self());
if (result == NULL) {
@@ -3303,8 +3314,9 @@ void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m) {
// If this is a static method, it could be called before the class
// has been initialized.
if (m->IsStatic()) {
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
- return NULL;
+ c = EnsureInitialized(Thread::Current(), c);
+ if (c == nullptr) {
+ return nullptr;
}
} else {
CHECK(c->IsInitializing()) << c->GetStatus() << " " << PrettyMethod(m);
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index a754b69..cf4b48c 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -108,6 +108,13 @@ inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_c
Runtime::Current()->GetHeap()->GetCurrentAllocator());
}
+template<class T>
+inline void PrimitiveArray<T>::VisitRoots(RootVisitor* visitor, void* arg) {
+ if (array_class_ != nullptr) {
+ array_class_ = down_cast<Class*>(visitor(array_class_, arg));
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index a332f97..5265946 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -149,6 +149,9 @@ class MANAGED PrimitiveArray : public Array {
array_class_ = NULL;
}
+ static void VisitRoots(RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
static Class* array_class_;
diff --git a/runtime/mirror/art_field.cc b/runtime/mirror/art_field.cc
index a8bbe4b..c3a4efb 100644
--- a/runtime/mirror/art_field.cc
+++ b/runtime/mirror/art_field.cc
@@ -52,5 +52,12 @@ void ArtField::SetOffset(MemberOffset num_bytes) {
SetField32(OFFSET_OF_OBJECT_MEMBER(ArtField, offset_), num_bytes.Uint32Value(), false);
}
+void ArtField::VisitRoots(RootVisitor* visitor, void* arg) {
+ if (java_lang_reflect_ArtField_ != nullptr) {
+ java_lang_reflect_ArtField_ = down_cast<mirror::Class*>(
+ visitor(java_lang_reflect_ArtField_, arg));
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/art_field.h b/runtime/mirror/art_field.h
index ae34cb1..62bcf06 100644
--- a/runtime/mirror/art_field.h
+++ b/runtime/mirror/art_field.h
@@ -130,6 +130,8 @@ class MANAGED ArtField : public Object {
static void SetClass(Class* java_lang_reflect_ArtField);
static void ResetClass();
+ static void VisitRoots(RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsVolatile() const {
return (GetAccessFlags() & kAccVolatile) != 0;
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index f5c0e9f..a4f6b3b 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -40,6 +40,13 @@ extern "C" void art_quick_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*,
// TODO: get global references for these
Class* ArtMethod::java_lang_reflect_ArtMethod_ = NULL;
+void ArtMethod::VisitRoots(RootVisitor* visitor, void* arg) {
+ if (java_lang_reflect_ArtMethod_ != nullptr) {
+ java_lang_reflect_ArtMethod_ = down_cast<mirror::Class*>(
+ visitor(java_lang_reflect_ArtMethod_, arg));
+ }
+}
+
InvokeType ArtMethod::GetInvokeType() const {
// TODO: kSuper?
if (GetDeclaringClass()->IsInterface()) {
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index f396fbe..d5524ec 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -23,6 +23,7 @@
#include "locks.h"
#include "modifiers.h"
#include "object.h"
+#include "root_visitor.h"
namespace art {
@@ -381,6 +382,9 @@ class MANAGED ArtMethod : public Object {
static void ResetClass();
+ static void VisitRoots(RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
protected:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// The class we are a part of
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index cdc5ab2..2746e1e 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -50,6 +50,12 @@ void Class::ResetClass() {
java_lang_Class_ = NULL;
}
+void Class::VisitRoots(RootVisitor* visitor, void* arg) {
+ if (java_lang_Class_ != nullptr) {
+ java_lang_Class_ = down_cast<Class*>(visitor(java_lang_Class_, arg));
+ }
+}
+
void Class::SetStatus(Status new_status, Thread* self) {
Status old_status = GetStatus();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 5f64bb4..50ede66 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -787,6 +787,8 @@ class MANAGED Class : public StaticStorageBase {
// Can't call this SetClass or else gets called instead of Object::SetClass in places.
static void SetClassClass(Class* java_lang_Class);
static void ResetClass();
+ static void VisitRoots(RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// When class is verified, set the kAccPreverified flag on each method.
void SetPreverifiedFlagOnAllMethods() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index 0fb2039..fe89b7e 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -225,6 +225,11 @@ class MANAGED Object {
void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile);
+ template<typename T>
+ void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) {
+ SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
+ }
+
protected:
// Accessors for non-Java type fields
template<class T>
@@ -232,11 +237,6 @@ class MANAGED Object {
return reinterpret_cast<T>(GetField32(field_offset, is_volatile));
}
- template<typename T>
- void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) {
- SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
- }
-
private:
static void VerifyObject(const Object* obj) ALWAYS_INLINE;
// Verify the type correctness of stores to fields.
diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc
index 32a50fe..a7ebe07 100644
--- a/runtime/mirror/stack_trace_element.cc
+++ b/runtime/mirror/stack_trace_element.cc
@@ -58,5 +58,12 @@ StackTraceElement* StackTraceElement::Alloc(Thread* self,
return trace;
}
+void StackTraceElement::VisitRoots(RootVisitor* visitor, void* arg) {
+ if (java_lang_StackTraceElement_ != nullptr) {
+ java_lang_StackTraceElement_ = down_cast<Class*>(visitor(java_lang_StackTraceElement_, arg));
+ }
+}
+
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index 2af5128..d1be4dc 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -57,8 +57,9 @@ class MANAGED StackTraceElement : public Object {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void SetClass(Class* java_lang_StackTraceElement);
-
static void ResetClass();
+ static void VisitRoots(RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index b372fe7..d6e509d 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -122,7 +122,7 @@ String* String::AllocFromUtf16(Thread* self,
const uint16_t* utf16_data_in,
int32_t hash_code) {
CHECK(utf16_data_in != NULL || utf16_length == 0);
- String* string = Alloc(self, GetJavaLangString(), utf16_length);
+ String* string = Alloc(self, utf16_length);
if (UNLIKELY(string == nullptr)) {
return nullptr;
}
@@ -152,7 +152,7 @@ String* String::AllocFromModifiedUtf8(Thread* self, const char* utf) {
String* String::AllocFromModifiedUtf8(Thread* self, int32_t utf16_length,
const char* utf8_data_in) {
- String* string = Alloc(self, GetJavaLangString(), utf16_length);
+ String* string = Alloc(self, utf16_length);
if (UNLIKELY(string == nullptr)) {
return nullptr;
}
@@ -163,21 +163,20 @@ String* String::AllocFromModifiedUtf8(Thread* self, int32_t utf16_length,
return string;
}
-String* String::Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length) {
- CharArray* array = CharArray::Alloc(self, utf16_length);
- if (UNLIKELY(array == nullptr)) {
+String* String::Alloc(Thread* self, int32_t utf16_length) {
+ SirtRef<CharArray> array(self, CharArray::Alloc(self, utf16_length));
+ if (UNLIKELY(array.get() == nullptr)) {
return nullptr;
}
- return Alloc(self, java_lang_String, array);
+ return Alloc(self, array);
}
-String* String::Alloc(Thread* self, Class* java_lang_String, CharArray* array) {
+String* String::Alloc(Thread* self, const SirtRef<CharArray>& array) {
// Hold reference in case AllocObject causes GC.
- SirtRef<CharArray> array_ref(self, array);
- String* string = down_cast<String*>(java_lang_String->AllocObject(self));
+ String* string = down_cast<String*>(GetJavaLangString()->AllocObject(self));
if (LIKELY(string != nullptr)) {
- string->SetArray(array_ref.get());
- string->SetCount(array_ref->GetLength());
+ string->SetArray(array.get());
+ string->SetCount(array->GetLength());
}
return string;
}
@@ -287,5 +286,11 @@ int32_t String::CompareTo(String* rhs) const {
return countDiff;
}
+void String::VisitRoots(RootVisitor* visitor, void* arg) {
+ if (java_lang_String_ != nullptr) {
+ java_lang_String_ = down_cast<Class*>(visitor(java_lang_String_, arg));
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 7520c4d..4bbcb9c 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -19,6 +19,7 @@
#include "class.h"
#include "gtest/gtest.h"
+#include "root_visitor.h"
namespace art {
@@ -77,12 +78,6 @@ class MANAGED String : public Object {
const char* utf8_data_in)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static String* Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static String* Alloc(Thread* self, Class* java_lang_String, CharArray* array)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
bool Equals(const char* modified_utf8) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -114,6 +109,8 @@ class MANAGED String : public Object {
static void SetClass(Class* java_lang_String);
static void ResetClass();
+ static void VisitRoots(RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
void SetHashCode(int32_t new_hash_code) {
@@ -132,6 +129,12 @@ class MANAGED String : public Object {
SetField32(OFFSET_OF_OBJECT_MEMBER(String, offset_), new_offset, false);
}
+ static String* Alloc(Thread* self, int32_t utf16_length)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static String* Alloc(Thread* self, const SirtRef<CharArray>& array)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
void SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
diff --git a/runtime/mirror/throwable.cc b/runtime/mirror/throwable.cc
index 961f6de..b55db72 100644
--- a/runtime/mirror/throwable.cc
+++ b/runtime/mirror/throwable.cc
@@ -93,5 +93,11 @@ void Throwable::ResetClass() {
java_lang_Throwable_ = NULL;
}
+void Throwable::VisitRoots(RootVisitor* visitor, void* arg) {
+ if (java_lang_Throwable_ != nullptr) {
+ java_lang_Throwable_ = down_cast<Class*>(visitor(java_lang_Throwable_, arg));
+ }
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/throwable.h b/runtime/mirror/throwable.h
index 27f6e12..5a90599 100644
--- a/runtime/mirror/throwable.h
+++ b/runtime/mirror/throwable.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_MIRROR_THROWABLE_H_
#include "object.h"
+#include "root_visitor.h"
#include "string.h"
namespace art {
@@ -50,6 +51,8 @@ class MANAGED Throwable : public Object {
static void SetClass(Class* java_lang_Throwable);
static void ResetClass();
+ static void VisitRoots(RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
private:
Object* GetStackState() const {
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 3389107..3e3f608 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -46,8 +46,8 @@ static mirror::Class* DecodeClass(const ScopedFastNativeObjectAccess& soa, jobje
static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize, jobject javaLoader) {
ScopedObjectAccess soa(env);
ScopedUtfChars name(env, javaName);
- if (name.c_str() == NULL) {
- return NULL;
+ if (name.c_str() == nullptr) {
+ return nullptr;
}
// We need to validate and convert the name (from x.y.z to x/y/z). This
@@ -57,27 +57,27 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ClassNotFoundException;",
"Invalid name: %s", name.c_str());
- return NULL;
+ return nullptr;
}
std::string descriptor(DotToDescriptor(name.c_str()));
SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
soa.Decode<mirror::ClassLoader*>(javaLoader));
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* c = class_linker->FindClass(descriptor.c_str(), class_loader);
- if (c == NULL) {
+ SirtRef<mirror::Class> c(soa.Self(), class_linker->FindClass(descriptor.c_str(), class_loader));
+ if (c.get() == nullptr) {
ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
env->ExceptionClear();
jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
WellKnownClasses::java_lang_ClassNotFoundException_init,
javaName, cause.get()));
env->Throw(cnfe);
- return NULL;
+ return nullptr;
}
if (initialize) {
class_linker->EnsureInitialized(c, true, true);
}
- return soa.AddLocalReference<jclass>(c);
+ return soa.AddLocalReference<jclass>(c.get());
}
static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 04dfcb5..5811992 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -41,24 +41,24 @@ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectA
javaMethod, WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
mirror::ArtMethod* m = soa.Decode<mirror::Object*>(art_method)->AsArtMethod();
- mirror::Class* c = m->GetDeclaringClass();
+ SirtRef<mirror::Class> c(soa.Self(), m->GetDeclaringClass());
if (UNLIKELY(c->IsAbstract())) {
ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/InstantiationException;",
"Can't instantiate %s %s",
c->IsInterface() ? "interface" : "abstract class",
- PrettyDescriptor(c).c_str());
- return NULL;
+ PrettyDescriptor(c.get()).c_str());
+ return nullptr;
}
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) {
DCHECK(soa.Self()->IsExceptionPending());
- return NULL;
+ return nullptr;
}
mirror::Object* receiver = c->AllocNonMovableObject(soa.Self());
- if (receiver == NULL) {
- return NULL;
+ if (receiver == nullptr) {
+ return nullptr;
}
jobject javaReceiver = soa.AddLocalReference<jobject>(receiver);
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 4d69a68..553aeb8 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -31,10 +31,13 @@ static bool GetFieldValue(const ScopedFastNativeObjectAccess& soa, mirror::Objec
mirror::ArtField* f, JValue& value, bool allow_references)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_EQ(value.GetJ(), 0LL);
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(),
- true, true)) {
+ CHECK(!kMovingFields);
+ SirtRef<mirror::Object> sirt_obj(soa.Self(), o);
+ SirtRef<mirror::Class> sirt_klass(soa.Self(), f->GetDeclaringClass());
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
return false;
}
+ o = sirt_obj.get();
switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
case Primitive::kPrimBoolean:
value.SetZ(f->GetBoolean(o));
@@ -168,13 +171,16 @@ static jshort Field_getShort(JNIEnv* env, jobject javaField, jobject javaObj) {
return GetPrimitiveField(env, javaField, javaObj, 'S').GetS();
}
-static void SetFieldValue(mirror::Object* o, mirror::ArtField* f, const JValue& new_value,
- bool allow_references)
+static void SetFieldValue(ScopedFastNativeObjectAccess& soa, mirror::Object* o,
+ mirror::ArtField* f, const JValue& new_value, bool allow_references)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(f->GetDeclaringClass(),
- true, true)) {
+ CHECK(!kMovingFields);
+ SirtRef<mirror::Object> sirt_obj(soa.Self(), o);
+ SirtRef<mirror::Class> sirt_klass(soa.Self(), f->GetDeclaringClass());
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_klass, true, true)) {
return;
}
+ o = sirt_obj.get();
switch (FieldHelper(f).GetTypeAsPrimitiveType()) {
case Primitive::kPrimBoolean:
f->SetBoolean(o, new_value.GetZ());
@@ -237,7 +243,7 @@ static void Field_set(JNIEnv* env, jobject javaField, jobject javaObj, jobject j
return;
}
- SetFieldValue(o, f, unboxed_value, true);
+ SetFieldValue(soa, o, f, unboxed_value, true);
}
static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, char src_descriptor,
@@ -264,7 +270,7 @@ static void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, c
}
// Write the value.
- SetFieldValue(o, f, wide_value, false);
+ SetFieldValue(soa, o, f, wide_value, false);
}
static void Field_setBoolean(JNIEnv* env, jobject javaField, jobject javaObj, jboolean z) {
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index e37510c..cc996bc 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -34,34 +34,36 @@
namespace art {
+template <typename T>
class ObjectLock {
public:
- explicit ObjectLock(Thread* self, mirror::Object* object)
+ explicit ObjectLock(Thread* self, const SirtRef<T>* object)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: self_(self), obj_(object) {
- CHECK(object != NULL);
- obj_->MonitorEnter(self_);
+ CHECK(object != nullptr);
+ CHECK(object->get() != nullptr);
+ obj_->get()->MonitorEnter(self_);
}
~ObjectLock() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->MonitorExit(self_);
+ obj_->get()->MonitorExit(self_);
}
void WaitIgnoringInterrupts() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Monitor::Wait(self_, obj_, 0, 0, false, kWaiting);
+ Monitor::Wait(self_, obj_->get(), 0, 0, false, kWaiting);
}
void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->Notify(self_);
+ obj_->get()->Notify(self_);
}
void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- obj_->NotifyAll(self_);
+ obj_->get()->NotifyAll(self_);
}
private:
Thread* const self_;
- mirror::Object* obj_;
+ const SirtRef<T>* obj_;
DISALLOW_COPY_AND_ASSIGN(ObjectLock);
};
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 80e16aa..ac8f5ef 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -39,8 +39,12 @@ jobject InvokeMethod(const ScopedObjectAccess& soa, jobject javaMethod, jobject
mirror::ArtMethod* m = soa.DecodeMethod(mid);
mirror::Class* declaring_class = m->GetDeclaringClass();
- if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaring_class, true, true)) {
- return NULL;
+ if (UNLIKELY(!declaring_class->IsInitialized())) {
+ SirtRef<mirror::Class> sirt_c(soa.Self(), declaring_class);
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true)) {
+ return nullptr;
+ }
+ declaring_class = sirt_c.get();
}
mirror::Object* receiver = NULL;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 4048bd3..e1b4d7e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -47,6 +47,7 @@
#include "mirror/array.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
+#include "mirror/stack_trace_element.h"
#include "mirror/throwable.h"
#include "monitor.h"
#include "oat_file.h"
@@ -86,6 +87,7 @@ Runtime::Runtime()
resolution_method_(NULL),
imt_conflict_method_(NULL),
default_imt_(NULL),
+ method_verifiers_lock_("Method verifiers lock"),
threads_being_born_(0),
shutdown_cond_(new ConditionVariable("Runtime shutdown", *Locks::runtime_shutdown_lock_)),
shutting_down_(false),
@@ -699,35 +701,38 @@ jobject CreateSystemClassLoader() {
}
ScopedObjectAccess soa(Thread::Current());
+ ClassLinker* cl = Runtime::Current()->GetClassLinker();
- mirror::Class* class_loader_class =
- soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader);
- CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(class_loader_class, true, true));
+ SirtRef<mirror::Class> class_loader_class(
+ soa.Self(), soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_ClassLoader));
+ CHECK(cl->EnsureInitialized(class_loader_class, true, true));
mirror::ArtMethod* getSystemClassLoader =
class_loader_class->FindDirectMethod("getSystemClassLoader", "()Ljava/lang/ClassLoader;");
CHECK(getSystemClassLoader != NULL);
JValue result;
- ArgArray arg_array(NULL, 0);
+ ArgArray arg_array(nullptr, 0);
InvokeWithArgArray(soa, getSystemClassLoader, &arg_array, &result, 'L');
- mirror::ClassLoader* class_loader = down_cast<mirror::ClassLoader*>(result.GetL());
- CHECK(class_loader != NULL);
-
+ SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
+ down_cast<mirror::ClassLoader*>(result.GetL()));
+ CHECK(class_loader.get() != nullptr);
JNIEnv* env = soa.Self()->GetJniEnv();
- ScopedLocalRef<jobject> system_class_loader(env, soa.AddLocalReference<jobject>(class_loader));
- CHECK(system_class_loader.get() != NULL);
+ ScopedLocalRef<jobject> system_class_loader(env,
+ soa.AddLocalReference<jobject>(class_loader.get()));
+ CHECK(system_class_loader.get() != nullptr);
- soa.Self()->SetClassLoaderOverride(class_loader);
+ soa.Self()->SetClassLoaderOverride(class_loader.get());
- mirror::Class* thread_class = soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread);
- CHECK(Runtime::Current()->GetClassLinker()->EnsureInitialized(thread_class, true, true));
+ SirtRef<mirror::Class> thread_class(soa.Self(),
+ soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_Thread));
+ CHECK(cl->EnsureInitialized(thread_class, true, true));
- mirror::ArtField* contextClassLoader = thread_class->FindDeclaredInstanceField("contextClassLoader",
- "Ljava/lang/ClassLoader;");
+ mirror::ArtField* contextClassLoader =
+ thread_class->FindDeclaredInstanceField("contextClassLoader", "Ljava/lang/ClassLoader;");
CHECK(contextClassLoader != NULL);
- contextClassLoader->SetObject(soa.Self()->GetPeer(), class_loader);
+ contextClassLoader->SetObject(soa.Self()->GetPeer(), class_loader.get());
return env->NewGlobalRef(system_class_loader.get());
}
@@ -1188,9 +1193,25 @@ void Runtime::VisitConcurrentRoots(RootVisitor* visitor, void* arg, bool only_di
}
void Runtime::VisitNonThreadRoots(RootVisitor* visitor, void* arg) {
+ // Visit the classes held as static in mirror classes.
+ mirror::ArtField::VisitRoots(visitor, arg);
+ mirror::ArtMethod::VisitRoots(visitor, arg);
+ mirror::Class::VisitRoots(visitor, arg);
+ mirror::StackTraceElement::VisitRoots(visitor, arg);
+ mirror::String::VisitRoots(visitor, arg);
+ mirror::Throwable::VisitRoots(visitor, arg);
+ // Visit all the primitive array types classes.
+ mirror::PrimitiveArray<uint8_t>::VisitRoots(visitor, arg); // BooleanArray
+ mirror::PrimitiveArray<int8_t>::VisitRoots(visitor, arg); // ByteArray
+ mirror::PrimitiveArray<uint16_t>::VisitRoots(visitor, arg); // CharArray
+ mirror::PrimitiveArray<double>::VisitRoots(visitor, arg); // DoubleArray
+ mirror::PrimitiveArray<float>::VisitRoots(visitor, arg); // FloatArray
+ mirror::PrimitiveArray<int32_t>::VisitRoots(visitor, arg); // IntArray
+ mirror::PrimitiveArray<int64_t>::VisitRoots(visitor, arg); // LongArray
+ mirror::PrimitiveArray<int16_t>::VisitRoots(visitor, arg); // ShortArray
java_vm_->VisitRoots(visitor, arg);
if (pre_allocated_OutOfMemoryError_ != nullptr) {
- pre_allocated_OutOfMemoryError_ = reinterpret_cast<mirror::Throwable*>(
+ pre_allocated_OutOfMemoryError_ = down_cast<mirror::Throwable*>(
visitor(pre_allocated_OutOfMemoryError_, arg));
DCHECK(pre_allocated_OutOfMemoryError_ != nullptr);
}
@@ -1209,6 +1230,12 @@ void Runtime::VisitNonThreadRoots(RootVisitor* visitor, void* arg) {
visitor(callee_save_methods_[i], arg));
}
}
+ {
+ MutexLock mu(Thread::Current(), method_verifiers_lock_);
+ for (verifier::MethodVerifier* verifier : method_verifiers_) {
+ verifier->VisitRoots(visitor, arg);
+ }
+ }
}
void Runtime::VisitNonConcurrentRoots(RootVisitor* visitor, void* arg) {
@@ -1355,4 +1382,18 @@ void Runtime::SetCompileTimeClassPath(jobject class_loader, std::vector<const De
compile_time_class_paths_.Put(class_loader, class_path);
}
+void Runtime::AddMethodVerifier(verifier::MethodVerifier* verifier) {
+ DCHECK(verifier != nullptr);
+ MutexLock mu(Thread::Current(), method_verifiers_lock_);
+ method_verifiers_.insert(verifier);
+}
+
+void Runtime::RemoveMethodVerifier(verifier::MethodVerifier* verifier) {
+ DCHECK(verifier != nullptr);
+ MutexLock mu(Thread::Current(), method_verifiers_lock_);
+ auto it = method_verifiers_.find(verifier);
+ CHECK(it != method_verifiers_.end());
+ method_verifiers_.erase(it);
+}
+
} // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index e6951d9..01a605a 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -52,6 +52,9 @@ namespace mirror {
class String;
class Throwable;
} // namespace mirror
+namespace verifier {
+class MethodVerifier;
+}
class ClassLinker;
class DexFile;
class InternTable;
@@ -320,14 +323,16 @@ class Runtime {
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Visit all of the roots we can do safely do concurrently.
- void VisitConcurrentRoots(RootVisitor* visitor, void* arg, bool only_dirty, bool clean_dirty);
+ void VisitConcurrentRoots(RootVisitor* visitor, void* arg, bool only_dirty, bool clean_dirty)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Visit all of the non thread roots, we can do this with mutators unpaused.
- void VisitNonThreadRoots(RootVisitor* visitor, void* arg);
+ void VisitNonThreadRoots(RootVisitor* visitor, void* arg)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Visit all other roots which must be done with mutators suspended.
void VisitNonConcurrentRoots(RootVisitor* visitor, void* arg)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Sweep system weaks, the system weak is deleted if the visitor return nullptr. Otherwise, the
// system weak is updated to be the visitor's returned value.
@@ -438,6 +443,9 @@ class Runtime {
return use_compile_time_class_path_;
}
+ void AddMethodVerifier(verifier::MethodVerifier* verifier);
+ void RemoveMethodVerifier(verifier::MethodVerifier* verifier);
+
const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader);
void SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path);
@@ -520,6 +528,10 @@ class Runtime {
mirror::ObjectArray<mirror::ArtMethod>* default_imt_;
+ // Method verifier set, used so that we can update their GC roots.
+ Mutex method_verifiers_lock_;
+ std::set<verifier::MethodVerifier*> method_verifiers_;
+
// A non-zero value indicates that a thread has been created but not yet initialized. Guarded by
// the shutdown lock so that threads aren't born while we're shutting down.
size_t threads_being_born_ GUARDED_BY(Locks::runtime_shutdown_lock_);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 715be99..570379a 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -987,8 +987,9 @@ void Thread::Destroy() {
mirror::Object* lock =
soa.DecodeField(WellKnownClasses::java_lang_Thread_lock)->GetObject(opeer_);
// (This conditional is only needed for tests, where Thread.lock won't have been set.)
- if (lock != NULL) {
- ObjectLock locker(self, lock);
+ if (lock != nullptr) {
+ SirtRef<mirror::Object> sirt_obj(self, lock);
+ ObjectLock<mirror::Object> locker(self, &sirt_obj);
locker.Notify();
}
}
@@ -1444,9 +1445,9 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
ClearException();
Runtime* runtime = Runtime::Current();
- mirror::ClassLoader* cl = NULL;
- if (throw_location.GetMethod() != NULL) {
- cl = throw_location.GetMethod()->GetDeclaringClass()->GetClassLoader();
+ mirror::ClassLoader* cl = nullptr;
+ if (saved_throw_method.get() != nullptr) {
+ cl = saved_throw_method.get()->GetDeclaringClass()->GetClassLoader();
}
SirtRef<mirror::ClassLoader> class_loader(this, cl);
SirtRef<mirror::Class>
@@ -1458,7 +1459,7 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
return;
}
- if (UNLIKELY(!runtime->GetClassLinker()->EnsureInitialized(exception_class.get(), true, true))) {
+ if (UNLIKELY(!runtime->GetClassLinker()->EnsureInitialized(exception_class, true, true))) {
DCHECK(IsExceptionPending());
return;
}
@@ -1468,7 +1469,9 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
// If we couldn't allocate the exception, throw the pre-allocated out of memory exception.
if (exception.get() == nullptr) {
- SetException(throw_location, Runtime::Current()->GetPreAllocatedOutOfMemoryError());
+ ThrowLocation gc_safe_throw_location(saved_throw_this.get(), saved_throw_method.get(),
+ throw_location.GetDexPc());
+ SetException(gc_safe_throw_location, Runtime::Current()->GetPreAllocatedOutOfMemoryError());
return;
}
diff --git a/runtime/throw_location.cc b/runtime/throw_location.cc
index 01497ef..1cc3e74 100644
--- a/runtime/throw_location.cc
+++ b/runtime/throw_location.cc
@@ -25,7 +25,7 @@
namespace art {
std::string ThrowLocation::Dump() const {
- if (method_ != NULL) {
+ if (method_ != nullptr) {
return StringPrintf("%s:%d", PrettyMethod(method_).c_str(),
MethodHelper(method_).GetLineNumFromDexPC(dex_pc_));
} else {
@@ -35,12 +35,11 @@ std::string ThrowLocation::Dump() const {
void ThrowLocation::VisitRoots(RootVisitor* visitor, void* arg) {
if (this_object_ != nullptr) {
- this_object_ = const_cast<mirror::Object*>(visitor(this_object_, arg));
+ this_object_ = visitor(this_object_, arg);
DCHECK(this_object_ != nullptr);
}
if (method_ != nullptr) {
- method_ = const_cast<mirror::ArtMethod*>(
- reinterpret_cast<const mirror::ArtMethod*>(visitor(method_, arg)));
+ method_ = down_cast<mirror::ArtMethod*>(visitor(method_, arg));
DCHECK(method_ != nullptr);
}
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 5f5d865..9183b5f 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -319,10 +319,12 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, SirtRef<mirror::DexCache
allow_soft_failures_(allow_soft_failures),
has_check_casts_(false),
has_virtual_or_interface_invokes_(false) {
+ Runtime::Current()->AddMethodVerifier(this);
DCHECK(class_def != nullptr);
}
MethodVerifier::~MethodVerifier() {
+ Runtime::Current()->RemoveMethodVerifier(this);
STLDeleteElements(&failure_messages_);
}
@@ -4385,5 +4387,9 @@ bool MethodVerifier::IsClassRejected(ClassReference ref) {
return (rejected_classes_->find(ref) != rejected_classes_->end());
}
+void MethodVerifier::VisitRoots(RootVisitor* visitor, void* arg) {
+ reg_types_.VisitRoots(visitor, arg);
+}
+
} // namespace verifier
} // namespace art
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 892b7a8..6b5747b 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -237,6 +237,8 @@ class MethodVerifier {
static bool IsCandidateForCompilation(MethodReference& method_ref,
const uint32_t access_flags);
+ void VisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
// Adds the given string to the beginning of the last failure message.
void PrependToLastFailMessage(std::string);
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index d82e75d..f394bce 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -969,6 +969,12 @@ void RegType::CheckInvariants() const {
}
}
+void RegType::VisitRoots(RootVisitor* visitor, void* arg) {
+ if (klass_ != nullptr) {
+ klass_ = down_cast<mirror::Class*>(visitor(klass_, arg));
+ }
+}
+
void UninitializedThisReferenceType::CheckInvariants() const {
CHECK_EQ(GetAllocationPc(), 0U) << *this;
}
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index f371733..8df481f 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -20,6 +20,7 @@
#include "base/macros.h"
#include "globals.h"
#include "primitive.h"
+#include "root_visitor.h"
#include "jni.h"
@@ -269,6 +270,8 @@ class RegType {
virtual ~RegType() {}
+ void VisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
protected:
RegType(mirror::Class* klass, const std::string& descriptor, uint16_t cache_id)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
@@ -282,7 +285,7 @@ class RegType {
const std::string descriptor_;
- mirror::Class* const klass_;
+ mirror::Class* klass_;
const uint16_t cache_id_;
friend class RegTypeCache;
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 9c9673a..3d24414 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -554,5 +554,11 @@ void RegTypeCache::Dump(std::ostream& os) {
}
}
+void RegTypeCache::VisitRoots(RootVisitor* visitor, void* arg) {
+ for (RegType* entry : entries_) {
+ entry->VisitRoots(visitor, arg);
+ }
+}
+
} // namespace verifier
} // namespace art
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index a9f8bff..a811696 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -21,6 +21,7 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "reg_type.h"
+#include "root_visitor.h"
#include "runtime.h"
#include <stdint.h>
@@ -139,6 +140,8 @@ class RegTypeCache {
void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
const RegType& RegTypeFromPrimitiveType(Primitive::Type) const;
+ void VisitRoots(RootVisitor* visitor, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
void FillPrimitiveAndSmallConstantTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::Class* ResolveClass(const char* descriptor, mirror::ClassLoader* loader)