summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/driver/compiler_driver.cc28
-rw-r--r--compiler/image_test.cc10
-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
55 files changed, 679 insertions, 452 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 7b42879..8e666dd 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1596,7 +1596,8 @@ static void ResolveType(const ParallelCompilationManager* manager, size_t type_i
ClassLinker* class_linker = manager->GetClassLinker();
const DexFile& dex_file = *manager->GetDexFile();
SirtRef<mirror::DexCache> dex_cache(soa.Self(), class_linker->FindDexCache(dex_file));
- SirtRef<mirror::ClassLoader> class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()));
+ SirtRef<mirror::ClassLoader> class_loader(
+ soa.Self(), soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()));
mirror::Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader);
if (klass == NULL) {
@@ -1651,8 +1652,8 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_
jobject jclass_loader = manager->GetClassLoader();
SirtRef<mirror::ClassLoader> class_loader(
soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader));
- mirror::Class* klass = class_linker->FindClass(descriptor, class_loader);
- if (klass == NULL) {
+ SirtRef<mirror::Class> klass(soa.Self(), class_linker->FindClass(descriptor, class_loader));
+ if (klass.get() == nullptr) {
CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
@@ -1669,8 +1670,8 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_
LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
<< " because: " << error_msg;
}
- } else if (!SkipClass(jclass_loader, dex_file, klass)) {
- CHECK(klass->IsResolved()) << PrettyClass(klass);
+ } else if (!SkipClass(jclass_loader, dex_file, klass.get())) {
+ CHECK(klass->IsResolved()) << PrettyClass(klass.get());
class_linker->VerifyClass(klass);
if (klass->IsErroneous()) {
@@ -1680,7 +1681,7 @@ static void VerifyClass(const ParallelCompilationManager* manager, size_t class_
}
CHECK(klass->IsCompileTimeVerified() || klass->IsErroneous())
- << PrettyDescriptor(klass) << ": state=" << klass->GetStatus();
+ << PrettyDescriptor(klass.get()) << ": state=" << klass->GetStatus();
}
soa.Self()->AssertNoPendingException();
}
@@ -2123,9 +2124,10 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
ScopedObjectAccess soa(Thread::Current());
SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
soa.Decode<mirror::ClassLoader*>(jclass_loader));
- mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader);
+ SirtRef<mirror::Class> klass(soa.Self(),
+ manager->GetClassLinker()->FindClass(descriptor, class_loader));
- if (klass != NULL && !SkipClass(jclass_loader, dex_file, klass)) {
+ if (klass.get() != nullptr && !SkipClass(jclass_loader, dex_file, klass.get())) {
// Only try to initialize classes that were successfully verified.
if (klass->IsVerified()) {
// Attempt to initialize the class but bail if we either need to initialize the super-class
@@ -2140,7 +2142,8 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
// parent-to-child and a child-to-parent lock ordering and consequent potential deadlock.
// We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
// than use a special Object for the purpose we use the Class of java.lang.Class.
- ObjectLock lock(soa.Self(), klass->GetClass());
+ SirtRef<mirror::Class> sirt_klass(soa.Self(), klass->GetClass());
+ ObjectLock<mirror::Class> lock(soa.Self(), &sirt_klass);
// Attempt to initialize allowing initialization of parent classes but still not static
// fields.
manager->GetClassLinker()->EnsureInitialized(klass, false, true);
@@ -2164,10 +2167,11 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
VLOG(compiler) << "Initializing: " << descriptor;
if (strcmp("Ljava/lang/Void;", descriptor) == 0) {
// Hand initialize j.l.Void to avoid Dex file operations in un-started runtime.
- ObjectLock lock(soa.Self(), klass);
+ ObjectLock<mirror::Class> lock(soa.Self(), &klass);
mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
CHECK_EQ(fields->GetLength(), 1);
- fields->Get(0)->SetObj(klass, manager->GetClassLinker()->FindPrimitiveClass('V'));
+ fields->Get(0)->SetObj(klass.get(),
+ manager->GetClassLinker()->FindPrimitiveClass('V'));
klass->SetStatus(mirror::Class::kStatusInitialized, soa.Self());
} else {
manager->GetClassLinker()->EnsureInitialized(klass, true, true);
@@ -2180,7 +2184,7 @@ static void InitializeClass(const ParallelCompilationManager* manager, size_t cl
// If successfully initialized place in SSB array.
if (klass->IsInitialized()) {
int32_t ssb_index = klass->GetDexTypeIndex();
- klass->GetDexCache()->GetInitializedStaticStorage()->Set(ssb_index, klass);
+ klass->GetDexCache()->GetInitializedStaticStorage()->Set(ssb_index, klass.get());
}
}
// Record the final class status if necessary.
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index c71cc97..3406fe6 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -152,14 +152,14 @@ TEST_F(ImageTest, WriteRead) {
const DexFile::ClassDef& class_def = dex->GetClassDef(i);
const char* descriptor = dex->GetClassDescriptor(class_def);
mirror::Class* klass = class_linker_->FindSystemClass(descriptor);
- EXPECT_TRUE(klass != NULL) << descriptor;
- EXPECT_LT(image_begin, reinterpret_cast<byte*>(klass)) << descriptor;
+ EXPECT_TRUE(klass != nullptr) << descriptor;
if (image_classes.find(descriptor) != image_classes.end()) {
- // image classes should be located before the end of the image.
+ // Image classes should be located inside the image.
+ EXPECT_LT(image_begin, reinterpret_cast<byte*>(klass)) << descriptor;
EXPECT_LT(reinterpret_cast<byte*>(klass), image_end) << descriptor;
} else {
- // non image classes should be in a space after the image.
- EXPECT_GT(reinterpret_cast<byte*>(klass), image_end) << descriptor;
+ EXPECT_TRUE(reinterpret_cast<byte*>(klass) >= image_end ||
+ reinterpret_cast<byte*>(klass) < image_begin) << descriptor;
}
EXPECT_TRUE(Monitor::IsValidLockWord(klass->GetLockWord()));
}
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)