diff options
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) |