diff options
author | 2012-10-04 10:09:15 -0700 | |
---|---|---|
committer | 2012-10-05 11:07:39 -0700 | |
commit | 50b35e2fd1a68cd1240e4a9d9f363e11764957d1 (patch) | |
tree | 4f3c58b7b293380f19e4f33357cb352e3330772e | |
parent | 8e9a1497f0d7da4d55f6e7ed8a7d96ba6db7222d (diff) |
Explicitly pass Thread::Current to MutexLock and Alloc.
Change-Id: I8b75bc0617915465f102815b32306aa7760dcae4
63 files changed, 782 insertions, 764 deletions
diff --git a/src/atomic.cc b/src/atomic.cc index 2638b21cd3..008aa87151 100644 --- a/src/atomic.cc +++ b/src/atomic.cc @@ -22,6 +22,7 @@ #include "mutex.h" #include "stl_util.h" #include "stringprintf.h" +#include "thread.h" #if defined(__APPLE__) #include <libkern/OSAtomic.h> @@ -172,7 +173,7 @@ static inline Mutex& GetSwapLock(const volatile int64_t* addr) { } int64_t QuasiAtomic::Swap64(int64_t value, volatile int64_t* addr) { - MutexLock mu(GetSwapLock(addr)); + MutexLock mu(Thread::Current(), GetSwapLock(addr)); int64_t old_value = *addr; *addr = value; return old_value; @@ -184,7 +185,7 @@ int64_t QuasiAtomic::Swap64Sync(int64_t value, volatile int64_t* addr) { } int QuasiAtomic::Cas64(int64_t old_value, int64_t new_value, volatile int64_t* addr) { - MutexLock mu(GetSwapLock(addr)); + MutexLock mu(Thread::Current(), GetSwapLock(addr)); if (*addr == old_value) { *addr = new_value; return 0; @@ -193,7 +194,7 @@ int QuasiAtomic::Cas64(int64_t old_value, int64_t new_value, volatile int64_t* a } int64_t QuasiAtomic::Read64(volatile const int64_t* addr) { - MutexLock mu(GetSwapLock(addr)); + MutexLock mu(Thread::Current(), GetSwapLock(addr)); return *addr; } diff --git a/src/class_linker.cc b/src/class_linker.cc index 448ad6a05a..9ce641febf 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -235,47 +235,48 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class // java_lang_Class comes first, it's needed for AllocClass Thread* self = Thread::Current(); Heap* heap = Runtime::Current()->GetHeap(); - SirtRef<Class> java_lang_Class(self, down_cast<Class*>(heap->AllocObject(NULL, sizeof(ClassClass)))); + SirtRef<Class> + java_lang_Class(self, down_cast<Class*>(heap->AllocObject(self, NULL, sizeof(ClassClass)))); CHECK(java_lang_Class.get() != NULL); java_lang_Class->SetClass(java_lang_Class.get()); java_lang_Class->SetClassSize(sizeof(ClassClass)); // AllocClass(Class*) can now be used // Class[] is used for reflection support. - SirtRef<Class> class_array_class(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> class_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); class_array_class->SetComponentType(java_lang_Class.get()); // java_lang_Object comes next so that object_array_class can be created. - SirtRef<Class> java_lang_Object(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> java_lang_Object(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); CHECK(java_lang_Object.get() != NULL); // backfill Object as the super class of Class. java_lang_Class->SetSuperClass(java_lang_Object.get()); java_lang_Object->SetStatus(Class::kStatusLoaded); // Object[] next to hold class roots. - SirtRef<Class> object_array_class(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> object_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); object_array_class->SetComponentType(java_lang_Object.get()); // Object[][] needed for iftables. - SirtRef<Class> object_array_array_class(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> object_array_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); object_array_array_class->SetComponentType(object_array_class.get()); // Setup the char class to be used for char[]. - SirtRef<Class> char_class(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> char_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); // Setup the char[] class to be used for String. - SirtRef<Class> char_array_class(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> char_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); char_array_class->SetComponentType(char_class.get()); CharArray::SetArrayClass(char_array_class.get()); // Setup String. - SirtRef<Class> java_lang_String(self, AllocClass(java_lang_Class.get(), sizeof(StringClass))); + SirtRef<Class> java_lang_String(self, AllocClass(self, java_lang_Class.get(), sizeof(StringClass))); String::SetClass(java_lang_String.get()); java_lang_String->SetObjectSize(sizeof(String)); java_lang_String->SetStatus(Class::kStatusResolved); // Create storage for root classes, save away our work so far (requires descriptors). - class_roots_ = ObjectArray<Class>::Alloc(object_array_class.get(), kClassRootsMax); + class_roots_ = ObjectArray<Class>::Alloc(self, object_array_class.get(), kClassRootsMax); CHECK(class_roots_ != NULL); SetClassRoot(kJavaLangClass, java_lang_Class.get()); SetClassRoot(kJavaLangObject, java_lang_Object.get()); @@ -286,20 +287,20 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class SetClassRoot(kJavaLangString, java_lang_String.get()); // Setup the primitive type classes. - SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(Primitive::kPrimBoolean)); - SetClassRoot(kPrimitiveByte, CreatePrimitiveClass(Primitive::kPrimByte)); - SetClassRoot(kPrimitiveShort, CreatePrimitiveClass(Primitive::kPrimShort)); - SetClassRoot(kPrimitiveInt, CreatePrimitiveClass(Primitive::kPrimInt)); - SetClassRoot(kPrimitiveLong, CreatePrimitiveClass(Primitive::kPrimLong)); - SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass(Primitive::kPrimFloat)); - SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass(Primitive::kPrimDouble)); - SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(Primitive::kPrimVoid)); + SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean)); + SetClassRoot(kPrimitiveByte, CreatePrimitiveClass(self, Primitive::kPrimByte)); + SetClassRoot(kPrimitiveShort, CreatePrimitiveClass(self, Primitive::kPrimShort)); + SetClassRoot(kPrimitiveInt, CreatePrimitiveClass(self, Primitive::kPrimInt)); + SetClassRoot(kPrimitiveLong, CreatePrimitiveClass(self, Primitive::kPrimLong)); + SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass(self, Primitive::kPrimFloat)); + SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass(self, Primitive::kPrimDouble)); + SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(self, Primitive::kPrimVoid)); // Create array interface entries to populate once we can load system classes. - array_iftable_ = AllocIfTable(2); + array_iftable_ = AllocIfTable(self, 2); // Create int array type for AllocDexCache (done in AppendToBootClassPath). - SirtRef<Class> int_array_class(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> int_array_class(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt)); IntArray::SetArrayClass(int_array_class.get()); SetClassRoot(kIntArrayClass, int_array_class.get()); @@ -307,34 +308,37 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class // now that these are registered, we can use AllocClass() and AllocObjectArray // Setup DexCache. This can not be done later since AppendToBootClassPath calls AllocDexCache. - SirtRef<Class> java_lang_DexCache(self, AllocClass(java_lang_Class.get(), sizeof(DexCacheClass))); + SirtRef<Class> + java_lang_DexCache(self, AllocClass(self, java_lang_Class.get(), sizeof(DexCacheClass))); SetClassRoot(kJavaLangDexCache, java_lang_DexCache.get()); java_lang_DexCache->SetObjectSize(sizeof(DexCacheClass)); java_lang_DexCache->SetStatus(Class::kStatusResolved); // Constructor, Field, Method, and AbstractMethod are necessary so that FindClass can link members. - SirtRef<Class> java_lang_reflect_Constructor(self, AllocClass(java_lang_Class.get(), - sizeof(MethodClass))); + SirtRef<Class> java_lang_reflect_Constructor(self, AllocClass(self, java_lang_Class.get(), + sizeof(MethodClass))); CHECK(java_lang_reflect_Constructor.get() != NULL); java_lang_reflect_Constructor->SetObjectSize(sizeof(Constructor)); SetClassRoot(kJavaLangReflectConstructor, java_lang_reflect_Constructor.get()); java_lang_reflect_Constructor->SetStatus(Class::kStatusResolved); - SirtRef<Class> java_lang_reflect_Field(self, AllocClass(java_lang_Class.get(), sizeof(FieldClass))); + SirtRef<Class> java_lang_reflect_Field(self, AllocClass(self, java_lang_Class.get(), + sizeof(FieldClass))); CHECK(java_lang_reflect_Field.get() != NULL); java_lang_reflect_Field->SetObjectSize(sizeof(Field)); SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field.get()); java_lang_reflect_Field->SetStatus(Class::kStatusResolved); Field::SetClass(java_lang_reflect_Field.get()); - SirtRef<Class> java_lang_reflect_Method(self, AllocClass(java_lang_Class.get(), sizeof(MethodClass))); + SirtRef<Class> java_lang_reflect_Method(self, AllocClass(self, java_lang_Class.get(), + sizeof(MethodClass))); CHECK(java_lang_reflect_Method.get() != NULL); java_lang_reflect_Method->SetObjectSize(sizeof(Method)); SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method.get()); java_lang_reflect_Method->SetStatus(Class::kStatusResolved); - SirtRef<Class> java_lang_reflect_AbstractMethod(self, AllocClass(java_lang_Class.get(), - sizeof(MethodClass))); + SirtRef<Class> java_lang_reflect_AbstractMethod(self, AllocClass(self, java_lang_Class.get(), + sizeof(MethodClass))); CHECK(java_lang_reflect_AbstractMethod.get() != NULL); java_lang_reflect_AbstractMethod->SetObjectSize(sizeof(AbstractMethod)); SetClassRoot(kJavaLangReflectAbstractMethod, java_lang_reflect_AbstractMethod.get()); @@ -342,15 +346,15 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class AbstractMethod::SetClasses(java_lang_reflect_Constructor.get(), java_lang_reflect_Method.get()); // Set up array classes for string, field, method - SirtRef<Class> object_array_string(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> object_array_string(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); object_array_string->SetComponentType(java_lang_String.get()); SetClassRoot(kJavaLangStringArrayClass, object_array_string.get()); - SirtRef<Class> object_array_field(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> object_array_field(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); object_array_field->SetComponentType(java_lang_reflect_Field.get()); SetClassRoot(kJavaLangReflectFieldArrayClass, object_array_field.get()); - SirtRef<Class> object_array_abstract_method(self, AllocClass(java_lang_Class.get(), sizeof(Class))); + SirtRef<Class> object_array_abstract_method(self, AllocClass(self, java_lang_Class.get(), sizeof(Class))); object_array_abstract_method->SetComponentType(java_lang_reflect_AbstractMethod.get()); SetClassRoot(kJavaLangReflectAbstractMethodArrayClass, object_array_abstract_method.get()); @@ -426,8 +430,8 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class CHECK(java_io_Serializable != NULL); // We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to // crawl up and explicitly list all of the supers as well. - array_iftable_->Set(0, AllocInterfaceEntry(java_lang_Cloneable)); - array_iftable_->Set(1, AllocInterfaceEntry(java_io_Serializable)); + array_iftable_->Set(0, AllocInterfaceEntry(self, java_lang_Cloneable)); + array_iftable_->Set(1, AllocInterfaceEntry(self, java_io_Serializable)); // Sanity check Class[] and Object[]'s interfaces. ClassHelper kh(class_array_class.get(), this); @@ -667,17 +671,17 @@ bool ClassLinker::GenerateOatFile(const std::string& dex_filename, } void ClassLinker::RegisterOatFile(const OatFile& oat_file) { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); RegisterOatFileLocked(oat_file); } void ClassLinker::RegisterOatFileLocked(const OatFile& oat_file) { - dex_lock_.AssertHeld(); + dex_lock_.AssertHeld(Thread::Current()); oat_files_.push_back(&oat_file); } OatFile* ClassLinker::OpenOat(const ImageSpace* space) { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); const Runtime* runtime = Runtime::Current(); const ImageHeader& image_header = space->GetImageHeader(); // Grab location but don't use Object::AsString as we haven't yet initialized the roots to @@ -708,7 +712,7 @@ OatFile* ClassLinker::OpenOat(const ImageSpace* space) { } const OatFile* ClassLinker::FindOpenedOatFileForDexFile(const DexFile& dex_file) { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); return FindOpenedOatFileFromDexLocation(dex_file.GetLocation()); } @@ -750,7 +754,7 @@ static const DexFile* FindDexFileInOatLocation(const std::string& dex_location, const DexFile* ClassLinker::FindOrCreateOatFileForDexLocation(const std::string& dex_location, const std::string& oat_location) { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); return FindOrCreateOatFileForDexLocationLocked(dex_location, oat_location); } @@ -855,7 +859,7 @@ const DexFile* ClassLinker::VerifyAndOpenDexFileFromOatFile(const OatFile* oat_f } const DexFile* ClassLinker::FindDexFileInOatFileFromDexLocation(const std::string& dex_location) { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); const OatFile* open_oat_file = FindOpenedOatFileFromDexLocation(dex_location); if (open_oat_file != NULL) { @@ -922,7 +926,7 @@ const OatFile* ClassLinker::FindOpenedOatFileFromOatLocation(const std::string& } const OatFile* ClassLinker::FindOatFileFromOatLocation(const std::string& oat_location) { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); return FindOatFileFromOatLocationLocked(oat_location); } @@ -980,7 +984,7 @@ void ClassLinker::InitFromImage() { // reinit clases_ table { - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); heap->FlushAllocStack(); heap->GetLiveBitmap()->Walk(InitFromImageCallback, this); } @@ -1037,16 +1041,16 @@ void ClassLinker::InitFromImageCallback(Object* obj, void* arg) { // mapped image. void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { visitor(class_roots_, arg); - + Thread* self = Thread::Current(); { - MutexLock mu(dex_lock_); + MutexLock mu(self, dex_lock_); for (size_t i = 0; i < dex_caches_.size(); i++) { visitor(dex_caches_[i], arg); } } { - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(self, *Locks::classlinker_classes_lock_); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) { visitor(it->second, arg); @@ -1060,7 +1064,7 @@ void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { } void ClassLinker::VisitClasses(ClassVisitor* visitor, void* arg) const { - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) { if (!visitor(it->second, arg)) { @@ -1110,13 +1114,12 @@ ClassLinker::~ClassLinker() { STLDeleteElements(&oat_files_); } -DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) { +DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) { Heap* heap = Runtime::Current()->GetHeap(); Class* dex_cache_class = GetClassRoot(kJavaLangDexCache); - Thread* self = Thread::Current(); - SirtRef<DexCache> dex_cache( - self, - down_cast<DexCache*>(heap->AllocObject(dex_cache_class, dex_cache_class->GetObjectSize()))); + SirtRef<DexCache> dex_cache(self, + down_cast<DexCache*>(heap->AllocObject(self, dex_cache_class, + dex_cache_class->GetObjectSize()))); if (dex_cache.get() == NULL) { return NULL; } @@ -1124,24 +1127,26 @@ DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) { if (location.get() == NULL) { return NULL; } - SirtRef<ObjectArray<String> > strings(self, AllocStringArray(dex_file.NumStringIds())); + SirtRef<ObjectArray<String> > strings(self, AllocStringArray(self, dex_file.NumStringIds())); if (strings.get() == NULL) { return NULL; } - SirtRef<ObjectArray<Class> > types(self, AllocClassArray(dex_file.NumTypeIds())); + SirtRef<ObjectArray<Class> > types(self, AllocClassArray(self, dex_file.NumTypeIds())); if (types.get() == NULL) { return NULL; } - SirtRef<ObjectArray<AbstractMethod> > methods(self, AllocMethodArray(dex_file.NumMethodIds())); + SirtRef<ObjectArray<AbstractMethod> > + methods(self, AllocMethodArray(self, dex_file.NumMethodIds())); if (methods.get() == NULL) { return NULL; } - SirtRef<ObjectArray<Field> > fields(self, AllocFieldArray(dex_file.NumFieldIds())); + SirtRef<ObjectArray<Field> > fields(self, AllocFieldArray(self, dex_file.NumFieldIds())); if (fields.get() == NULL) { return NULL; } SirtRef<ObjectArray<StaticStorageBase> > - initialized_static_storage(self, AllocObjectArray<StaticStorageBase>(dex_file.NumTypeIds())); + initialized_static_storage(self, + AllocObjectArray<StaticStorageBase>(self, dex_file.NumTypeIds())); if (initialized_static_storage.get() == NULL) { return NULL; } @@ -1156,52 +1161,51 @@ DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) { return dex_cache.get(); } -InterfaceEntry* ClassLinker::AllocInterfaceEntry(Class* interface) { +InterfaceEntry* ClassLinker::AllocInterfaceEntry(Thread* self, Class* interface) { DCHECK(interface->IsInterface()); - Thread* self = Thread::Current(); - SirtRef<ObjectArray<Object> > array(self, AllocObjectArray<Object>(InterfaceEntry::LengthAsArray())); + SirtRef<ObjectArray<Object> > array(self, AllocObjectArray<Object>(self, InterfaceEntry::LengthAsArray())); SirtRef<InterfaceEntry> interface_entry(self, down_cast<InterfaceEntry*>(array.get())); interface_entry->SetInterface(interface); return interface_entry.get(); } -Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) { +Class* ClassLinker::AllocClass(Thread* self, Class* java_lang_Class, size_t class_size) { DCHECK_GE(class_size, sizeof(Class)); Heap* heap = Runtime::Current()->GetHeap(); - SirtRef<Class> klass(Thread::Current(), - heap->AllocObject(java_lang_Class, class_size)->AsClass()); + SirtRef<Class> klass(self, + heap->AllocObject(self, java_lang_Class, class_size)->AsClass()); klass->SetPrimitiveType(Primitive::kPrimNot); // default to not being primitive klass->SetClassSize(class_size); return klass.get(); } -Class* ClassLinker::AllocClass(size_t class_size) { - return AllocClass(GetClassRoot(kJavaLangClass), class_size); +Class* ClassLinker::AllocClass(Thread* self, size_t class_size) { + return AllocClass(self, GetClassRoot(kJavaLangClass), class_size); } -Field* ClassLinker::AllocField() { - return down_cast<Field*>(GetClassRoot(kJavaLangReflectField)->AllocObject()); +Field* ClassLinker::AllocField(Thread* self) { + return down_cast<Field*>(GetClassRoot(kJavaLangReflectField)->AllocObject(self)); } -Method* ClassLinker::AllocMethod() { - return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->AllocObject()); +Method* ClassLinker::AllocMethod(Thread* self) { + return down_cast<Method*>(GetClassRoot(kJavaLangReflectMethod)->AllocObject(self)); } -Constructor* ClassLinker::AllocConstructor() { - return down_cast<Constructor*>(GetClassRoot(kJavaLangReflectConstructor)->AllocObject()); +Constructor* ClassLinker::AllocConstructor(Thread* self) { + return down_cast<Constructor*>(GetClassRoot(kJavaLangReflectConstructor)->AllocObject(self)); } -ObjectArray<StackTraceElement>* ClassLinker::AllocStackTraceElementArray(size_t length) { - return ObjectArray<StackTraceElement>::Alloc( - GetClassRoot(kJavaLangStackTraceElementArrayClass), - length); +ObjectArray<StackTraceElement>* ClassLinker::AllocStackTraceElementArray(Thread* self, + size_t length) { + return ObjectArray<StackTraceElement>::Alloc(self, + GetClassRoot(kJavaLangStackTraceElementArrayClass), + length); } -static Class* EnsureResolved(Class* klass) +static Class* EnsureResolved(Thread* self, Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(klass != NULL); // Wait for the class if it has not already been linked. - Thread* self = Thread::Current(); if (!klass->IsResolved() && !klass->IsErroneous()) { ObjectLock lock(self, klass); // Check for circular dependencies between classes. @@ -1245,7 +1249,7 @@ Class* ClassLinker::FindClass(const char* descriptor, ClassLoader* class_loader) // Find the class in the loaded classes table. Class* klass = LookupClass(descriptor, class_loader); if (klass != NULL) { - return EnsureResolved(klass); + return EnsureResolved(self, klass); } // Class is not yet loaded. if (descriptor[0] == '[') { @@ -1341,10 +1345,10 @@ Class* ClassLinker::DefineClass(const StringPiece& descriptor, } else if (descriptor == "Ljava/lang/reflect/Method;") { klass.reset(GetClassRoot(kJavaLangReflectMethod)); } else { - klass.reset(AllocClass(SizeOfClass(dex_file, dex_class_def))); + klass.reset(AllocClass(self, SizeOfClass(dex_file, dex_class_def))); } } else { - klass.reset(AllocClass(SizeOfClass(dex_file, dex_class_def))); + klass.reset(AllocClass(self, SizeOfClass(dex_file, dex_class_def))); } klass->SetDexCache(FindDexCache(dex_file)); LoadClass(dex_file, dex_class_def, klass, class_loader); @@ -1359,7 +1363,7 @@ Class* ClassLinker::DefineClass(const StringPiece& descriptor, SirtRef<Class> existing(self, InsertClass(descriptor, klass.get(), false)); if (existing.get() != NULL) { // We failed to insert because we raced with another thread. - return EnsureResolved(existing.get()); + return EnsureResolved(self, existing.get()); } // Finish loading (if necessary) by finding parents CHECK(!klass->IsLoaded()); @@ -1588,20 +1592,20 @@ void ClassLinker::LoadClass(const DexFile& dex_file, return; // no fields or methods - for example a marker interface } ClassDataItemIterator it(dex_file, class_data); + Thread* self = Thread::Current(); if (it.NumStaticFields() != 0) { - klass->SetSFields(AllocObjectArray<Field>(it.NumStaticFields())); + klass->SetSFields(AllocObjectArray<Field>(self, it.NumStaticFields())); } if (it.NumInstanceFields() != 0) { - klass->SetIFields(AllocObjectArray<Field>(it.NumInstanceFields())); + klass->SetIFields(AllocObjectArray<Field>(self, it.NumInstanceFields())); } - Thread* self = Thread::Current(); for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) { - SirtRef<Field> sfield(self, AllocField()); + SirtRef<Field> sfield(self, AllocField(self)); klass->SetStaticField(i, sfield.get()); LoadField(dex_file, it, klass, sfield); } for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) { - SirtRef<Field> ifield(self, AllocField()); + SirtRef<Field> ifield(self, AllocField(self)); klass->SetInstanceField(i, ifield.get()); LoadField(dex_file, it, klass, ifield); } @@ -1614,15 +1618,15 @@ void ClassLinker::LoadClass(const DexFile& dex_file, // Load methods. if (it.NumDirectMethods() != 0) { // TODO: append direct methods to class object - klass->SetDirectMethods(AllocObjectArray<AbstractMethod>(it.NumDirectMethods())); + klass->SetDirectMethods(AllocObjectArray<AbstractMethod>(self, it.NumDirectMethods())); } if (it.NumVirtualMethods() != 0) { // TODO: append direct methods to class object - klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(it.NumVirtualMethods())); + klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(self, it.NumVirtualMethods())); } size_t class_def_method_index = 0; for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) { - SirtRef<AbstractMethod> method(self, LoadMethod(dex_file, it, klass)); + SirtRef<AbstractMethod> method(self, LoadMethod(self, dex_file, it, klass)); klass->SetDirectMethod(i, method.get()); if (oat_class.get() != NULL) { LinkCode(method, oat_class.get(), class_def_method_index); @@ -1631,7 +1635,7 @@ void ClassLinker::LoadClass(const DexFile& dex_file, class_def_method_index++; } for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) { - SirtRef<AbstractMethod> method(self, LoadMethod(dex_file, it, klass)); + SirtRef<AbstractMethod> method(self, LoadMethod(self, dex_file, it, klass)); klass->SetVirtualMethod(i, method.get()); DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i); if (oat_class.get() != NULL) { @@ -1650,21 +1654,22 @@ void ClassLinker::LoadField(const DexFile& /*dex_file*/, const ClassDataItemIter dst->SetAccessFlags(it.GetMemberAccessFlags()); } -AbstractMethod* ClassLinker::LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& it, - SirtRef<Class>& klass) { +AbstractMethod* ClassLinker::LoadMethod(Thread* self, const DexFile& dex_file, + const ClassDataItemIterator& it, + SirtRef<Class>& klass) { uint32_t dex_method_idx = it.GetMemberIndex(); const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); StringPiece method_name(dex_file.GetMethodName(method_id)); AbstractMethod* dst = NULL; if (method_name == "<init>") { - dst = AllocConstructor(); + dst = AllocConstructor(self); } else { - dst = AllocMethod(); + dst = AllocMethod(self); } DCHECK(dst->IsMethod()) << PrettyDescriptor(dst->GetClass()); - const char* old_cause = Thread::Current()->StartAssertNoThreadSuspension("LoadMethod"); + const char* old_cause = self->StartAssertNoThreadSuspension("LoadMethod"); dst->SetDexMethodIndex(dex_method_idx); dst->SetDeclaringClass(klass.get()); @@ -1708,12 +1713,13 @@ AbstractMethod* ClassLinker::LoadMethod(const DexFile& dex_file, const ClassData CHECK(dst->IsMethod()); - Thread::Current()->EndAssertNoThreadSuspension(old_cause); + self->EndAssertNoThreadSuspension(old_cause); return dst; } void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) { - SirtRef<DexCache> dex_cache(Thread::Current(), AllocDexCache(dex_file)); + Thread* self = Thread::Current(); + SirtRef<DexCache> dex_cache(self, AllocDexCache(self, dex_file)); AppendToBootClassPath(dex_file, dex_cache); } @@ -1724,7 +1730,7 @@ void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, SirtRef<DexCach } bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) const { - dex_lock_.AssertHeld(); + dex_lock_.AssertHeld(Thread::Current()); for (size_t i = 0; i != dex_caches_.size(); ++i) { if (dex_caches_[i]->GetDexFile() == &dex_file) { return true; @@ -1734,12 +1740,12 @@ bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) const { } bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) const { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); return IsDexFileRegisteredLocked(dex_file); } void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) { - dex_lock_.AssertHeld(); + dex_lock_.AssertHeld(Thread::Current()); CHECK(dex_cache.get() != NULL) << dex_file.GetLocation(); CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation())); dex_caches_.push_back(dex_cache.get()); @@ -1757,7 +1763,7 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) { // Don't alloc while holding the lock, since allocation may need to // suspend all threads and another thread may need the dex_lock_ to // get to a suspend point. - SirtRef<DexCache> dex_cache(self, AllocDexCache(dex_file)); + SirtRef<DexCache> dex_cache(self, AllocDexCache(self, dex_file)); { MutexLock mu(self, dex_lock_); if (IsDexFileRegisteredLocked(dex_file)) { @@ -1768,7 +1774,7 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file) { } void ClassLinker::RegisterDexFile(const DexFile& dex_file, SirtRef<DexCache>& dex_cache) { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); RegisterDexFileLocked(dex_file, dex_cache); } @@ -1783,7 +1789,7 @@ const DexFile& ClassLinker::FindDexFile(const DexCache* dex_cache) const { } DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); for (size_t i = 0; i != dex_caches_.size(); ++i) { DexCache* dex_cache = dex_caches_[i]; if (dex_cache->GetDexFile() == &dex_file) { @@ -1795,7 +1801,7 @@ DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const { } void ClassLinker::FixupDexCaches(AbstractMethod* resolution_method) const { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); for (size_t i = 0; i != dex_caches_.size(); ++i) { dex_caches_[i]->Fixup(resolution_method); } @@ -1891,7 +1897,7 @@ Class* ClassLinker::CreateArrayClass(const std::string& descriptor, ClassLoader* } } if (new_class.get() == NULL) { - new_class.reset(AllocClass(sizeof(Class))); + new_class.reset(AllocClass(self, sizeof(Class))); if (new_class.get() == NULL) { return NULL; } @@ -1986,7 +1992,7 @@ Class* ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass, boo LOG(INFO) << "Loaded class " << descriptor << source; } size_t hash = StringPieceHash()(descriptor); - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); Table& classes = image_class ? image_classes_ : classes_; Class* existing = LookupClassLocked(descriptor.data(), klass->GetClassLoader(), hash, classes); #ifndef NDEBUG @@ -2003,7 +2009,7 @@ Class* ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass, boo bool ClassLinker::RemoveClass(const char* descriptor, const ClassLoader* class_loader) { size_t hash = Hash(descriptor); - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); typedef Table::iterator It; // TODO: C++0x auto // TODO: determine if its better to search classes_ or image_classes_ first ClassHelper kh; @@ -2028,7 +2034,7 @@ bool ClassLinker::RemoveClass(const char* descriptor, const ClassLoader* class_l Class* ClassLinker::LookupClass(const char* descriptor, const ClassLoader* class_loader) { size_t hash = Hash(descriptor); - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); // TODO: determine if its better to search classes_ or image_classes_ first Class* klass = LookupClassLocked(descriptor, class_loader, hash, classes_); if (klass != NULL) { @@ -2063,7 +2069,7 @@ Class* ClassLinker::LookupClassLocked(const char* descriptor, const ClassLoader* void ClassLinker::LookupClasses(const char* descriptor, std::vector<Class*>& classes) { classes.clear(); size_t hash = Hash(descriptor); - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); typedef Table::const_iterator It; // TODO: C++0x auto // TODO: determine if its better to search classes_ or image_classes_ first ClassHelper kh(NULL, this); @@ -2295,7 +2301,8 @@ Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interface ClassLoader* loader, ObjectArray<AbstractMethod>* methods, ObjectArray<ObjectArray<Class> >* throws) { Thread* self = Thread::Current(); - SirtRef<Class> klass(self, AllocClass(GetClassRoot(kJavaLangClass), sizeof(SynthesizedProxyClass))); + SirtRef<Class> klass(self, AllocClass(self, GetClassRoot(kJavaLangClass), + sizeof(SynthesizedProxyClass))); CHECK(klass.get() != NULL); DCHECK(klass->GetClass() != NULL); klass->SetObjectSize(sizeof(Proxy)); @@ -2311,31 +2318,31 @@ Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interface klass->SetDexTypeIndex(DexFile::kDexNoIndex16); // Instance fields are inherited, but we add a couple of static fields... - klass->SetSFields(AllocObjectArray<Field>(2)); + klass->SetSFields(AllocObjectArray<Field>(self, 2)); // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by // our proxy, so Class.getInterfaces doesn't return the flattened set. - SirtRef<Field> interfaces_sfield(self, AllocField()); + SirtRef<Field> interfaces_sfield(self, AllocField(self)); klass->SetStaticField(0, interfaces_sfield.get()); interfaces_sfield->SetDexFieldIndex(0); interfaces_sfield->SetDeclaringClass(klass.get()); interfaces_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal); // 2. Create a static field 'throws' that holds exceptions thrown by our methods. - SirtRef<Field> throws_sfield(self, AllocField()); + SirtRef<Field> throws_sfield(self, AllocField(self)); klass->SetStaticField(1, throws_sfield.get()); throws_sfield->SetDexFieldIndex(1); throws_sfield->SetDeclaringClass(klass.get()); throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal); // Proxies have 1 direct method, the constructor - klass->SetDirectMethods(AllocObjectArray<AbstractMethod>(1)); - klass->SetDirectMethod(0, CreateProxyConstructor(klass, proxy_class)); + klass->SetDirectMethods(AllocObjectArray<AbstractMethod>(self, 1)); + klass->SetDirectMethod(0, CreateProxyConstructor(self, klass, proxy_class)); // Create virtual method using specified prototypes size_t num_virtual_methods = methods->GetLength(); - klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(num_virtual_methods)); + klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(self, num_virtual_methods)); for (size_t i = 0; i < num_virtual_methods; ++i) { SirtRef<AbstractMethod> prototype(self, methods->Get(i)); - klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype)); + klass->SetVirtualMethod(i, CreateProxyMethod(self, klass, prototype)); } klass->SetSuperClass(proxy_class); // The super class is java.lang.reflect.Proxy @@ -2392,7 +2399,7 @@ AbstractMethod* ClassLinker::FindMethodForProxy(const Class* proxy_class, const DexCache* dex_cache = NULL; { ObjectArray<Class>* resolved_types = proxy_method->GetDexCacheResolvedTypes(); - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); for (size_t i = 0; i != dex_caches_.size(); ++i) { if (dex_caches_[i]->GetResolvedTypes() == resolved_types) { dex_cache = dex_caches_[i]; @@ -2408,14 +2415,14 @@ AbstractMethod* ClassLinker::FindMethodForProxy(const Class* proxy_class, const } -AbstractMethod* ClassLinker::CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class) { +AbstractMethod* ClassLinker::CreateProxyConstructor(Thread* self, SirtRef<Class>& klass, Class* proxy_class) { // Create constructor for Proxy that must initialize h ObjectArray<AbstractMethod>* proxy_direct_methods = proxy_class->GetDirectMethods(); CHECK_EQ(proxy_direct_methods->GetLength(), 15); AbstractMethod* proxy_constructor = proxy_direct_methods->Get(2); // Clone the existing constructor of Proxy (our constructor would just invoke it so steal its // code_ too) - AbstractMethod* constructor = down_cast<AbstractMethod*>(proxy_constructor->Clone()); + AbstractMethod* constructor = down_cast<AbstractMethod*>(proxy_constructor->Clone(self)); // Make this constructor public and fix the class to be our Proxy version constructor->SetAccessFlags((constructor->GetAccessFlags() & ~kAccProtected) | kAccPublic); constructor->SetDeclaringClass(klass.get()); @@ -2431,14 +2438,15 @@ static void CheckProxyConstructor(AbstractMethod* constructor) DCHECK(constructor->IsPublic()); } -AbstractMethod* ClassLinker::CreateProxyMethod(SirtRef<Class>& klass, SirtRef<AbstractMethod>& prototype) { +AbstractMethod* ClassLinker::CreateProxyMethod(Thread* self, SirtRef<Class>& klass, + SirtRef<AbstractMethod>& 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(), prototype.get()); // We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize // as necessary - AbstractMethod* method = down_cast<AbstractMethod*>(prototype->Clone()); + AbstractMethod* method = down_cast<AbstractMethod*>(prototype->Clone(self)); // Set class to be the concrete proxy class and clear the abstract flag, modify exceptions to // the intersection of throw exceptions as defined in Proxy @@ -2980,7 +2988,7 @@ bool ClassLinker::LinkVirtualMethods(SirtRef<Class>& klass) { CHECK_LE(actual_count, max_count); // TODO: do not assign to the vtable field until it is fully constructed. SirtRef<ObjectArray<AbstractMethod> > - vtable(self, klass->GetSuperClass()->GetVTable()->CopyOf(max_count)); + vtable(self, klass->GetSuperClass()->GetVTable()->CopyOf(self, max_count)); // See if any of our virtual methods override the superclass. MethodHelper local_mh(NULL, this); MethodHelper super_mh(NULL, this); @@ -3023,7 +3031,7 @@ bool ClassLinker::LinkVirtualMethods(SirtRef<Class>& klass) { // Shrink vtable if possible CHECK_LE(actual_count, max_count); if (actual_count < max_count) { - vtable.reset(vtable->CopyOf(actual_count)); + vtable.reset(vtable->CopyOf(self, actual_count)); } klass->SetVTable(vtable.get()); } else { @@ -3034,7 +3042,7 @@ bool ClassLinker::LinkVirtualMethods(SirtRef<Class>& klass) { return false; } SirtRef<ObjectArray<AbstractMethod> > - vtable(self, AllocObjectArray<AbstractMethod>(num_virtual_methods)); + vtable(self, AllocObjectArray<AbstractMethod>(self, num_virtual_methods)); for (size_t i = 0; i < num_virtual_methods; ++i) { AbstractMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i); vtable->Set(i, virtual_method); @@ -3067,12 +3075,12 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> return true; } Thread* self = Thread::Current(); - SirtRef<ObjectArray<InterfaceEntry> > iftable(self, AllocIfTable(ifcount)); + SirtRef<ObjectArray<InterfaceEntry> > iftable(self, AllocIfTable(self, ifcount)); if (super_ifcount != 0) { ObjectArray<InterfaceEntry>* super_iftable = klass->GetSuperClass()->GetIfTable(); for (size_t i = 0; i < super_ifcount; i++) { Class* super_interface = super_iftable->Get(i)->GetInterface(); - iftable->Set(i, AllocInterfaceEntry(super_interface)); + iftable->Set(i, AllocInterfaceEntry(self, super_interface)); } } // Flatten the interface inheritance hierarchy. @@ -3099,7 +3107,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> } if (!duplicate) { // Add this non-duplicate interface. - iftable->Set(idx++, AllocInterfaceEntry(interface)); + iftable->Set(idx++, AllocInterfaceEntry(self, interface)); // Add this interface's non-duplicate super-interfaces. for (int32_t j = 0; j < interface->GetIfTableCount(); j++) { Class* super_interface = interface->GetIfTable()->Get(j)->GetInterface(); @@ -3112,14 +3120,14 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> } } if (!super_duplicate) { - iftable->Set(idx++, AllocInterfaceEntry(super_interface)); + iftable->Set(idx++, AllocInterfaceEntry(self, super_interface)); } } } } // Shrink iftable in case duplicates were found if (idx < ifcount) { - iftable.reset(iftable->CopyOf(idx)); + iftable.reset(iftable->CopyOf(self, idx)); ifcount = idx; } else { CHECK_EQ(idx, ifcount); @@ -3136,7 +3144,8 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> for (size_t i = 0; i < ifcount; ++i) { InterfaceEntry* interface_entry = iftable->Get(i); Class* interface = interface_entry->GetInterface(); - ObjectArray<AbstractMethod>* method_array = AllocObjectArray<AbstractMethod>(interface->NumVirtualMethods()); + ObjectArray<AbstractMethod>* method_array = + AllocObjectArray<AbstractMethod>(self, interface->NumVirtualMethods()); interface_entry->SetMethodArray(method_array); ObjectArray<AbstractMethod>* vtable = klass->GetVTableDuringLinking(); for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) { @@ -3176,7 +3185,7 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> } if (miranda_method.get() == NULL) { // point the interface table at a phantom slot - miranda_method.reset(down_cast<AbstractMethod*>(interface_method->Clone())); + miranda_method.reset(down_cast<AbstractMethod*>(interface_method->Clone(self))); miranda_list.push_back(miranda_method.get()); } method_array->Set(j, miranda_method.get()); @@ -3187,14 +3196,14 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class> int old_method_count = klass->NumVirtualMethods(); int new_method_count = old_method_count + miranda_list.size(); klass->SetVirtualMethods((old_method_count == 0) - ? AllocObjectArray<AbstractMethod>(new_method_count) - : klass->GetVirtualMethods()->CopyOf(new_method_count)); + ? AllocObjectArray<AbstractMethod>(self, new_method_count) + : klass->GetVirtualMethods()->CopyOf(self, new_method_count)); SirtRef<ObjectArray<AbstractMethod> > vtable(self, klass->GetVTableDuringLinking()); CHECK(vtable.get() != NULL); int old_vtable_count = vtable->GetLength(); int new_vtable_count = old_vtable_count + miranda_list.size(); - vtable.reset(vtable->CopyOf(new_vtable_count)); + vtable.reset(vtable->CopyOf(self, new_vtable_count)); for (size_t i = 0; i < miranda_list.size(); ++i) { AbstractMethod* method = miranda_list[i]; // Leave the declaring class alone as type indices are relative to it @@ -3730,7 +3739,7 @@ void ClassLinker::DumpAllClasses(int flags) const { // lock held, because it might need to resolve a field's type, which would try to take the lock. std::vector<Class*> all_classes; { - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) { all_classes.push_back(it->second); @@ -3746,13 +3755,13 @@ void ClassLinker::DumpAllClasses(int flags) const { } void ClassLinker::DumpForSigQuit(std::ostream& os) const { - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); os << "Loaded classes: " << image_classes_.size() << " image classes; " << classes_.size() << " allocated classes\n"; } size_t ClassLinker::NumLoadedClasses() const { - MutexLock mu(*Locks::classlinker_classes_lock_); + MutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); return classes_.size() + image_classes_.size(); } @@ -3776,7 +3785,7 @@ void ClassLinker::SetClassRoot(ClassRoot class_root, Class* klass) { } void ClassLinker::RelocateExecutable() { - MutexLock mu(dex_lock_); + MutexLock mu(Thread::Current(), dex_lock_); for (size_t i = 0; i < oat_files_.size(); ++i) { const_cast<OatFile*>(oat_files_[i])->RelocateExecutable(); } diff --git a/src/class_linker.h b/src/class_linker.h index b07157a92c..38b402f294 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -313,38 +313,38 @@ class ClassLinker { // TODO: replace this with multiple methods that allocate the correct managed type. template <class T> - ObjectArray<T>* AllocObjectArray(size_t length) + ObjectArray<T>* AllocObjectArray(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<T>::Alloc(GetClassRoot(kObjectArrayClass), length); + return ObjectArray<T>::Alloc(self, GetClassRoot(kObjectArrayClass), length); } - ObjectArray<Class>* AllocClassArray(size_t length) + ObjectArray<Class>* AllocClassArray(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<Class>::Alloc(GetClassRoot(kClassArrayClass), length); + return ObjectArray<Class>::Alloc(self, GetClassRoot(kClassArrayClass), length); } - ObjectArray<String>* AllocStringArray(size_t length) + ObjectArray<String>* AllocStringArray(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<String>::Alloc(GetClassRoot(kJavaLangStringArrayClass), length); + return ObjectArray<String>::Alloc(self, GetClassRoot(kJavaLangStringArrayClass), length); } - ObjectArray<AbstractMethod>* AllocMethodArray(size_t length) + ObjectArray<AbstractMethod>* AllocMethodArray(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<AbstractMethod>::Alloc( + return ObjectArray<AbstractMethod>::Alloc(self, GetClassRoot(kJavaLangReflectAbstractMethodArrayClass), length); } - ObjectArray<InterfaceEntry>* AllocIfTable(size_t length) + ObjectArray<InterfaceEntry>* AllocIfTable(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<InterfaceEntry>::Alloc(GetClassRoot(kObjectArrayArrayClass), length); + return ObjectArray<InterfaceEntry>::Alloc(self, GetClassRoot(kObjectArrayArrayClass), length); } - ObjectArray<Field>* AllocFieldArray(size_t length) + ObjectArray<Field>* AllocFieldArray(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return ObjectArray<Field>::Alloc(GetClassRoot(kJavaLangReflectFieldArrayClass), length); + return ObjectArray<Field>::Alloc(self, GetClassRoot(kJavaLangReflectFieldArrayClass), length); } - ObjectArray<StackTraceElement>* AllocStackTraceElementArray(size_t length) + ObjectArray<StackTraceElement>* AllocStackTraceElementArray(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void VerifyClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -396,25 +396,25 @@ class ClassLinker { void FinishInit() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // For early bootstrapping by Init - Class* AllocClass(Class* java_lang_Class, size_t class_size) + Class* AllocClass(Thread* self, Class* java_lang_Class, size_t class_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Alloc* convenience functions to avoid needing to pass in Class* // values that are known to the ClassLinker such as // kObjectArrayClass and kJavaLangString etc. - Class* AllocClass(size_t class_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - DexCache* AllocDexCache(const DexFile& dex_file) + Class* AllocClass(Thread* self, size_t class_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + DexCache* AllocDexCache(Thread* self, const DexFile& dex_file) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Field* AllocField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Method* AllocMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Constructor* AllocConstructor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Field* AllocField(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Method* AllocMethod(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Constructor* AllocConstructor(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - InterfaceEntry* AllocInterfaceEntry(Class* interface) + InterfaceEntry* AllocInterfaceEntry(Thread* self, Class* interface) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Class* CreatePrimitiveClass(Primitive::Type type) + Class* CreatePrimitiveClass(Thread* self, Primitive::Type type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return InitializePrimitiveClass(AllocClass(sizeof(Class)), type); + return InitializePrimitiveClass(AllocClass(self, sizeof(Class)), type); } Class* InitializePrimitiveClass(Class* primitive_class, Primitive::Type type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -444,8 +444,9 @@ class ClassLinker { void LoadField(const DexFile& dex_file, const ClassDataItemIterator& it, SirtRef<Class>& klass, SirtRef<Field>& dst) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* LoadMethod(const DexFile& dex_file, const ClassDataItemIterator& dex_method, - SirtRef<Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + AbstractMethod* LoadMethod(Thread* self, const DexFile& dex_file, + const ClassDataItemIterator& dex_method, + SirtRef<Class>& klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void FixupStaticTrampolines(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -538,9 +539,10 @@ class ClassLinker { EXCLUSIVE_LOCKS_REQUIRED(dex_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* CreateProxyConstructor(SirtRef<Class>& klass, Class* proxy_class) + AbstractMethod* CreateProxyConstructor(Thread* self, SirtRef<Class>& klass, Class* proxy_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - AbstractMethod* CreateProxyMethod(SirtRef<Class>& klass, SirtRef<AbstractMethod>& prototype) + AbstractMethod* CreateProxyMethod(Thread* self, SirtRef<Class>& klass, + SirtRef<AbstractMethod>& prototype) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); std::vector<const DexFile*> boot_class_path_; diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc index d0b9e1648e..02512eb867 100644 --- a/src/class_linker_test.cc +++ b/src/class_linker_test.cc @@ -773,7 +773,7 @@ TEST_F(ClassLinkerTest, LibCore) { TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) { ScopedObjectAccess soa(Thread::Current()); Class* array_class = class_linker_->FindSystemClass("[Ljava/lang/String;"); - ObjectArray<String>* array = ObjectArray<String>::Alloc(array_class, 0); + ObjectArray<String>* array = ObjectArray<String>::Alloc(soa.Self(), array_class, 0); uint32_t array_offset = reinterpret_cast<uint32_t>(array); uint32_t data_offset = array_offset + ObjectArray<String>::DataOffset(sizeof(String*)).Uint32Value(); @@ -786,27 +786,27 @@ TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) { TEST_F(ClassLinkerTest, ValidatePrimitiveArrayElementsOffset) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<LongArray> long_array(soa.Self(), LongArray::Alloc(0)); + SirtRef<LongArray> long_array(soa.Self(), LongArray::Alloc(soa.Self(), 0)); EXPECT_EQ(class_linker_->FindSystemClass("[J"), long_array->GetClass()); uintptr_t data_offset = reinterpret_cast<uintptr_t>(long_array->GetData()); EXPECT_TRUE(IsAligned<8>(data_offset)); // Longs require 8 byte alignment - SirtRef<DoubleArray> double_array(soa.Self(), DoubleArray::Alloc(0)); + SirtRef<DoubleArray> double_array(soa.Self(), DoubleArray::Alloc(soa.Self(), 0)); EXPECT_EQ(class_linker_->FindSystemClass("[D"), double_array->GetClass()); data_offset = reinterpret_cast<uintptr_t>(double_array->GetData()); EXPECT_TRUE(IsAligned<8>(data_offset)); // Doubles require 8 byte alignment - SirtRef<IntArray> int_array(soa.Self(), IntArray::Alloc(0)); + SirtRef<IntArray> int_array(soa.Self(), IntArray::Alloc(soa.Self(), 0)); EXPECT_EQ(class_linker_->FindSystemClass("[I"), int_array->GetClass()); data_offset = reinterpret_cast<uintptr_t>(int_array->GetData()); EXPECT_TRUE(IsAligned<4>(data_offset)); // Ints require 4 byte alignment - SirtRef<CharArray> char_array(soa.Self(), CharArray::Alloc(0)); + SirtRef<CharArray> char_array(soa.Self(), CharArray::Alloc(soa.Self(), 0)); EXPECT_EQ(class_linker_->FindSystemClass("[C"), char_array->GetClass()); data_offset = reinterpret_cast<uintptr_t>(char_array->GetData()); EXPECT_TRUE(IsAligned<2>(data_offset)); // Chars require 2 byte alignment - SirtRef<ShortArray> short_array(soa.Self(), ShortArray::Alloc(0)); + SirtRef<ShortArray> short_array(soa.Self(), ShortArray::Alloc(soa.Self(), 0)); EXPECT_EQ(class_linker_->FindSystemClass("[S"), short_array->GetClass()); data_offset = reinterpret_cast<uintptr_t>(short_array->GetData()); EXPECT_TRUE(IsAligned<2>(data_offset)); // Shorts require 2 byte alignment @@ -923,7 +923,7 @@ TEST_F(ClassLinkerTest, StaticFields) { fh.ChangeField(s8); EXPECT_TRUE(fh.GetTypeAsPrimitiveType() == Primitive::kPrimNot); EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("android")); - s8->SetObject(NULL, String::AllocFromModifiedUtf8("robot")); + s8->SetObject(NULL, 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 diff --git a/src/compiler.cc b/src/compiler.cc index 10b4939bb0..3899ce9ed6 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -34,6 +34,7 @@ #include "scoped_thread_state_change.h" #include "ScopedLocalRef.h" #include "stl_util.h" +#include "thread.h" #include "timing_logger.h" #include "verifier/method_verifier.h" @@ -110,9 +111,9 @@ class AOTCompilationStats { } } -// Allow lossy statistics in non-debug builds +// Allow lossy statistics in non-debug builds. #ifndef NDEBUG -#define STATS_LOCK() MutexLock mu(stats_lock_) +#define STATS_LOCK() MutexLock mu(Thread::Current(), stats_lock_) #else #define STATS_LOCK() #endif @@ -359,30 +360,31 @@ Compiler::Compiler(InstructionSet instruction_set, bool image, size_t thread_cou } Compiler::~Compiler() { + Thread* self = Thread::Current(); { - MutexLock mu(compiled_classes_lock_); + MutexLock mu(self, compiled_classes_lock_); STLDeleteValues(&compiled_classes_); } { - MutexLock mu(compiled_methods_lock_); + MutexLock mu(self, compiled_methods_lock_); STLDeleteValues(&compiled_methods_); } { - MutexLock mu(compiled_invoke_stubs_lock_); + MutexLock mu(self, compiled_invoke_stubs_lock_); STLDeleteValues(&compiled_invoke_stubs_); } #if defined(ART_USE_LLVM_COMPILER) { - MutexLock mu(compiled_proxy_stubs_lock_); + MutexLock mu(self, compiled_proxy_stubs_lock_); STLDeleteValues(&compiled_proxy_stubs_); } #endif { - MutexLock mu(compiled_methods_lock_); + MutexLock mu(self, compiled_methods_lock_); STLDeleteElements(&code_to_patch_); } { - MutexLock mu(compiled_methods_lock_); + MutexLock mu(self, compiled_methods_lock_); STLDeleteElements(&methods_to_patch_); } #if defined(ART_USE_LLVM_COMPILER) @@ -554,7 +556,7 @@ bool Compiler::IsImageClass(const std::string& descriptor) const { } void Compiler::RecordClassStatus(ClassReference ref, CompiledClass* compiled_class) { - MutexLock mu(Compiler::compiled_classes_lock_); + MutexLock mu(Thread::Current(), Compiler::compiled_classes_lock_); compiled_classes_.Put(ref, compiled_class); } @@ -929,7 +931,7 @@ void Compiler::AddCodePatch(const DexFile* dex_file, uint32_t target_method_idx, InvokeType target_invoke_type, size_t literal_offset) { - MutexLock mu(compiled_methods_lock_); + MutexLock mu(Thread::Current(), compiled_methods_lock_); code_to_patch_.push_back(new PatchInformation(dex_file, referrer_method_idx, referrer_invoke_type, @@ -943,7 +945,7 @@ void Compiler::AddMethodPatch(const DexFile* dex_file, uint32_t target_method_idx, InvokeType target_invoke_type, size_t literal_offset) { - MutexLock mu(compiled_methods_lock_); + MutexLock mu(Thread::Current(), compiled_methods_lock_); methods_to_patch_.push_back(new PatchInformation(dex_file, referrer_method_idx, referrer_invoke_type, @@ -1068,10 +1070,7 @@ static void ForAll(CompilationContext* context, size_t begin, size_t end, Callba // Ensure we're suspended while we're blocked waiting for the other threads to finish (worker // thread destructor's called below perform join). - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - CHECK_NE(self->GetState(), kRunnable); - } + CHECK_NE(self->GetState(), kRunnable); STLDeleteElements(&threads); } @@ -1427,11 +1426,12 @@ void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access << " took " << PrettyDuration(duration_ns); } + Thread* self = Thread::Current(); if (compiled_method != NULL) { MethodReference ref(&dex_file, method_idx); CHECK(GetCompiledMethod(ref) == NULL) << PrettyMethod(method_idx, dex_file); { - MutexLock mu(compiled_methods_lock_); + MutexLock mu(self, compiled_methods_lock_); compiled_methods_.Put(ref, compiled_method); } DCHECK(GetCompiledMethod(ref) != NULL) << PrettyMethod(method_idx, dex_file); @@ -1459,10 +1459,10 @@ void Compiler::CompileMethod(const DexFile::CodeItem* code_item, uint32_t access } #endif - if (Thread::Current()->IsExceptionPending()) { - ScopedObjectAccess soa(Thread::Current()); + if (self->IsExceptionPending()) { + ScopedObjectAccess soa(self); LOG(FATAL) << "Unexpected exception compiling: " << PrettyMethod(method_idx, dex_file) << "\n" - << Thread::Current()->GetException()->Dump(); + << self->GetException()->Dump(); } } @@ -1472,7 +1472,7 @@ const CompiledInvokeStub* Compiler::FindInvokeStub(bool is_static, const char* s } const CompiledInvokeStub* Compiler::FindInvokeStub(const std::string& key) const { - MutexLock mu(compiled_invoke_stubs_lock_); + MutexLock mu(Thread::Current(), compiled_invoke_stubs_lock_); InvokeStubTable::const_iterator it = compiled_invoke_stubs_.find(key); if (it == compiled_invoke_stubs_.end()) { return NULL; @@ -1484,7 +1484,7 @@ const CompiledInvokeStub* Compiler::FindInvokeStub(const std::string& key) const void Compiler::InsertInvokeStub(const std::string& key, const CompiledInvokeStub* compiled_invoke_stub) { - MutexLock mu(compiled_invoke_stubs_lock_); + MutexLock mu(Thread::Current(), compiled_invoke_stubs_lock_); InvokeStubTable::iterator it = compiled_invoke_stubs_.find(key); if (it != compiled_invoke_stubs_.end()) { // Someone else won the race. @@ -1496,7 +1496,7 @@ void Compiler::InsertInvokeStub(const std::string& key, #if defined(ART_USE_LLVM_COMPILER) const CompiledInvokeStub* Compiler::FindProxyStub(const char* shorty) const { - MutexLock mu(compiled_proxy_stubs_lock_); + MutexLock mu(Thread::Current(), compiled_proxy_stubs_lock_); ProxyStubTable::const_iterator it = compiled_proxy_stubs_.find(shorty); if (it == compiled_proxy_stubs_.end()) { return NULL; @@ -1508,7 +1508,7 @@ const CompiledInvokeStub* Compiler::FindProxyStub(const char* shorty) const { void Compiler::InsertProxyStub(const char* shorty, const CompiledInvokeStub* compiled_proxy_stub) { - MutexLock mu(compiled_proxy_stubs_lock_); + MutexLock mu(Thread::Current(), compiled_proxy_stubs_lock_); InvokeStubTable::iterator it = compiled_proxy_stubs_.find(shorty); if (it != compiled_proxy_stubs_.end()) { // Someone else won the race. @@ -1520,7 +1520,7 @@ void Compiler::InsertProxyStub(const char* shorty, #endif CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const { - MutexLock mu(compiled_classes_lock_); + MutexLock mu(Thread::Current(), compiled_classes_lock_); ClassTable::const_iterator it = compiled_classes_.find(ref); if (it == compiled_classes_.end()) { return NULL; @@ -1530,7 +1530,7 @@ CompiledClass* Compiler::GetCompiledClass(ClassReference ref) const { } CompiledMethod* Compiler::GetCompiledMethod(MethodReference ref) const { - MutexLock mu(compiled_methods_lock_); + MutexLock mu(Thread::Current(), compiled_methods_lock_); MethodTable::const_iterator it = compiled_methods_.find(ref); if (it == compiled_methods_.end()) { return NULL; diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc index f65f684697..85ae7948e5 100644 --- a/src/compiler_llvm/compiler_llvm.cc +++ b/src/compiler_llvm/compiler_llvm.cc @@ -126,7 +126,7 @@ CompilerLLVM::~CompilerLLVM() { CompilationUnit* CompilerLLVM::AllocateCompilationUnit() { - MutexLock GUARD(num_cunits_lock_); + MutexLock GUARD(Thread::Current(), num_cunits_lock_); CompilationUnit* cunit = new CompilationUnit(this, num_cunits_++); if (!bitcode_filename_.empty()) { cunit->SetBitcodeFileName(StringPrintf("%s-%zu", bitcode_filename_.c_str(), num_cunits_-1)); diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc index 3bb4ae526d..d7e146ac39 100644 --- a/src/compiler_llvm/runtime_support_llvm.cc +++ b/src/compiler_llvm/runtime_support_llvm.cc @@ -230,17 +230,17 @@ Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx, Object* art_alloc_array_from_code(uint32_t type_idx, AbstractMethod* referrer, uint32_t length, - Thread* /*thread*/) + Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return AllocArrayFromCode(type_idx, referrer, length, false); + return AllocArrayFromCode(type_idx, referrer, length, self, false); } Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx, AbstractMethod* referrer, uint32_t length, - Thread* /*thread*/) + Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return AllocArrayFromCode(type_idx, referrer, length, true); + return AllocArrayFromCode(type_idx, referrer, length, self, true); } Object* art_check_and_alloc_array_from_code(uint32_t type_idx, @@ -748,12 +748,12 @@ void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) va_start(ap, proxy_method); Object* receiver = va_arg(ap, Object*); - Thread* thread = va_arg(ap, Thread*); + Thread* self = va_arg(ap, Thread*); MethodHelper proxy_mh(proxy_method); const size_t num_params = proxy_mh.NumArgs(); // Start new JNI local reference state - JNIEnvExt* env = thread->GetJniEnv(); + JNIEnvExt* env = self->GetJniEnv(); ScopedObjectAccessUnchecked soa(env); ScopedJniEnvLocalRefState env_state(env); @@ -773,9 +773,9 @@ void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) args_jobj[2].l = NULL; ObjectArray<Object>* args = NULL; if ((num_params - 1) > 0) { - args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1); + args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(self, num_params - 1); if (args == NULL) { - CHECK(thread->IsExceptionPending()); + CHECK(self->IsExceptionPending()); return; } args_jobj[2].l = soa.AddLocalReference<jobjectArray>(args); @@ -783,9 +783,9 @@ void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) // Get parameter types. const char* shorty = proxy_mh.GetShorty(); - ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes(); + ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes(self); if (param_types == NULL) { - CHECK(thread->IsExceptionPending()); + CHECK(self->IsExceptionPending()); return; } @@ -822,7 +822,7 @@ void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) Class* param_type = param_types->Get(i); if (param_type->IsPrimitive()) { BoxPrimitive(param_type->GetPrimitiveType(), val); - if (thread->IsExceptionPending()) { + if (self->IsExceptionPending()) { return; } } @@ -836,19 +836,19 @@ void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) jobject result = env->CallObjectMethodA(inv_hand, WellKnownClasses::java_lang_reflect_InvocationHandler_invoke, args_jobj); // Place result in stack args - if (!thread->IsExceptionPending()) { + if (!self->IsExceptionPending()) { if (shorty[0] == 'V') { return; } - Object* result_ref = thread->DecodeJObject(result); + Object* result_ref = self->DecodeJObject(result); JValue* result_unboxed = va_arg(ap, JValue*); if (result_ref == NULL) { result_unboxed->SetL(NULL); } else { bool unboxed_okay = UnboxPrimitiveForResult(result_ref, proxy_mh.GetReturnType(), *result_unboxed); if (!unboxed_okay) { - thread->ClearException(); - thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;", + self->ClearException(); + self->ThrowNewExceptionF("Ljava/lang/ClassCastException;", "Couldn't convert result of type %s to %s", PrettyTypeOf(result_ref).c_str(), PrettyDescriptor(proxy_mh.GetReturnType()).c_str()); @@ -858,7 +858,7 @@ void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) } else { // In the case of checked exceptions that aren't declared, the exception must be wrapped by // a UndeclaredThrowableException. - Throwable* exception = thread->GetException(); + Throwable* exception = self->GetException(); if (exception->IsCheckedException()) { SynthesizedProxyClass* proxy_class = down_cast<SynthesizedProxyClass*>(proxy_method->GetDeclaringClass()); @@ -879,7 +879,7 @@ void art_proxy_invoke_handler_from_code(AbstractMethod* proxy_method, ...) declares_exception = declared_exception->IsAssignableFrom(exception_class); } if (!declares_exception) { - thread->ThrowNewWrappedException("Ljava/lang/reflect/UndeclaredThrowableException;", NULL); + self->ThrowNewWrappedException("Ljava/lang/reflect/UndeclaredThrowableException;", NULL); } } } diff --git a/src/debugger.cc b/src/debugger.cc index e28845ffa4..c8e7381c6b 100644 --- a/src/debugger.cc +++ b/src/debugger.cc @@ -55,19 +55,19 @@ class ObjectRegistry { return 0; } JDWP::ObjectId id = static_cast<JDWP::ObjectId>(reinterpret_cast<uintptr_t>(o)); - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); map_.Overwrite(id, o); return id; } void Clear() { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); LOG(DEBUG) << "Debugger has detached; object registry had " << map_.size() << " entries"; map_.clear(); } bool Contains(JDWP::ObjectId id) { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); return map_.find(id) != map_.end(); } @@ -76,14 +76,14 @@ class ObjectRegistry { return NULL; } - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); typedef SafeMap<JDWP::ObjectId, Object*>::iterator It; // C++0x auto It it = map_.find(id); return (it != map_.end()) ? reinterpret_cast<T>(it->second) : reinterpret_cast<T>(kInvalidId); } void VisitRoots(Heap::RootVisitor* visitor, void* arg) { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); typedef SafeMap<JDWP::ObjectId, Object*>::iterator It; // C++0x auto for (It it = map_.begin(); it != map_.end(); ++it) { visitor(it->second, arg); @@ -184,7 +184,7 @@ static SingleStepControl gSingleStepControl GUARDED_BY(gBreakpointsLock); static bool IsBreakpoint(AbstractMethod* m, uint32_t dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - MutexLock mu(gBreakpointsLock); + MutexLock mu(Thread::Current(), gBreakpointsLock); for (size_t i = 0; i < gBreakpoints.size(); ++i) { if (gBreakpoints[i].method == m && gBreakpoints[i].dex_pc == dex_pc) { VLOG(jdwp) << "Hit breakpoint #" << i << ": " << gBreakpoints[i]; @@ -492,7 +492,7 @@ static void SetDebuggerUpdatesEnabledCallback(Thread* t, void* user_data) { } static void SetDebuggerUpdatesEnabled(bool enabled) { - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); Runtime::Current()->GetThreadList()->ForEach(SetDebuggerUpdatesEnabledCallback, &enabled); } @@ -508,7 +508,7 @@ void Dbg::GoActive() { { // TODO: dalvik only warned if there were breakpoints left over. clear in Dbg::Disconnected? - MutexLock mu(gBreakpointsLock); + MutexLock mu(Thread::Current(), gBreakpointsLock); CHECK_EQ(gBreakpoints.size(), 0U); } @@ -884,7 +884,7 @@ JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId arrayId, int offset, int co } JDWP::ObjectId Dbg::CreateString(const std::string& str) { - return gRegistry->Add(String::AllocFromModifiedUtf8(str.c_str())); + return gRegistry->Add(String::AllocFromModifiedUtf8(Thread::Current(), str.c_str())); } JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId classId, JDWP::ObjectId& new_object) { @@ -893,7 +893,7 @@ JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId classId, JDWP::ObjectId& new_o if (c == NULL) { return status; } - new_object = gRegistry->Add(c->AllocObject()); + new_object = gRegistry->Add(c->AllocObject(Thread::Current())); return JDWP::ERR_NONE; } @@ -907,7 +907,7 @@ JDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId arrayClassId, uint32_t le if (c == NULL) { return status; } - new_array = gRegistry->Add(Array::Alloc(c, length)); + new_array = gRegistry->Add(Array::Alloc(Thread::Current(), c, length)); return JDWP::ERR_NONE; } @@ -1331,8 +1331,9 @@ std::string Dbg::StringToUtf8(JDWP::ObjectId strId) { } bool Dbg::GetThreadName(JDWP::ObjectId threadId, std::string& name) { - MutexLock mu(*Locks::thread_list_lock_); - ScopedObjectAccessUnchecked soa(Thread::Current()); + Thread* self = Thread::Current(); + MutexLock mu(self, *Locks::thread_list_lock_); + ScopedObjectAccessUnchecked soa(self); Thread* thread = DecodeThread(soa, threadId); if (thread == NULL) { return false; @@ -1349,7 +1350,7 @@ JDWP::JdwpError Dbg::GetThreadGroup(JDWP::ObjectId threadId, JDWP::ExpandBuf* pR } // Okay, so it's an object, but is it actually a thread? - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); if (DecodeThread(soa, threadId) == NULL) { return JDWP::ERR_INVALID_THREAD; } @@ -1408,13 +1409,13 @@ JDWP::ObjectId Dbg::GetMainThreadGroupId() { bool Dbg::GetThreadStatus(JDWP::ObjectId threadId, JDWP::JdwpThreadStatus* pThreadStatus, JDWP::JdwpSuspendStatus* pSuspendStatus) { ScopedObjectAccess soa(Thread::Current()); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = DecodeThread(soa, threadId); if (thread == NULL) { return false; } - MutexLock mu2(*Locks::thread_suspend_count_lock_); + MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); // TODO: if we're in Thread.sleep(long), we should return TS_SLEEPING, // even if it's implemented using Object.wait(long). @@ -1448,28 +1449,28 @@ bool Dbg::GetThreadStatus(JDWP::ObjectId threadId, JDWP::JdwpThreadStatus* pThre JDWP::JdwpError Dbg::GetThreadDebugSuspendCount(JDWP::ObjectId threadId, JDWP::ExpandBuf* pReply) { ScopedObjectAccess soa(Thread::Current()); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = DecodeThread(soa, threadId); if (thread == NULL) { return JDWP::ERR_INVALID_THREAD; } - MutexLock mu2(*Locks::thread_suspend_count_lock_); + MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); expandBufAdd4BE(pReply, thread->GetDebugSuspendCount()); return JDWP::ERR_NONE; } bool Dbg::ThreadExists(JDWP::ObjectId threadId) { ScopedObjectAccess soa(Thread::Current()); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); return DecodeThread(soa, threadId) != NULL; } bool Dbg::IsSuspended(JDWP::ObjectId threadId) { ScopedObjectAccess soa(Thread::Current()); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = DecodeThread(soa, threadId); CHECK(thread != NULL); - MutexLock mu2(*Locks::thread_suspend_count_lock_); + MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); return thread->IsSuspended(); } @@ -1513,7 +1514,7 @@ void Dbg::GetThreads(JDWP::ObjectId thread_group_id, std::vector<JDWP::ObjectId> ScopedObjectAccessUnchecked soa(Thread::Current()); Object* thread_group = gRegistry->Get<Object*>(thread_group_id); ThreadListVisitor tlv(soa, thread_group, thread_ids); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Runtime::Current()->GetThreadList()->ForEach(ThreadListVisitor::Visit, &tlv); } @@ -1554,7 +1555,7 @@ static int GetStackDepth(Thread* thread) }; if (kIsDebugBuild) { - MutexLock mu(*Locks::thread_suspend_count_lock_); + MutexLock mu(Thread::Current(), *Locks::thread_suspend_count_lock_); CHECK(thread->IsSuspended()); } CountStackDepthVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack()); @@ -1652,7 +1653,7 @@ JDWP::JdwpError Dbg::SuspendThread(JDWP::ObjectId threadId, bool request_suspens void Dbg::ResumeThread(JDWP::ObjectId threadId) { ScopedObjectAccessUnchecked soa(Thread::Current()); Object* peer = gRegistry->Get<Object*>(threadId); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = Thread::FromManagedThread(soa, peer); if (thread == NULL) { LOG(WARNING) << "No such thread for resume: " << peer; @@ -1660,7 +1661,7 @@ void Dbg::ResumeThread(JDWP::ObjectId threadId) { } bool needs_resume; { - MutexLock mu2(*Locks::thread_suspend_count_lock_); + MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); needs_resume = thread->GetSuspendCount() > 0; } if (needs_resume) { @@ -1716,12 +1717,12 @@ JDWP::JdwpError Dbg::GetThisObject(JDWP::ObjectId thread_id, JDWP::FrameId frame ScopedObjectAccessUnchecked soa(Thread::Current()); Thread* thread; { - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); thread = DecodeThread(soa, thread_id); if (thread == NULL) { return JDWP::ERR_INVALID_THREAD; } - MutexLock mu2(*Locks::thread_suspend_count_lock_); + MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); if (!thread->IsSuspended()) { return JDWP::ERR_THREAD_NOT_SUSPENDED; } @@ -2020,7 +2021,7 @@ void Dbg::UpdateDebugger(int32_t dex_pc, Thread* self) { // If the debugger is single-stepping one of our threads, check to // see if we're that thread and we've reached a step point. - MutexLock mu(gBreakpointsLock); + MutexLock mu(Thread::Current(), gBreakpointsLock); if (gSingleStepControl.is_active && gSingleStepControl.thread == self) { CHECK(!m->IsNative()); if (gSingleStepControl.step_depth == JDWP::SD_INTO) { @@ -2104,14 +2105,14 @@ void Dbg::UpdateDebugger(int32_t dex_pc, Thread* self) { } void Dbg::WatchLocation(const JDWP::JdwpLocation* location) { - MutexLock mu(gBreakpointsLock); + MutexLock mu(Thread::Current(), gBreakpointsLock); AbstractMethod* m = FromMethodId(location->method_id); gBreakpoints.push_back(Breakpoint(m, location->dex_pc)); VLOG(jdwp) << "Set breakpoint #" << (gBreakpoints.size() - 1) << ": " << gBreakpoints[gBreakpoints.size() - 1]; } void Dbg::UnwatchLocation(const JDWP::JdwpLocation* location) { - MutexLock mu(gBreakpointsLock); + MutexLock mu(Thread::Current(), gBreakpointsLock); AbstractMethod* m = FromMethodId(location->method_id); for (size_t i = 0; i < gBreakpoints.size(); ++i) { if (gBreakpoints[i].method == m && gBreakpoints[i].dex_pc == location->dex_pc) { @@ -2130,7 +2131,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize s return JDWP::ERR_INVALID_THREAD; } - MutexLock mu(gBreakpointsLock); + MutexLock mu(soa.Self(), gBreakpointsLock); // TODO: there's no theoretical reason why we couldn't support single-stepping // of multiple threads at once, but we never did so historically. if (gSingleStepControl.thread != NULL && thread != gSingleStepControl.thread) { @@ -2149,7 +2150,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize s EXCLUSIVE_LOCKS_REQUIRED(gBreakpointsLock) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) : StackVisitor(stack, trace_stack, NULL) { - gBreakpointsLock.AssertHeld(); + gBreakpointsLock.AssertHeld(Thread::Current()); gSingleStepControl.method = NULL; gSingleStepControl.stack_depth = 0; } @@ -2157,7 +2158,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize s // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses // annotalysis. bool VisitFrame() NO_THREAD_SAFETY_ANALYSIS { - gBreakpointsLock.AssertHeld(); + gBreakpointsLock.AssertHeld(Thread::Current()); const AbstractMethod* m = GetMethod(); if (!m->IsRuntimeMethod()) { ++gSingleStepControl.stack_depth; @@ -2188,7 +2189,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize s } static bool Callback(void* raw_context, uint32_t address, uint32_t line_number) { - MutexLock mu(gBreakpointsLock); // Keep GCC happy. + MutexLock mu(Thread::Current(), gBreakpointsLock); // Keep GCC happy. DebugCallbackContext* context = reinterpret_cast<DebugCallbackContext*>(raw_context); if (static_cast<int32_t>(line_number) == gSingleStepControl.line_number) { if (!context->last_pc_valid) { @@ -2209,7 +2210,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize s } ~DebugCallbackContext() { - MutexLock mu(gBreakpointsLock); // Keep GCC happy. + MutexLock mu(Thread::Current(), gBreakpointsLock); // Keep GCC happy. // If the line number was the last in the position table... if (last_pc_valid) { size_t end = MethodHelper(gSingleStepControl.method).GetCodeItem()->insns_size_in_code_units_; @@ -2259,7 +2260,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId threadId, JDWP::JdwpStepSize s } void Dbg::UnconfigureStep(JDWP::ObjectId /*threadId*/) { - MutexLock mu(gBreakpointsLock); + MutexLock mu(Thread::Current(), gBreakpointsLock); gSingleStepControl.is_active = false; gSingleStepControl.thread = NULL; @@ -2307,7 +2308,7 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId threadId, JDWP::ObjectId object Thread* self = Thread::Current(); { ScopedObjectAccessUnchecked soa(self); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); targetThread = DecodeThread(soa, threadId); if (targetThread == NULL) { LOG(ERROR) << "InvokeMethod request for non-existent thread " << threadId; @@ -2335,7 +2336,7 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId threadId, JDWP::ObjectId object */ int suspend_count; { - MutexLock mu2(*Locks::thread_suspend_count_lock_); + MutexLock mu2(soa.Self(), *Locks::thread_suspend_count_lock_); suspend_count = targetThread->GetSuspendCount(); } if (suspend_count > 1) { @@ -2411,7 +2412,7 @@ JDWP::JdwpError Dbg::InvokeMethod(JDWP::ObjectId threadId, JDWP::ObjectId object VLOG(jdwp) << " Transferring control to event thread"; { - MutexLock mu(req->lock_); + MutexLock mu(self, req->lock_); if ((options & JDWP::INVOKE_SINGLE_THREADED) == 0) { VLOG(jdwp) << " Resuming all threads"; @@ -2631,12 +2632,9 @@ void Dbg::DdmBroadcast(bool connect) { VLOG(jdwp) << "Broadcasting DDM " << (connect ? "connect" : "disconnect") << "..."; Thread* self = Thread::Current(); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - if (self->GetState() != kRunnable) { - LOG(ERROR) << "DDM broadcast in thread state " << self->GetState(); - /* try anyway? */ - } + if (self->GetState() != kRunnable) { + LOG(ERROR) << "DDM broadcast in thread state " << self->GetState(); + /* try anyway? */ } JNIEnv* env = self->GetJniEnv(); @@ -2699,12 +2697,13 @@ void Dbg::DdmSetThreadNotification(bool enable) { // notification. SuspendVM(); std::list<Thread*> threads; + Thread* self = Thread::Current(); { - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(self, *Locks::thread_list_lock_); threads = Runtime::Current()->GetThreadList()->GetList(); } { - ScopedObjectAccess soa(Thread::Current()); + ScopedObjectAccess soa(self); typedef std::list<Thread*>::const_iterator It; // TODO: C++0x auto for (It it = threads.begin(), end = threads.end(); it != end; ++it) { Dbg::DdmSendThreadNotification(*it, CHUNK_TYPE("THCR")); @@ -3096,9 +3095,10 @@ void Dbg::DdmSendHeapSegments(bool native) { } else { Heap* heap = Runtime::Current()->GetHeap(); const Spaces& spaces = heap->GetSpaces(); + Thread* self = Thread::Current(); for (Spaces::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) { if ((*cur)->IsAllocSpace()) { - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); (*cur)->AsAllocSpace()->Walk(HeapChunkContext::HeapChunkCallback, &context); } } @@ -3111,7 +3111,7 @@ void Dbg::DdmSendHeapSegments(bool native) { } void Dbg::SetAllocTrackingEnabled(bool enabled) { - MutexLock mu(gAllocTrackerLock); + MutexLock mu(Thread::Current(), gAllocTrackerLock); if (enabled) { if (recent_allocation_records_ == NULL) { LOG(INFO) << "Enabling alloc tracker (" << kNumAllocRecords << " entries, " @@ -3164,7 +3164,7 @@ void Dbg::RecordAllocation(Class* type, size_t byte_count) { Thread* self = Thread::Current(); CHECK(self != NULL); - MutexLock mu(gAllocTrackerLock); + MutexLock mu(self, gAllocTrackerLock); if (recent_allocation_records_ == NULL) { return; } @@ -3203,7 +3203,7 @@ static inline int HeadIndex() EXCLUSIVE_LOCKS_REQUIRED(gAllocTrackerLock) { void Dbg::DumpRecentAllocations() { ScopedObjectAccess soa(Thread::Current()); - MutexLock mu(gAllocTrackerLock); + MutexLock mu(soa.Self(), gAllocTrackerLock); if (recent_allocation_records_ == NULL) { LOG(INFO) << "Not recording tracked allocations"; return; @@ -3323,7 +3323,8 @@ jbyteArray Dbg::GetRecentAllocations() { DumpRecentAllocations(); } - MutexLock mu(gAllocTrackerLock); + Thread* self = Thread::Current(); + MutexLock mu(self, gAllocTrackerLock); // // Part 1: generate string tables. @@ -3428,7 +3429,7 @@ jbyteArray Dbg::GetRecentAllocations() { method_names.WriteTo(bytes); filenames.WriteTo(bytes); - JNIEnv* env = Thread::Current()->GetJniEnv(); + JNIEnv* env = self->GetJniEnv(); jbyteArray result = env->NewByteArray(bytes.size()); if (result != NULL) { env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0])); diff --git a/src/dex_cache_test.cc b/src/dex_cache_test.cc index 6c0107ca8b..b131e4c248 100644 --- a/src/dex_cache_test.cc +++ b/src/dex_cache_test.cc @@ -29,7 +29,8 @@ class DexCacheTest : public CommonTest {}; TEST_F(DexCacheTest, Open) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<DexCache> dex_cache(soa.Self(), class_linker_->AllocDexCache(*java_lang_dex_file_)); + SirtRef<DexCache> dex_cache(soa.Self(), class_linker_->AllocDexCache(soa.Self(), + *java_lang_dex_file_)); ASSERT_TRUE(dex_cache.get() != NULL); EXPECT_EQ(java_lang_dex_file_->NumStringIds(), dex_cache->NumStrings()); diff --git a/src/heap.cc b/src/heap.cc index fa044c2cbb..f7cb68d05d 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -277,7 +277,7 @@ struct SpaceSorter { }; void Heap::AddSpace(ContinuousSpace* space) { - WriterMutexLock mu(*Locks::heap_bitmap_lock_); + WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); DCHECK(space != NULL); DCHECK(space->GetLiveBitmap() != NULL); live_bitmap_->AddSpaceBitmap(space->GetLiveBitmap()); @@ -357,7 +357,7 @@ static void MSpaceChunkCallback(void* start, void* end, size_t used_bytes, void* } } -Object* Heap::AllocObject(Class* c, size_t byte_count) { +Object* Heap::AllocObject(Thread* self, Class* c, size_t byte_count) { DCHECK(c == NULL || (c->IsClassClass() && byte_count >= sizeof(Class)) || (c->IsVariableSize() || c->GetObjectSize() == byte_count) || strlen(ClassHelper(c).GetDescriptor()) == 0); @@ -372,7 +372,7 @@ Object* Heap::AllocObject(Class* c, size_t byte_count) { // range. This also means that we rely on SetClass not dirtying the object's card. if (byte_count >= large_object_threshold_ && have_zygote_space_ && c->IsPrimitiveArray()) { size = RoundUp(byte_count, kPageSize); - obj = Allocate(NULL, size); + obj = Allocate(self, NULL, size); if (obj != NULL) { // Make sure that our large object didn't get placed anywhere within the space interval or else @@ -381,7 +381,7 @@ Object* Heap::AllocObject(Class* c, size_t byte_count) { reinterpret_cast<byte*>(obj) >= spaces_.back()->End()); } } else { - obj = Allocate(alloc_space_, byte_count); + obj = Allocate(self, alloc_space_, byte_count); size = alloc_space_->AllocationSize(obj); if (obj != NULL) { @@ -405,7 +405,6 @@ Object* Heap::AllocObject(Class* c, size_t byte_count) { // concurrent_start_bytes_. concurrent_start_bytes_ = std::numeric_limits<size_t>::max(); // The SirtRef is necessary since the calls in RequestConcurrentGC are a safepoint. - Thread* self = Thread::Current(); SirtRef<Object> ref(self, obj); RequestConcurrentGC(self); } @@ -424,7 +423,7 @@ Object* Heap::AllocObject(Class* c, size_t byte_count) { std::string msg(StringPrintf("Failed to allocate a %zd-byte %s (%lld total bytes free; largest possible contiguous allocation %zd bytes)", byte_count, PrettyDescriptor(c).c_str(), total_bytes_free, max_contiguous_allocation)); - Thread::Current()->ThrowOutOfMemoryError(msg.c_str()); + self->ThrowOutOfMemoryError(msg.c_str()); return NULL; } @@ -483,7 +482,7 @@ void Heap::VerifyObjectBody(const Object* obj) { if (!std::binary_search(live_stack_->Begin(), live_stack_->End(), obj) && std::find(allocation_stack_->Begin(), allocation_stack_->End(), obj) == allocation_stack_->End()) { - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); if (large_object_space_->GetLiveObjects()->Test(obj)) { DumpSpaces(); LOG(FATAL) << "Object is dead: " << obj; @@ -520,7 +519,7 @@ void Heap::VerificationCallback(Object* obj, void* arg) { } void Heap::VerifyHeap() { - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); GetLiveBitmap()->Walk(Heap::VerificationCallback, this); } @@ -561,44 +560,38 @@ void Heap::RecordFree(size_t freed_objects, size_t freed_bytes) { } } -Object* Heap::TryToAllocate(AllocSpace* space, size_t alloc_size, bool grow) { +Object* Heap::TryToAllocate(Thread* self, AllocSpace* space, size_t alloc_size, bool grow) { // Should we try to use a CAS here and fix up num_bytes_allocated_ later with AllocationSize? if (num_bytes_allocated_ + alloc_size > growth_limit_) { return NULL; } if (UNLIKELY(space == NULL)) { - return large_object_space_->Alloc(alloc_size); + return large_object_space_->Alloc(self, alloc_size); } else if (grow) { - return space->AllocWithGrowth(alloc_size); + return space->AllocWithGrowth(self, alloc_size); } else { - return space->AllocWithoutGrowth(alloc_size); + return space->AllocWithoutGrowth(self, alloc_size); } } -Object* Heap::Allocate(AllocSpace* space, size_t alloc_size) { +Object* Heap::Allocate(Thread* self, AllocSpace* space, size_t alloc_size) { // Since allocation can cause a GC which will need to SuspendAll, make sure all allocations are // done in the runnable state where suspension is expected. -#ifndef NDEBUG - Thread* self = Thread::Current(); DCHECK_EQ(self->GetState(), kRunnable); self->AssertThreadSuspensionIsAllowable(); -#endif - Object* ptr = TryToAllocate(space, alloc_size, false); + Object* ptr = TryToAllocate(self, space, alloc_size, false); if (ptr != NULL) { return ptr; } // The allocation failed. If the GC is running, block until it completes, and then retry the // allocation. -#ifdef NDEBUG - Thread* self = Thread::Current(); -#endif GcType last_gc = WaitForConcurrentGcToComplete(self); if (last_gc != kGcTypeNone) { // A GC was in progress and we blocked, retry allocation now that memory has been freed. - ptr = TryToAllocate(space, alloc_size, false); + ptr = TryToAllocate(self, space, alloc_size, false); if (ptr != NULL) { return ptr; } @@ -635,7 +628,7 @@ Object* Heap::Allocate(AllocSpace* space, size_t alloc_size) { self->TransitionFromSuspendedToRunnable(); // Did we free sufficient memory for the allocation to succeed? - ptr = TryToAllocate(space, alloc_size, false); + ptr = TryToAllocate(self, space, alloc_size, false); if (ptr != NULL) { return ptr; } @@ -644,7 +637,7 @@ Object* Heap::Allocate(AllocSpace* space, size_t alloc_size) { // Allocations have failed after GCs; this is an exceptional state. // Try harder, growing the heap if necessary. - ptr = TryToAllocate(space, alloc_size, true); + ptr = TryToAllocate(self, space, alloc_size, true); if (ptr != NULL) { if (space != NULL) { size_t new_footprint = space->GetFootprintLimit(); @@ -669,7 +662,7 @@ Object* Heap::Allocate(AllocSpace* space, size_t alloc_size) { self->TransitionFromRunnableToSuspended(kWaitingPerformingGc); CollectGarbageInternal(kGcTypeFull, kGcCauseForAlloc, true); self->TransitionFromSuspendedToRunnable(); - return TryToAllocate(space, alloc_size, true); + return TryToAllocate(self, space, alloc_size, true); } int64_t Heap::GetMaxMemory() { @@ -721,7 +714,7 @@ class InstanceCounter { }; int64_t Heap::CountInstances(Class* c, bool count_assignable) { - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); InstanceCounter counter(c, count_assignable); GetLiveBitmap()->Walk(InstanceCounter::Callback, &counter); return counter.GetCount(); @@ -1620,12 +1613,12 @@ void Heap::CollectGarbageConcurrentMarkSweepPlan(Thread* self, GcType gc_type, G { // TODO: this lock shouldn't be necessary (it's why we did the bitmap flip above). if (gc_type != kGcTypeSticky) { - WriterMutexLock mu(*Locks::heap_bitmap_lock_); + WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); mark_sweep.SweepLargeObjects(swap); timings.AddSplit("SweepLargeObjects"); mark_sweep.Sweep(gc_type == kGcTypePartial, swap); } else { - WriterMutexLock mu(*Locks::heap_bitmap_lock_); + WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); mark_sweep.SweepArray(timings, live_stack_.get(), swap); timings.AddSplit("SweepArray"); } diff --git a/src/heap.h b/src/heap.h index 5fe491f5f9..7a96fd61d6 100644 --- a/src/heap.h +++ b/src/heap.h @@ -77,7 +77,7 @@ enum GcCause { }; std::ostream& operator<<(std::ostream& os, const GcCause& policy); -class LOCKABLE Heap { +class Heap { public: static const size_t kInitialSize = 2 * MB; @@ -95,7 +95,7 @@ class LOCKABLE Heap { ~Heap(); // Allocates and initializes storage for an object instance. - Object* AllocObject(Class* klass, size_t num_bytes) + Object* AllocObject(Thread* self, Class* klass, size_t num_bytes) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Check sanity of given reference. Requires the heap lock. @@ -296,12 +296,12 @@ class LOCKABLE Heap { private: // Allocates uninitialized storage. Passing in a null space tries to place the object in the // large object space. - Object* Allocate(AllocSpace* space, size_t num_bytes) + Object* Allocate(Thread* self, AllocSpace* space, size_t num_bytes) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Try to allocate a number of bytes, this function never does any GCs. - Object* TryToAllocate(AllocSpace* space, size_t alloc_size, bool grow) + Object* TryToAllocate(Thread* self, AllocSpace* space, size_t alloc_size, bool grow) LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/src/heap_test.cc b/src/heap_test.cc index 881a765131..6db7416d06 100644 --- a/src/heap_test.cc +++ b/src/heap_test.cc @@ -39,9 +39,10 @@ TEST_F(HeapTest, GarbageCollectClassLinkerInit) { Class* c = class_linker_->FindSystemClass("[Ljava/lang/Object;"); for (size_t i = 0; i < 1024; ++i) { - SirtRef<ObjectArray<Object> > array(soa.Self(), ObjectArray<Object>::Alloc(c, 2048)); + SirtRef<ObjectArray<Object> > array(soa.Self(), + ObjectArray<Object>::Alloc(soa.Self(), c, 2048)); for (size_t j = 0; j < 2048; ++j) { - array->Set(j, String::AllocFromModifiedUtf8("hello, world!")); + array->Set(j, String::AllocFromModifiedUtf8(soa.Self(), "hello, world!")); } } } diff --git a/src/hprof/hprof.cc b/src/hprof/hprof.cc index 0cad70968b..125b19a2b8 100644 --- a/src/hprof/hprof.cc +++ b/src/hprof/hprof.cc @@ -407,12 +407,13 @@ class Hprof { // Walk the roots and the heap. current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_SEGMENT, HPROF_TIME); Runtime::Current()->VisitRoots(RootVisitor, this); + Thread* self = Thread::Current(); { - WriterMutexLock mu(*Locks::heap_bitmap_lock_); + WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); Runtime::Current()->GetHeap()->FlushAllocStack(); } { - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); Runtime::Current()->GetHeap()->GetLiveBitmap()->Walk(HeapBitmapCallback, this); } current_record_.StartNewRecord(body_fp_, HPROF_TAG_HEAP_DUMP_END, HPROF_TIME); @@ -444,22 +445,27 @@ class Hprof { if (fd_ >= 0) { out_fd = dup(fd_); if (out_fd < 0) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "Couldn't dump heap; dup(%d) failed: %s", fd_, strerror(errno)); + self->ThrowNewExceptionF("Ljava/lang/RuntimeException;", + "Couldn't dump heap; dup(%d) failed: %s", fd_, strerror(errno)); return; } } else { out_fd = open(filename_.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644); if (out_fd < 0) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "Couldn't dump heap; open(\"%s\") failed: %s", filename_.c_str(), strerror(errno)); + self->ThrowNewExceptionF("Ljava/lang/RuntimeException;", + "Couldn't dump heap; open(\"%s\") failed: %s", filename_.c_str(), + strerror(errno)); return; } } UniquePtr<File> file(OS::FileFromFd(filename_.c_str(), out_fd)); - okay = file->WriteFully(header_data_ptr_, header_data_size_) && file->WriteFully(body_data_ptr_, body_data_size_); + okay = file->WriteFully(header_data_ptr_, header_data_size_) && + file->WriteFully(body_data_ptr_, body_data_size_); if (!okay) { - std::string msg(StringPrintf("Couldn't dump heap; writing \"%s\" failed: %s", filename_.c_str(), strerror(errno))); - Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;", msg.c_str()); + std::string msg(StringPrintf("Couldn't dump heap; writing \"%s\" failed: %s", + filename_.c_str(), strerror(errno))); + self->ThrowNewException("Ljava/lang/RuntimeException;", msg.c_str()); LOG(ERROR) << msg; } close(out_fd); @@ -468,7 +474,9 @@ class Hprof { // Throw out a log message for the benefit of "runhat". if (okay) { uint64_t duration = NanoTime() - start_ns_; - LOG(INFO) << "hprof: heap dump completed (" << PrettySize(header_data_size_ + body_data_size_ + 1023) << ") in " << PrettyDuration(duration); + LOG(INFO) << "hprof: heap dump completed (" + << PrettySize(header_data_size_ + body_data_size_ + 1023) + << ") in " << PrettyDuration(duration); } } diff --git a/src/image_writer.cc b/src/image_writer.cc index c876329a62..fe12baf2da 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -192,7 +192,7 @@ void ImageWriter::ComputeEagerResolvedStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // TODO: Check image spaces only? Heap* heap = Runtime::Current()->GetHeap(); - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); heap->FlushAllocStack(); heap->GetLiveBitmap()->Walk(ComputeEagerResolvedStringsCallback, this); } @@ -276,12 +276,13 @@ void ImageWriter::CheckNonImageClassesRemoved() } Heap* heap = Runtime::Current()->GetHeap(); + Thread* self = Thread::Current(); { - WriterMutexLock mu(*Locks::heap_bitmap_lock_); + WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); heap->FlushAllocStack(); } - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); heap->GetLiveBitmap()->Walk(CheckNonImageClassesRemovedCallback, this); } @@ -340,9 +341,10 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { Runtime* runtime = Runtime::Current(); ClassLinker* class_linker = runtime->GetClassLinker(); Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;"); + Thread* self = Thread::Current(); // build an Object[] of all the DexCaches used in the source_space_ - ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(object_array_class, + ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(self, object_array_class, dex_caches_.size()); int i = 0; typedef Set::const_iterator It; // TODO: C++0x auto @@ -352,8 +354,9 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { // build an Object[] of the roots needed to restore the runtime SirtRef<ObjectArray<Object> > - image_roots(Thread::Current(), - ObjectArray<Object>::Alloc(object_array_class, ImageHeader::kImageRootsMax)); + image_roots(self, + ObjectArray<Object>::Alloc(self, object_array_class, + ImageHeader::kImageRootsMax)); image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniDlsymLookupStub()); image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray, runtime->GetAbstractMethodErrorStubArray()); @@ -369,7 +372,7 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { image_roots->Set(ImageHeader::kRefsAndArgsSaveMethod, runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)); image_roots->Set(ImageHeader::kOatLocation, - String::AllocFromModifiedUtf8(oat_file_->GetLocation().c_str())); + String::AllocFromModifiedUtf8(self, oat_file_->GetLocation().c_str())); image_roots->Set(ImageHeader::kDexCaches, dex_caches); image_roots->Set(ImageHeader::kClassRoots, @@ -425,15 +428,16 @@ void ImageWriter::CalculateNewObjectOffsets() { void ImageWriter::CopyAndFixupObjects() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const char* old_cause = Thread::Current()->StartAssertNoThreadSuspension("ImageWriter"); + Thread* self = Thread::Current(); + const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); Heap* heap = Runtime::Current()->GetHeap(); // TODO: heap validation can't handle this fix up pass heap->DisableObjectValidation(); // TODO: Image spaces only? - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); heap->FlushAllocStack(); heap->GetLiveBitmap()->Walk(CopyAndFixupObjectsCallback, this); - Thread::Current()->EndAssertNoThreadSuspension(old_cause); + self->EndAssertNoThreadSuspension(old_cause); } void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) { diff --git a/src/indirect_reference_table_test.cc b/src/indirect_reference_table_test.cc index 971e42a3dc..b5a05ece2b 100644 --- a/src/indirect_reference_table_test.cc +++ b/src/indirect_reference_table_test.cc @@ -49,13 +49,13 @@ TEST_F(IndirectReferenceTableTest, BasicTest) { Class* c = class_linker_->FindSystemClass("Ljava/lang/Object;"); ASSERT_TRUE(c != NULL); - Object* obj0 = c->AllocObject(); + Object* obj0 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj0 != NULL); - Object* obj1 = c->AllocObject(); + Object* obj1 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj1 != NULL); - Object* obj2 = c->AllocObject(); + Object* obj2 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj2 != NULL); - Object* obj3 = c->AllocObject(); + Object* obj3 = c->AllocObject(soa.Self()); ASSERT_TRUE(obj3 != NULL); const uint32_t cookie = IRT_FIRST_SEGMENT; diff --git a/src/intern_table.cc b/src/intern_table.cc index 10dd7f020a..5ad39582b8 100644 --- a/src/intern_table.cc +++ b/src/intern_table.cc @@ -25,19 +25,19 @@ InternTable::InternTable() : intern_table_lock_("InternTable lock") { } size_t InternTable::Size() const { - MutexLock mu(intern_table_lock_); + MutexLock mu(Thread::Current(), intern_table_lock_); return strong_interns_.size() + weak_interns_.size(); } void InternTable::DumpForSigQuit(std::ostream& os) const { - MutexLock mu(intern_table_lock_); + MutexLock mu(Thread::Current(), intern_table_lock_); os << "Intern table: " << strong_interns_.size() << " strong; " << weak_interns_.size() << " weak; " << image_strong_interns_.size() << " image strong\n"; } void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { - MutexLock mu(intern_table_lock_); + MutexLock mu(Thread::Current(), intern_table_lock_); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = strong_interns_.begin(), end = strong_interns_.end(); it != end; ++it) { visitor(it->second, arg); @@ -46,7 +46,7 @@ void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) const { } String* InternTable::Lookup(Table& table, String* s, uint32_t hash_code) { - intern_table_lock_.AssertHeld(); + intern_table_lock_.AssertHeld(Thread::Current()); typedef Table::const_iterator It; // TODO: C++0x auto for (It it = table.find(hash_code), end = table.end(); it != end; ++it) { String* existing_string = it->second; @@ -58,18 +58,18 @@ String* InternTable::Lookup(Table& table, String* s, uint32_t hash_code) { } String* InternTable::Insert(Table& table, String* s, uint32_t hash_code) { - intern_table_lock_.AssertHeld(); + intern_table_lock_.AssertHeld(Thread::Current()); table.insert(std::make_pair(hash_code, s)); return s; } void InternTable::RegisterStrong(String* s) { - MutexLock mu(intern_table_lock_); + MutexLock mu(Thread::Current(), intern_table_lock_); Insert(image_strong_interns_, s, s->GetHashCode()); } void InternTable::Remove(Table& table, const String* s, uint32_t hash_code) { - intern_table_lock_.AssertHeld(); + intern_table_lock_.AssertHeld(Thread::Current()); typedef Table::iterator It; // TODO: C++0x auto for (It it = table.find(hash_code), end = table.end(); it != end; ++it) { if (it->second == s) { @@ -80,7 +80,7 @@ void InternTable::Remove(Table& table, const String* s, uint32_t hash_code) { } String* InternTable::Insert(String* s, bool is_strong) { - MutexLock mu(intern_table_lock_); + MutexLock mu(Thread::Current(), intern_table_lock_); DCHECK(s != NULL); uint32_t hash_code = s->GetHashCode(); @@ -129,11 +129,11 @@ String* InternTable::Insert(String* s, bool is_strong) { } String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) { - return InternStrong(String::AllocFromModifiedUtf8(utf16_length, utf8_data)); + return InternStrong(String::AllocFromModifiedUtf8(Thread::Current(), utf16_length, utf8_data)); } String* InternTable::InternStrong(const char* utf8_data) { - return InternStrong(String::AllocFromModifiedUtf8(utf8_data)); + return InternStrong(String::AllocFromModifiedUtf8(Thread::Current(), utf8_data)); } String* InternTable::InternStrong(String* s) { @@ -151,13 +151,13 @@ String* InternTable::InternWeak(String* s) { } bool InternTable::ContainsWeak(String* s) { - MutexLock mu(intern_table_lock_); + MutexLock mu(Thread::Current(), intern_table_lock_); const String* found = Lookup(weak_interns_, s, s->GetHashCode()); return found == s; } void InternTable::SweepInternTableWeaks(Heap::IsMarkedTester is_marked, void* arg) { - MutexLock mu(intern_table_lock_); + MutexLock mu(Thread::Current(), intern_table_lock_); typedef Table::iterator It; // TODO: C++0x auto for (It it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) { Object* object = it->second; diff --git a/src/intern_table_test.cc b/src/intern_table_test.cc index 2833f6e225..ee9165e69a 100644 --- a/src/intern_table_test.cc +++ b/src/intern_table_test.cc @@ -29,7 +29,7 @@ TEST_F(InternTableTest, Intern) { InternTable intern_table; SirtRef<String> foo_1(soa.Self(), intern_table.InternStrong(3, "foo")); SirtRef<String> foo_2(soa.Self(), intern_table.InternStrong(3, "foo")); - SirtRef<String> foo_3(soa.Self(), String::AllocFromModifiedUtf8("foo")); + SirtRef<String> foo_3(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); SirtRef<String> bar(soa.Self(), intern_table.InternStrong(3, "bar")); EXPECT_TRUE(foo_1->Equals("foo")); EXPECT_TRUE(foo_2->Equals("foo")); @@ -47,7 +47,7 @@ TEST_F(InternTableTest, Size) { InternTable t; EXPECT_EQ(0U, t.Size()); t.InternStrong(3, "foo"); - SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8("foo")); + SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); t.InternWeak(foo.get()); EXPECT_EQ(1U, t.Size()); t.InternStrong(3, "bar"); @@ -91,8 +91,8 @@ TEST_F(InternTableTest, SweepInternTableWeaks) { InternTable t; t.InternStrong(3, "foo"); t.InternStrong(3, "bar"); - SirtRef<String> hello(soa.Self(), String::AllocFromModifiedUtf8("hello")); - SirtRef<String> world(soa.Self(), String::AllocFromModifiedUtf8("world")); + SirtRef<String> hello(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "hello")); + SirtRef<String> world(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "world")); SirtRef<String> s0(soa.Self(), t.InternWeak(hello.get())); SirtRef<String> s1(soa.Self(), t.InternWeak(world.get())); @@ -110,7 +110,7 @@ TEST_F(InternTableTest, SweepInternTableWeaks) { EXPECT_EQ(2U, t.Size()); // Just check that we didn't corrupt the map. - SirtRef<String> still_here(soa.Self(), String::AllocFromModifiedUtf8("still here")); + SirtRef<String> still_here(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "still here")); t.InternWeak(still_here.get()); EXPECT_EQ(3U, t.Size()); } @@ -130,8 +130,8 @@ TEST_F(InternTableTest, ContainsWeak) { { // Weaks are always weak. InternTable t; - SirtRef<String> foo_1(soa.Self(), String::AllocFromModifiedUtf8("foo")); - SirtRef<String> foo_2(soa.Self(), String::AllocFromModifiedUtf8("foo")); + SirtRef<String> foo_1(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); + SirtRef<String> foo_2(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); EXPECT_NE(foo_1.get(), foo_2.get()); SirtRef<String> interned_foo_1(soa.Self(), t.InternWeak(foo_1.get())); SirtRef<String> interned_foo_2(soa.Self(), t.InternWeak(foo_2.get())); @@ -142,7 +142,7 @@ TEST_F(InternTableTest, ContainsWeak) { { // A weak can be promoted to a strong. InternTable t; - SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8("foo")); + SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); SirtRef<String> interned_foo_1(soa.Self(), t.InternWeak(foo.get())); EXPECT_TRUE(t.ContainsWeak(interned_foo_1.get())); SirtRef<String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo")); @@ -155,7 +155,7 @@ TEST_F(InternTableTest, ContainsWeak) { InternTable t; SirtRef<String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo")); EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get())); - SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8("foo")); + SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "foo")); SirtRef<String> interned_foo_2(soa.Self(), t.InternWeak(foo.get())); EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get())); EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get()); diff --git a/src/jdwp/jdwp_event.cc b/src/jdwp/jdwp_event.cc index 19f10eb4c3..2865f3a870 100644 --- a/src/jdwp/jdwp_event.cc +++ b/src/jdwp/jdwp_event.cc @@ -141,7 +141,7 @@ static void dumpEvent(const JdwpEvent* pEvent) { * not be added to the list, and an appropriate error will be returned. */ JdwpError JdwpState::RegisterEvent(JdwpEvent* pEvent) { - MutexLock mu(event_list_lock_); + MutexLock mu(Thread::Current(), event_list_lock_); CHECK(pEvent != NULL); CHECK(pEvent->prev == NULL); @@ -234,7 +234,7 @@ void JdwpState::UnregisterEvent(JdwpEvent* pEvent) { * explicitly remove one-off single-step events.) */ void JdwpState::UnregisterEventById(uint32_t requestId) { - MutexLock mu(event_list_lock_); + MutexLock mu(Thread::Current(), event_list_lock_); JdwpEvent* pEvent = event_list_; while (pEvent != NULL) { @@ -254,7 +254,7 @@ void JdwpState::UnregisterEventById(uint32_t requestId) { * Remove all entries from the event list. */ void JdwpState::UnregisterAll() { - MutexLock mu(event_list_lock_); + MutexLock mu(Thread::Current(), event_list_lock_); JdwpEvent* pEvent = event_list_; while (pEvent != NULL) { @@ -537,7 +537,7 @@ void JdwpState::SuspendByPolicy(JdwpSuspendPolicy suspend_policy, JDWP::ObjectId pReq->invoke_needed_ = false; VLOG(jdwp) << "invoke complete, signaling and self-suspending"; - MutexLock mu(pReq->lock_); + MutexLock mu(Thread::Current(), pReq->lock_); pReq->cond_.Signal(); } } @@ -615,7 +615,7 @@ void JdwpState::ClearWaitForEventThread() { * function is called by dvmSuspendSelf(), and the transition back * to RUNNING would confuse it. */ - MutexLock mu(event_thread_lock_); + MutexLock mu(Thread::Current(), event_thread_lock_); CHECK_NE(event_thread_id_, 0U); VLOG(jdwp) << StringPrintf("cleared event token (%#llx)", event_thread_id_); @@ -676,7 +676,7 @@ bool JdwpState::PostVMStart() { ExpandBuf* pReq = eventPrep(); { - MutexLock mu(event_list_lock_); // probably don't need this here + MutexLock mu(Thread::Current(), event_list_lock_); // probably don't need this here VLOG(jdwp) << "EVENT: " << EK_VM_START; VLOG(jdwp) << " suspend_policy=" << suspend_policy; @@ -757,7 +757,7 @@ bool JdwpState::PostLocationEvent(const JdwpLocation* pLoc, ObjectId thisPtr, in JdwpSuspendPolicy suspend_policy = SP_NONE; { - MutexLock mu(event_list_lock_); + MutexLock mu(Thread::Current(), event_list_lock_); match_list = AllocMatchList(event_list_size_); if ((eventFlags & Dbg::kBreakpoint) != 0) { FindMatchingEvents(EK_BREAKPOINT, &basket, match_list, &match_count); @@ -828,7 +828,7 @@ bool JdwpState::PostThreadChange(ObjectId threadId, bool start) { int match_count = 0; { // Don't allow the list to be updated while we scan it. - MutexLock mu(event_list_lock_); + MutexLock mu(Thread::Current(), event_list_lock_); JdwpEvent** match_list = AllocMatchList(event_list_size_); if (start) { @@ -917,7 +917,7 @@ bool JdwpState::PostException(const JdwpLocation* pThrowLoc, ExpandBuf* pReq = NULL; JdwpSuspendPolicy suspend_policy = SP_NONE; { - MutexLock mu(event_list_lock_); + MutexLock mu(Thread::Current(), event_list_lock_); match_list = AllocMatchList(event_list_size_); FindMatchingEvents(EK_EXCEPTION, &basket, match_list, &match_count); if (match_count != 0) { @@ -987,7 +987,7 @@ bool JdwpState::PostClassPrepare(JdwpTypeTag tag, RefTypeId refTypeId, const std JdwpSuspendPolicy suspend_policy = SP_NONE; int match_count = 0; { - MutexLock mu(event_list_lock_); + MutexLock mu(Thread::Current(), event_list_lock_); JdwpEvent** match_list = AllocMatchList(event_list_size_); FindMatchingEvents(EK_CLASS_PREPARE, &basket, match_list, &match_count); if (match_count != 0) { diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc index 0c3a9a0567..69fc2fcfc5 100644 --- a/src/jdwp/jdwp_main.cc +++ b/src/jdwp/jdwp_main.cc @@ -47,7 +47,7 @@ JdwpNetStateBase::JdwpNetStateBase() : socket_lock_("JdwpNetStateBase lock") { * Write a packet. Grabs a mutex to assure atomicity. */ ssize_t JdwpNetStateBase::writePacket(ExpandBuf* pReply) { - MutexLock mu(socket_lock_); + MutexLock mu(Thread::Current(), socket_lock_); return write(clientSock, expandBufGetBuffer(pReply), expandBufGetLength(pReply)); } @@ -55,7 +55,7 @@ ssize_t JdwpNetStateBase::writePacket(ExpandBuf* pReply) { * Write a buffered packet. Grabs a mutex to assure atomicity. */ ssize_t JdwpNetStateBase::writeBufferedPacket(const iovec* iov, int iov_count) { - MutexLock mu(socket_lock_); + MutexLock mu(Thread::Current(), socket_lock_); return writev(clientSock, iov, iov_count); } @@ -72,7 +72,7 @@ bool JdwpState::SendRequest(ExpandBuf* pReq) { * packets to the debugger. */ uint32_t JdwpState::NextRequestSerial() { - MutexLock mu(serial_lock_); + MutexLock mu(Thread::Current(), serial_lock_); return request_serial_++; } @@ -81,7 +81,7 @@ uint32_t JdwpState::NextRequestSerial() { * message type EventRequest.Set. */ uint32_t JdwpState::NextEventSerial() { - MutexLock mu(serial_lock_); + MutexLock mu(Thread::Current(), serial_lock_); return event_serial_++; } @@ -145,7 +145,7 @@ JdwpState* JdwpState::Create(const JdwpOptions* options) { * won't signal the cond var before we're waiting. */ { - MutexLock thread_start_locker(state->thread_start_lock_); + MutexLock thread_start_locker(self, state->thread_start_lock_); const bool should_suspend = options->suspend; if (!should_suspend) { /* @@ -161,7 +161,7 @@ JdwpState* JdwpState::Create(const JdwpOptions* options) { state->thread_start_cond_.Wait(self, state->thread_start_lock_); } else { { - MutexLock attach_locker(state->attach_lock_); + MutexLock attach_locker(self, state->attach_lock_); /* * We have bound to a port, or are trying to connect outbound to a * debugger. Create the JDWP thread and let it continue the mission. @@ -217,7 +217,7 @@ void JdwpState::ResetState() { UnregisterAll(); { - MutexLock mu(event_list_lock_); + MutexLock mu(Thread::Current(), event_list_lock_); CHECK(event_list_ == NULL); } @@ -302,11 +302,8 @@ void JdwpState::Run() { } /* set the thread state to kWaitingInMainDebuggerLoop so GCs don't wait for us */ - { - MutexLock mu(thread_, *Locks::thread_suspend_count_lock_); - CHECK_EQ(thread_->GetState(), kNative); - thread_->SetState(kWaitingInMainDebuggerLoop); - } + CHECK_EQ(thread_->GetState(), kNative); + thread_->SetState(kWaitingInMainDebuggerLoop); /* * Loop forever if we're in server mode, processing connections. In @@ -334,7 +331,7 @@ void JdwpState::Run() { */ if (!(*transport_->establish)(this, options_)) { /* wake anybody who was waiting for us to succeed */ - MutexLock mu(attach_lock_); + MutexLock mu(thread_, attach_lock_); attach_cond_.Broadcast(); break; } diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc index 81941c00de..16976d4994 100644 --- a/src/jni_compiler_test.cc +++ b/src/jni_compiler_test.cc @@ -115,11 +115,8 @@ int gJava_MyClassNatives_foo_calls = 0; void Java_MyClassNatives_foo(JNIEnv* env, jobject thisObj) { // 1 = thisObj EXPECT_EQ(1U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - Locks::mutator_lock_->AssertNotHeld(Thread::Current()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); + Locks::mutator_lock_->AssertNotHeld(Thread::Current()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(thisObj != NULL); EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_)); @@ -169,10 +166,7 @@ int gJava_MyClassNatives_fooI_calls = 0; jint Java_MyClassNatives_fooI(JNIEnv* env, jobject thisObj, jint x) { // 1 = thisObj EXPECT_EQ(1U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(thisObj != NULL); EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_)); @@ -197,10 +191,7 @@ int gJava_MyClassNatives_fooII_calls = 0; jint Java_MyClassNatives_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) { // 1 = thisObj EXPECT_EQ(1U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(thisObj != NULL); EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_)); @@ -226,10 +217,7 @@ int gJava_MyClassNatives_fooJJ_calls = 0; jlong Java_MyClassNatives_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) { // 1 = thisObj EXPECT_EQ(1U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(thisObj != NULL); EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_)); @@ -256,10 +244,7 @@ int gJava_MyClassNatives_fooDD_calls = 0; jdouble Java_MyClassNatives_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) { // 1 = thisObj EXPECT_EQ(1U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(thisObj != NULL); EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_)); @@ -287,10 +272,7 @@ int gJava_MyClassNatives_fooJJ_synchronized_calls = 0; jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject thisObj, jlong x, jlong y) { // 1 = thisObj EXPECT_EQ(1U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(thisObj != NULL); EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_)); @@ -315,10 +297,7 @@ jobject Java_MyClassNatives_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject jobject z) { // 3 = this + y + z EXPECT_EQ(3U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(thisObj != NULL); EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_)); @@ -368,10 +347,7 @@ int gJava_MyClassNatives_fooSII_calls = 0; jint Java_MyClassNatives_fooSII(JNIEnv* env, jclass klass, jint x, jint y) { // 1 = klass EXPECT_EQ(1U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(klass != NULL); EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass)); @@ -393,10 +369,7 @@ int gJava_MyClassNatives_fooSDD_calls = 0; jdouble Java_MyClassNatives_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) { // 1 = klass EXPECT_EQ(1U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(klass != NULL); EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass)); @@ -424,10 +397,7 @@ jobject Java_MyClassNatives_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y jobject z) { // 3 = klass + y + z EXPECT_EQ(3U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(klass != NULL); EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass)); @@ -478,10 +448,7 @@ int gJava_MyClassNatives_fooSSIOO_calls = 0; jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) { // 3 = klass + y + z EXPECT_EQ(3U, Thread::Current()->NumStackReferences()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - EXPECT_EQ(kNative, Thread::Current()->GetState()); - } + EXPECT_EQ(kNative, Thread::Current()->GetState()); EXPECT_EQ(Thread::Current()->GetJniEnv(), env); EXPECT_TRUE(klass != NULL); EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass)); diff --git a/src/jni_internal.cc b/src/jni_internal.cc index 75ab1f07d8..22438a0147 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -195,7 +195,7 @@ static jweak AddWeakGlobalReference(ScopedObjectAccess& soa, Object* obj) } JavaVMExt* vm = soa.Vm(); IndirectReferenceTable& weak_globals = vm->weak_globals; - MutexLock mu(vm->weak_globals_lock); + MutexLock mu(soa.Self(), vm->weak_globals_lock); IndirectRef ref = weak_globals.Add(IRT_FIRST_SEGMENT, obj); return reinterpret_cast<jweak>(ref); } @@ -203,15 +203,27 @@ static jweak AddWeakGlobalReference(ScopedObjectAccess& soa, Object* obj) static void CheckMethodArguments(AbstractMethod* m, JValue* args) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { MethodHelper mh(m); - ObjectArray<Class>* parameter_types = mh.GetParameterTypes(); - CHECK(parameter_types != NULL); + const DexFile::TypeList* params = mh.GetParameterTypeList(); + if (params == NULL) { + return; // No arguments so nothing to check. + } + uint32_t num_params = params->Size(); size_t error_count = 0; - for (int i = 0; i < parameter_types->GetLength(); ++i) { - Class* parameter_type = parameter_types->Get(i); - // TODO: check primitives are in range. - if (!parameter_type->IsPrimitive()) { + for (uint32_t i = 0; i < num_params; i++) { + uint16_t type_idx = params->GetTypeItem(i).type_idx_; + Class* param_type = mh.GetClassFromTypeIdx(type_idx); + if (param_type == NULL) { + Thread* self = Thread::Current(); + CHECK(self->IsExceptionPending()); + LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: " + << mh.GetTypeDescriptorFromTypeIdx(type_idx) << "\n" + << self->GetException()->Dump(); + self->ClearException(); + ++error_count; + } else if (!param_type->IsPrimitive()) { + // TODO: check primitives are in range. Object* argument = args[i].GetL(); - if (argument != NULL && !argument->InstanceOf(parameter_type)) { + if (argument != NULL && !argument->InstanceOf(param_type)) { LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of " << PrettyTypeOf(argument) << " as argument " << (i + 1) << " to " << PrettyMethod(m); ++error_count; @@ -382,14 +394,14 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con static void PinPrimitiveArray(const ScopedObjectAccess& soa, const Array* array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { JavaVMExt* vm = soa.Vm(); - MutexLock mu(vm->pins_lock); + MutexLock mu(soa.Self(), vm->pins_lock); vm->pin_table.Add(array); } static void UnpinPrimitiveArray(const ScopedObjectAccess& soa, const Array* array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { JavaVMExt* vm = soa.Vm(); - MutexLock mu(vm->pins_lock); + MutexLock mu(soa.Self(), vm->pins_lock); vm->pin_table.Remove(array); } @@ -521,7 +533,7 @@ class SharedLibrary { self->TransitionFromRunnableToSuspended(kWaitingForJniOnLoad); bool okay; { - MutexLock mu(jni_on_load_lock_); + MutexLock mu(self, jni_on_load_lock_); if (jni_on_load_thread_id_ == self->GetThinLockId()) { // Check this so we don't end up waiting for ourselves. We need to return "true" so the @@ -544,7 +556,7 @@ class SharedLibrary { } void SetResult(bool result) LOCKS_EXCLUDED(jni_on_load_lock_) { - MutexLock mu(jni_on_load_lock_); + MutexLock mu(Thread::Current(), jni_on_load_lock_); jni_on_load_result_ = result ? kOkay : kFailed; jni_on_load_thread_id_ = 0; @@ -836,7 +848,7 @@ class JNI { JavaVMExt* vm = soa.Vm(); IndirectReferenceTable& globals = vm->globals; Object* decoded_obj = soa.Decode<Object*>(obj); - MutexLock mu(vm->globals_lock); + MutexLock mu(soa.Self(), vm->globals_lock); IndirectRef ref = globals.Add(IRT_FIRST_SEGMENT, decoded_obj); return reinterpret_cast<jobject>(ref); } @@ -848,7 +860,7 @@ class JNI { ScopedObjectAccess soa(env); JavaVMExt* vm = soa.Vm(); IndirectReferenceTable& globals = vm->globals; - MutexLock mu(vm->globals_lock); + MutexLock mu(soa.Self(), vm->globals_lock); if (!globals.Remove(IRT_FIRST_SEGMENT, obj)) { LOG(WARNING) << "JNI WARNING: DeleteGlobalRef(" << obj << ") " @@ -868,7 +880,7 @@ class JNI { ScopedObjectAccess soa(env); JavaVMExt* vm = soa.Vm(); IndirectReferenceTable& weak_globals = vm->weak_globals; - MutexLock mu(vm->weak_globals_lock); + MutexLock mu(soa.Self(), vm->weak_globals_lock); if (!weak_globals.Remove(IRT_FIRST_SEGMENT, obj)) { LOG(WARNING) << "JNI WARNING: DeleteWeakGlobalRef(" << obj << ") " @@ -918,7 +930,7 @@ class JNI { if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) { return NULL; } - return soa.AddLocalReference<jobject>(c->AllocObject()); + return soa.AddLocalReference<jobject>(c->AllocObject(soa.Self())); } static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) { @@ -935,7 +947,7 @@ class JNI { if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) { return NULL; } - Object* result = c->AllocObject(); + Object* result = c->AllocObject(soa.Self()); if (result == NULL) { return NULL; } @@ -954,7 +966,7 @@ class JNI { if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true, true)) { return NULL; } - Object* result = c->AllocObject(); + Object* result = c->AllocObject(soa.Self()); if (result == NULL) { return NULL; } @@ -1754,7 +1766,7 @@ class JNI { static jstring NewString(JNIEnv* env, const jchar* chars, jsize char_count) { ScopedObjectAccess soa(env); - String* result = String::AllocFromUtf16(char_count, chars); + String* result = String::AllocFromUtf16(soa.Self(), char_count, chars); return soa.AddLocalReference<jstring>(result); } @@ -1763,7 +1775,7 @@ class JNI { return NULL; } ScopedObjectAccess soa(env); - String* result = String::AllocFromModifiedUtf8(utf); + String* result = String::AllocFromModifiedUtf8(soa.Self(), utf); return soa.AddLocalReference<jstring>(result); } @@ -1923,7 +1935,7 @@ class JNI { // Allocate and initialize if necessary. Class* array_class = soa.Decode<Class*>(java_array_class.get()); - ObjectArray<Object>* result = ObjectArray<Object>::Alloc(array_class, length); + ObjectArray<Object>* result = ObjectArray<Object>::Alloc(soa.Self(), array_class, length); if (initial_element != NULL) { Object* initial_object = soa.Decode<Object*>(initial_element); for (jsize i = 0; i < length; ++i) { @@ -2297,7 +2309,7 @@ class JNI { static JniT NewPrimitiveArray(const ScopedObjectAccess& soa, jsize length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { CHECK_GE(length, 0); // TODO: ReportJniError - ArtT* result = ArtT::Alloc(length); + ArtT* result = ArtT::Alloc(soa.Self(), length); return soa.AddLocalReference<JniT>(result); } @@ -2762,16 +2774,17 @@ void JavaVMExt::DumpForSigQuit(std::ostream& os) { os << " (with forcecopy)"; } os << "; workarounds are " << (work_around_app_jni_bugs ? "on" : "off"); + Thread* self = Thread::Current(); { - MutexLock mu(pins_lock); + MutexLock mu(self, pins_lock); os << "; pins=" << pin_table.Size(); } { - MutexLock mu(globals_lock); + MutexLock mu(self, globals_lock); os << "; globals=" << globals.Capacity(); } { - MutexLock mu(weak_globals_lock); + MutexLock mu(self, weak_globals_lock); if (weak_globals.Capacity() > 0) { os << " (plus " << weak_globals.Capacity() << " weak)"; } @@ -2779,22 +2792,23 @@ void JavaVMExt::DumpForSigQuit(std::ostream& os) { os << '\n'; { - MutexLock mu(libraries_lock); + MutexLock mu(self, libraries_lock); os << "Libraries: " << Dumpable<Libraries>(*libraries) << " (" << libraries->size() << ")\n"; } } void JavaVMExt::DumpReferenceTables(std::ostream& os) { + Thread* self = Thread::Current(); { - MutexLock mu(globals_lock); + MutexLock mu(self, globals_lock); globals.Dump(os); } { - MutexLock mu(weak_globals_lock); + MutexLock mu(self, weak_globals_lock); weak_globals.Dump(os); } { - MutexLock mu(pins_lock); + MutexLock mu(self, pins_lock); pin_table.Dump(os); } } @@ -2808,9 +2822,10 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_lo // TODO: for better results we should canonicalize the pathname (or even compare // inodes). This implementation is fine if everybody is using System.loadLibrary. SharedLibrary* library; + Thread* self = Thread::Current(); { // TODO: move the locking (and more of this logic) into Libraries. - MutexLock mu(libraries_lock); + MutexLock mu(self, libraries_lock); library = libraries->Get(path); } if (library != NULL) { @@ -2847,7 +2862,6 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_lo // This can execute slowly for a large library on a busy system, so we // want to switch from kRunnable while it executes. This allows the GC to ignore us. - Thread* self = Thread::Current(); self->TransitionFromRunnableToSuspended(kWaitingForJniOnLoad); void* handle = dlopen(path.empty() ? NULL : path.c_str(), RTLD_LAZY); self->TransitionFromSuspendedToRunnable(); @@ -2864,7 +2878,7 @@ bool JavaVMExt::LoadNativeLibrary(const std::string& path, ClassLoader* class_lo // TODO: move the locking (and more of this logic) into Libraries. bool created_library = false; { - MutexLock mu(libraries_lock); + MutexLock mu(self, libraries_lock); library = libraries->Get(path); if (library == NULL) { // We won race to get libraries_lock library = new SharedLibrary(path, handle, class_loader); @@ -2942,24 +2956,26 @@ void* JavaVMExt::FindCodeForNativeMethod(AbstractMethod* m) { std::string detail; void* native_method; + Thread* self = Thread::Current(); { - MutexLock mu(libraries_lock); + MutexLock mu(self, libraries_lock); native_method = libraries->FindNativeMethod(m, detail); } // throwing can cause libraries_lock to be reacquired if (native_method == NULL) { - Thread::Current()->ThrowNewException("Ljava/lang/UnsatisfiedLinkError;", detail.c_str()); + self->ThrowNewException("Ljava/lang/UnsatisfiedLinkError;", detail.c_str()); } return native_method; } void JavaVMExt::VisitRoots(Heap::RootVisitor* visitor, void* arg) { + Thread* self = Thread::Current(); { - MutexLock mu(globals_lock); + MutexLock mu(self, globals_lock); globals.VisitRoots(visitor, arg); } { - MutexLock mu(pins_lock); + MutexLock mu(self, pins_lock); pin_table.VisitRoots(visitor, arg); } // The weak_globals table is visited by the GC itself (because it mutates the table). diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc index bc1be28e0b..d94da1ef65 100644 --- a/src/jni_internal_test.cc +++ b/src/jni_internal_test.cc @@ -93,7 +93,7 @@ class JniInternalTest : public CommonTest { : c->FindVirtualMethod(method_name, method_signature); CHECK(method != NULL); - receiver = (is_static ? NULL : c->AllocObject()); + receiver = (is_static ? NULL : c->AllocObject(self)); AbstractMethod::InvokeStub* stub = method->GetInvokeStub(); CHECK(stub != NULL); diff --git a/src/logging.cc b/src/logging.cc index 48785c5ad2..5680ed0a34 100644 --- a/src/logging.cc +++ b/src/logging.cc @@ -105,7 +105,7 @@ LogMessage::~LogMessage() { // Do the actual logging with the lock held. { - MutexLock mu(*Locks::logging_lock_); + MutexLock mu(Thread::Current(), *Locks::logging_lock_); if (msg.find('\n') == std::string::npos) { LogLine(msg.c_str()); } else { diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc index e9056f5055..96223a98e2 100644 --- a/src/mark_sweep.cc +++ b/src/mark_sweep.cc @@ -378,7 +378,7 @@ void MarkSweep::SweepJniWeakGlobals(bool swap_bitmaps) { } JavaVMExt* vm = Runtime::Current()->GetJavaVM(); - MutexLock mu(vm->weak_globals_lock); + MutexLock mu(Thread::Current(), vm->weak_globals_lock); IndirectReferenceTable* table = &vm->weak_globals; typedef IndirectReferenceTable::iterator It; // TODO: C++0x auto for (It it = table->begin(), end = table->end(); it != end; ++it) { @@ -428,7 +428,7 @@ void MarkSweep::VerifySystemWeaks() { runtime->GetMonitorList()->SweepMonitorList(VerifyIsLiveCallback, this); JavaVMExt* vm = runtime->GetJavaVM(); - MutexLock mu(vm->weak_globals_lock); + MutexLock mu(Thread::Current(), vm->weak_globals_lock); IndirectReferenceTable* table = &vm->weak_globals; typedef IndirectReferenceTable::iterator It; // TODO: C++0x auto for (It it = table->begin(), end = table->end(); it != end; ++it) { @@ -440,17 +440,18 @@ void MarkSweep::VerifySystemWeaks() { struct SweepCallbackContext { MarkSweep* mark_sweep; AllocSpace* space; + Thread* self; }; void MarkSweep::SweepCallback(size_t num_ptrs, Object** ptrs, void* arg) { - Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current()); - size_t freed_objects = num_ptrs; size_t freed_bytes = 0; SweepCallbackContext* context = static_cast<SweepCallbackContext*>(arg); MarkSweep* mark_sweep = context->mark_sweep; Heap* heap = mark_sweep->GetHeap(); AllocSpace* space = context->space; + Thread* self = context->self; + Locks::heap_bitmap_lock_->AssertExclusiveHeld(self); // Use a bulk free, that merges consecutive objects before freeing or free per object? // Documentation suggests better free performance with merging, but this may be at the expensive // of allocation. @@ -462,12 +463,12 @@ void MarkSweep::SweepCallback(size_t num_ptrs, Object** ptrs, void* arg) { freed_bytes += space->AllocationSize(obj); } // AllocSpace::FreeList clears the value in ptrs, so perform after clearing the live bit - space->FreeList(num_ptrs, ptrs); + space->FreeList(self, num_ptrs, ptrs); } else { for (size_t i = 0; i < num_ptrs; ++i) { Object* obj = static_cast<Object*>(ptrs[i]); freed_bytes += space->AllocationSize(obj); - space->Free(obj); + space->Free(self, obj); } } @@ -477,9 +478,8 @@ void MarkSweep::SweepCallback(size_t num_ptrs, Object** ptrs, void* arg) { } void MarkSweep::ZygoteSweepCallback(size_t num_ptrs, Object** ptrs, void* arg) { - Locks::heap_bitmap_lock_->AssertExclusiveHeld(Thread::Current()); - SweepCallbackContext* context = static_cast<SweepCallbackContext*>(arg); + Locks::heap_bitmap_lock_->AssertExclusiveHeld(context->self); Heap* heap = context->mark_sweep->GetHeap(); // We don't free any actual memory to avoid dirtying the shared zygote pages. for (size_t i = 0; i < num_ptrs; ++i) { @@ -516,6 +516,7 @@ void MarkSweep::SweepArray(TimingLogger& logger, MarkStack* allocations, bool sw Object** out = objects; // Empty the allocation stack. + Thread* self = Thread::Current(); for (size_t i = 0;i < count;++i) { Object* obj = objects[i]; // There should only be objects in the AllocSpace/LargeObjectSpace in the allocation stack. @@ -530,7 +531,7 @@ void MarkSweep::SweepArray(TimingLogger& logger, MarkStack* allocations, bool sw ++freed_large_objects; size_t size = large_object_space->AllocationSize(obj); freed_bytes += size; - large_object_space->Free(obj); + large_object_space->Free(self, obj); } } logger.AddSplit("Process allocation stack"); @@ -538,7 +539,7 @@ void MarkSweep::SweepArray(TimingLogger& logger, MarkStack* allocations, bool sw size_t freed_objects = out - objects; VLOG(heap) << "Freed " << freed_objects << "/" << count << " objects with size " << PrettySize(freed_bytes); - space->FreeList(freed_objects, objects); + space->FreeList(self, freed_objects, objects); heap_->RecordFree(freed_objects + freed_large_objects, freed_bytes); freed_objects_ += freed_objects; freed_bytes_ += freed_bytes; @@ -557,6 +558,7 @@ void MarkSweep::Sweep(bool partial, bool swap_bitmaps) { const Spaces& spaces = heap_->GetSpaces(); SweepCallbackContext scc; scc.mark_sweep = this; + scc.self = Thread::Current(); // TODO: C++0x auto for (Spaces::const_iterator it = spaces.begin(); it != spaces.end(); ++it) { ContinuousSpace* space = *it; @@ -598,10 +600,11 @@ void MarkSweep::SweepLargeObjects(bool swap_bitmaps) { size_t freed_objects = 0; size_t freed_bytes = 0; // TODO: C++0x + Thread* self = Thread::Current(); for (SpaceSetMap::Objects::iterator it = live_objects.begin(); it != live_objects.end(); ++it) { if (!large_mark_objects->Test(*it)) { freed_bytes += large_object_space->AllocationSize(*it); - large_object_space->Free(const_cast<Object*>(*it)); + large_object_space->Free(self, const_cast<Object*>(*it)); ++freed_objects; } } diff --git a/src/monitor.cc b/src/monitor.cc index c0484af1bf..9890822d02 100644 --- a/src/monitor.cc +++ b/src/monitor.cc @@ -284,7 +284,7 @@ void Monitor::FailedUnlock(Object* o, Thread* expected_owner, Thread* found_owne { // TODO: isn't this too late to prevent threads from disappearing? // Acquire thread list lock so threads won't disappear from under us. - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); // Re-read owner now that we hold lock. current_owner = (monitor != NULL) ? monitor->owner_ : NULL; // Get short descriptions of the threads involved. @@ -427,7 +427,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, bool interruptShouldThr ThrowIllegalMonitorStateExceptionF("object not locked by thread before wait()"); return; } - monitor_lock_.AssertHeld(); + monitor_lock_.AssertHeld(self); WaitWithLock(self, ms, ns, interruptShouldThrow); } @@ -476,7 +476,7 @@ void Monitor::WaitWithLock(Thread* self, int64_t ms, int32_t ns, bool interruptS bool wasInterrupted = false; { // Pseudo-atomically wait on self's wait_cond_ and release the monitor lock. - MutexLock mu(*self->wait_mutex_); + MutexLock mu(self, *self->wait_mutex_); // Set wait_monitor_ to the monitor object we will be waiting on. When wait_monitor_ is // non-NULL a notifying or interrupting thread must signal the thread's wait_cond_ to wake it @@ -538,7 +538,7 @@ void Monitor::WaitWithLock(Thread* self, int64_t ms, int32_t ns, bool interruptS * cleared when this exception is thrown." */ { - MutexLock mu(*self->wait_mutex_); + MutexLock mu(self, *self->wait_mutex_); self->interrupted_ = false; } if (interruptShouldThrow) { @@ -554,11 +554,11 @@ void Monitor::Notify(Thread* self) { ThrowIllegalMonitorStateExceptionF("object not locked by thread before notify()"); return; } - monitor_lock_.AssertHeld(); - NotifyWithLock(); + monitor_lock_.AssertHeld(self); + NotifyWithLock(self); } -void Monitor::NotifyWithLock() { +void Monitor::NotifyWithLock(Thread* self) { // Signal the first waiting thread in the wait set. while (wait_set_ != NULL) { Thread* thread = wait_set_; @@ -566,7 +566,7 @@ void Monitor::NotifyWithLock() { thread->wait_next_ = NULL; // Check to see if the thread is still waiting. - MutexLock mu(*thread->wait_mutex_); + MutexLock mu(self, *thread->wait_mutex_); if (thread->wait_monitor_ != NULL) { thread->wait_cond_->Signal(); return; @@ -581,7 +581,7 @@ void Monitor::NotifyAll(Thread* self) { ThrowIllegalMonitorStateExceptionF("object not locked by thread before notifyAll()"); return; } - monitor_lock_.AssertHeld(); + monitor_lock_.AssertHeld(self); NotifyAllWithLock(); } @@ -872,10 +872,7 @@ static uint32_t LockOwnerFromThreadLock(Object* thread_lock) { void Monitor::DescribeWait(std::ostream& os, const Thread* thread) { ThreadState state; - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - state = thread->GetState(); - } + state = thread->GetState(); Object* object = NULL; uint32_t lock_owner = ThreadList::kInvalidId; @@ -883,7 +880,7 @@ void Monitor::DescribeWait(std::ostream& os, const Thread* thread) { os << " - waiting on "; Monitor* monitor; { - MutexLock mu(*thread->wait_mutex_); + MutexLock mu(Thread::Current(), *thread->wait_mutex_); monitor = thread->wait_monitor_; } if (monitor != NULL) { @@ -1002,17 +999,17 @@ MonitorList::MonitorList() : monitor_list_lock_("MonitorList lock") { } MonitorList::~MonitorList() { - MutexLock mu(monitor_list_lock_); + MutexLock mu(Thread::Current(), monitor_list_lock_); STLDeleteElements(&list_); } void MonitorList::Add(Monitor* m) { - MutexLock mu(monitor_list_lock_); + MutexLock mu(Thread::Current(), monitor_list_lock_); list_.push_front(m); } void MonitorList::SweepMonitorList(Heap::IsMarkedTester is_marked, void* arg) { - MutexLock mu(monitor_list_lock_); + MutexLock mu(Thread::Current(), monitor_list_lock_); typedef std::list<Monitor*>::iterator It; // TODO: C++0x auto It it = list_.begin(); while (it != list_.end()) { diff --git a/src/monitor.h b/src/monitor.h index 4a627288de..4277d2c22a 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -115,7 +115,7 @@ class Monitor { bool Unlock(Thread* thread, bool for_wait) UNLOCK_FUNCTION(monitor_lock_); void Notify(Thread* self) NO_THREAD_SAFETY_ANALYSIS; - void NotifyWithLock() + void NotifyWithLock(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(monitor_lock_) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/src/mutex.cc b/src/mutex.cc index 522f849583..96e04ef353 100644 --- a/src/mutex.cc +++ b/src/mutex.cc @@ -196,7 +196,7 @@ Mutex::~Mutex() { if (rc != 0) { errno = rc; // TODO: should we just not log at all if shutting down? this could be the logging mutex! - MutexLock mu(*Locks::runtime_shutdown_lock_); + MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_); Runtime* runtime = Runtime::Current(); bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown(); PLOG(shutting_down ? WARNING : FATAL) << "pthread_mutex_destroy failed for " << name_; @@ -329,7 +329,7 @@ ReaderWriterMutex::~ReaderWriterMutex() { if (rc != 0) { errno = rc; // TODO: should we just not log at all if shutting down? this could be the logging mutex! - MutexLock mu(*Locks::runtime_shutdown_lock_); + MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_); Runtime* runtime = Runtime::Current(); bool shutting_down = runtime == NULL || runtime->IsShuttingDown(); PLOG(shutting_down ? WARNING : FATAL) << "pthread_rwlock_destroy failed for " << name_; @@ -586,7 +586,7 @@ ConditionVariable::~ConditionVariable() { int rc = pthread_cond_destroy(&cond_); if (rc != 0) { errno = rc; - MutexLock mu(*Locks::runtime_shutdown_lock_); + MutexLock mu(Thread::Current(), *Locks::runtime_shutdown_lock_); Runtime* runtime = Runtime::Current(); bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown(); PLOG(shutting_down ? WARNING : FATAL) << "pthread_cond_destroy failed for " << name_; diff --git a/src/mutex.h b/src/mutex.h index 32aeaf9b5d..d51e2ccb2d 100644 --- a/src/mutex.h +++ b/src/mutex.h @@ -25,8 +25,8 @@ #include "globals.h" #include "locks.h" +#include "logging.h" #include "macros.h" -#include "thread.h" #if defined(__APPLE__) #define ART_USE_FUTEXES 0 @@ -43,6 +43,8 @@ namespace art { +class Thread; + const bool kDebugLocking = kIsDebugBuild; // Base class for all Mutex implementations @@ -110,7 +112,6 @@ class LOCKABLE Mutex : public BaseMutex { } } void AssertHeld(const Thread* self) { AssertExclusiveHeld(self); } - void AssertHeld() { AssertExclusiveHeld(Thread::Current()); } // Assert that the Mutex is not held by the current thread. void AssertNotHeldExclusive(const Thread* self) { @@ -275,10 +276,6 @@ class SCOPED_LOCKABLE MutexLock { mu_.ExclusiveLock(self_); } - explicit MutexLock(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : self_(Thread::Current()), mu_(mu) { - mu_.ExclusiveLock(self_); - } - ~MutexLock() UNLOCK_FUNCTION() { mu_.ExclusiveUnlock(self_); } @@ -300,11 +297,6 @@ class SCOPED_LOCKABLE ReaderMutexLock { mu_.SharedLock(self_); } - explicit ReaderMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : - self_(Thread::Current()), mu_(mu) { - mu_.SharedLock(self_); - } - ~ReaderMutexLock() UNLOCK_FUNCTION() { mu_.SharedUnlock(self_); } @@ -327,17 +319,12 @@ class SCOPED_LOCKABLE WriterMutexLock { mu_.ExclusiveLock(self_); } - explicit WriterMutexLock(ReaderWriterMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : - self_(Thread::Current()), mu_(mu) { - mu_.ExclusiveLock(self_); - } - ~WriterMutexLock() UNLOCK_FUNCTION() { mu_.ExclusiveUnlock(self_); } private: - Thread* self_; + Thread* const self_; ReaderWriterMutex& mu_; DISALLOW_COPY_AND_ASSIGN(WriterMutexLock); }; diff --git a/src/native/dalvik_system_VMRuntime.cc b/src/native/dalvik_system_VMRuntime.cc index 7184e48ff4..91b7b5f401 100644 --- a/src/native/dalvik_system_VMRuntime.cc +++ b/src/native/dalvik_system_VMRuntime.cc @@ -54,11 +54,11 @@ static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaEle Class* element_class = soa.Decode<Class*>(javaElementClass); if (element_class == NULL) { - Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "element class == null"); + soa.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "element class == null"); return NULL; } if (length < 0) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length); + soa.Self()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length); return NULL; } @@ -67,7 +67,7 @@ static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaEle descriptor += "["; descriptor += ClassHelper(element_class).GetDescriptor(); Class* array_class = class_linker->FindClass(descriptor.c_str(), NULL); - Array* result = Array::Alloc(array_class, length); + Array* result = Array::Alloc(soa.Self(), array_class, length); if (result == NULL) { return NULL; } @@ -81,7 +81,7 @@ static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) { ScopedObjectAccess soa(env); Array* array = soa.Decode<Array*>(javaArray); if (!array->IsArrayInstance()) { - Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;", "not an array"); + soa.Self()->ThrowNewException("Ljava/lang/IllegalArgumentException;", "not an array"); return 0; } // TODO: we should also check that this is a non-movable array. @@ -127,7 +127,7 @@ static void DisableCheckJniCallback(Thread* t, void*) { } #endif -static void VMRuntime_setTargetSdkVersion(JNIEnv*, jobject, jint targetSdkVersion) { +static void VMRuntime_setTargetSdkVersion(JNIEnv* env, jobject, jint targetSdkVersion) { // This is the target SDK version of the app we're about to run. // Note that targetSdkVersion may be CUR_DEVELOPMENT (10000). // Note that targetSdkVersion may be 0, meaning "current". @@ -138,7 +138,8 @@ static void VMRuntime_setTargetSdkVersion(JNIEnv*, jobject, jint targetSdkVersio #if !defined(ART_USE_LLVM_COMPILER) if (vm->check_jni) { LOG(WARNING) << "Turning off CheckJNI so we can turn on JNI app bug workarounds..."; - MutexLock mu(*Locks::thread_list_lock_); + Thread* self = static_cast<JNIEnvExt*>(env)->self; + MutexLock mu(self, *Locks::thread_list_lock_); vm->SetCheckJniEnabled(false); runtime->GetThreadList()->ForEach(DisableCheckJniCallback, NULL); } @@ -148,6 +149,7 @@ static void VMRuntime_setTargetSdkVersion(JNIEnv*, jobject, jint targetSdkVersio vm->work_around_app_jni_bugs = true; #else + UNUSED(env); LOG(WARNING) << "LLVM does not work-around app jni bugs."; vm->work_around_app_jni_bugs = false; #endif diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc index c023b7e2da..488df80e65 100644 --- a/src/native/java_lang_Class.cc +++ b/src/native/java_lang_Class.cc @@ -199,7 +199,8 @@ static jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboo AbstractMethod* m = c->GetVirtualMethod(i); mh.ChangeMethod(m); if (IsVisibleMethod(m, publicOnly)) { - if (mh.GetReturnType() == NULL || mh.GetParameterTypes() == NULL) { + // TODO: the use of GetParameterTypes creates an unused array here. + if (mh.GetReturnType() == NULL || mh.GetParameterTypes(soa.Self()) == NULL) { DCHECK(env->ExceptionOccurred()); return NULL; } @@ -213,7 +214,8 @@ static jobjectArray Class_getDeclaredMethods(JNIEnv* env, jclass javaClass, jboo AbstractMethod* m = c->GetDirectMethod(i); mh.ChangeMethod(m); if (IsVisibleMethod(m, publicOnly)) { - if (mh.GetReturnType() == NULL || mh.GetParameterTypes() == NULL) { + // TODO: the use of GetParameterTypes creates an unused array here. + if (mh.GetReturnType() == NULL || mh.GetParameterTypes(soa.Self()) == NULL) { DCHECK(env->ExceptionOccurred()); return NULL; } @@ -349,7 +351,7 @@ static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) { static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) { ScopedObjectAccess soa(env); SynthesizedProxyClass* c = down_cast<SynthesizedProxyClass*>(DecodeClass(soa, javaThis)); - return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone()); + return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self())); } static jboolean Class_isAssignableFrom(JNIEnv* env, jobject javaLhs, jclass javaRhs) { @@ -412,7 +414,7 @@ static jobject Class_newInstanceImpl(JNIEnv* env, jobject javaThis) { return NULL; } - Object* new_obj = c->AllocObject(); + Object* new_obj = c->AllocObject(soa.Self()); if (new_obj == NULL) { DCHECK(soa.Self()->IsExceptionPending()); return NULL; diff --git a/src/native/java_lang_Object.cc b/src/native/java_lang_Object.cc index 89019f78a9..a6ae49dcf1 100644 --- a/src/native/java_lang_Object.cc +++ b/src/native/java_lang_Object.cc @@ -23,7 +23,7 @@ namespace art { static jobject Object_internalClone(JNIEnv* env, jobject javaThis) { ScopedObjectAccess soa(env); Object* o = soa.Decode<Object*>(javaThis); - return soa.AddLocalReference<jobject>(o->Clone()); + return soa.AddLocalReference<jobject>(o->Clone(soa.Self())); } static void Object_notify(JNIEnv* env, jobject javaThis) { diff --git a/src/native/java_lang_Thread.cc b/src/native/java_lang_Thread.cc index edf55c3c9e..cf475e280c 100644 --- a/src/native/java_lang_Thread.cc +++ b/src/native/java_lang_Thread.cc @@ -34,7 +34,7 @@ static jboolean Thread_interrupted(JNIEnv* env, jclass) { static jboolean Thread_isInterrupted(JNIEnv* env, jobject java_thread) { ScopedObjectAccess soa(env); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = Thread::FromManagedThread(soa, java_thread); return (thread != NULL) ? thread->IsInterrupted() : JNI_FALSE; } @@ -55,10 +55,9 @@ static jint Thread_nativeGetStatus(JNIEnv* env, jobject java_thread, jboolean ha ScopedObjectAccess soa(env); ThreadState internal_thread_state = (has_been_started ? kTerminated : kStarting); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = Thread::FromManagedThread(soa, java_thread); if (thread != NULL) { - MutexLock mu(*Locks::thread_suspend_count_lock_); internal_thread_state = thread->GetState(); } switch (internal_thread_state) { @@ -91,7 +90,7 @@ static jboolean Thread_nativeHoldsLock(JNIEnv* env, jobject java_thread, jobject Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "object == null"); return JNI_FALSE; } - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = Thread::FromManagedThread(soa, java_thread); return thread->HoldsLock(object); } @@ -138,7 +137,7 @@ static void Thread_nativeSetName(JNIEnv* env, jobject peer, jstring java_name) { */ static void Thread_nativeSetPriority(JNIEnv* env, jobject java_thread, jint new_priority) { ScopedObjectAccess soa(env); - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(soa.Self(), *Locks::thread_list_lock_); Thread* thread = Thread::FromManagedThread(soa, java_thread); if (thread != NULL) { thread->SetNativePriority(new_priority); diff --git a/src/native/java_lang_reflect_Array.cc b/src/native/java_lang_reflect_Array.cc index d3a57bf917..863f9fce7b 100644 --- a/src/native/java_lang_reflect_Array.cc +++ b/src/native/java_lang_reflect_Array.cc @@ -29,7 +29,7 @@ static Array* CreateMultiArray(Thread* self, Class* array_class, int current_dim IntArray* dimensions) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { int32_t array_length = dimensions->Get(current_dimension++); - SirtRef<Array> new_array(self, Array::Alloc(array_class, array_length)); + SirtRef<Array> new_array(self, Array::Alloc(self, array_class, array_length)); if (new_array.get() == NULL) { CHECK(self->IsExceptionPending()); return NULL; @@ -139,7 +139,7 @@ static jobject Array_createObjectArray(JNIEnv* env, jclass, jclass javaElementCl return NULL; } DCHECK(array_class->IsArrayClass()); - Array* new_array = Array::Alloc(array_class, length); + Array* new_array = Array::Alloc(soa.Self(), array_class, length); if (new_array == NULL) { CHECK(soa.Self()->IsExceptionPending()); return NULL; diff --git a/src/native/java_lang_reflect_Constructor.cc b/src/native/java_lang_reflect_Constructor.cc index 44b459dec0..ed0d1f127b 100644 --- a/src/native/java_lang_reflect_Constructor.cc +++ b/src/native/java_lang_reflect_Constructor.cc @@ -45,7 +45,7 @@ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectA return NULL; } - Object* receiver = c->AllocObject(); + Object* receiver = c->AllocObject(soa.Self()); if (receiver == NULL) { return NULL; } diff --git a/src/native/java_lang_reflect_Method.cc b/src/native/java_lang_reflect_Method.cc index 63a277be52..b1eb6e07d7 100644 --- a/src/native/java_lang_reflect_Method.cc +++ b/src/native/java_lang_reflect_Method.cc @@ -44,7 +44,7 @@ static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) { } CHECK_NE(throws_index, -1); ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index); - return soa.AddLocalReference<jobject>(declared_exceptions->Clone()); + return soa.AddLocalReference<jobject>(declared_exceptions->Clone(soa.Self())); } static jobject Method_findOverriddenMethodNative(JNIEnv* env, jobject javaMethod) { diff --git a/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc index 66c27e434f..0ed964b65a 100644 --- a/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc +++ b/src/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc @@ -39,7 +39,7 @@ static jboolean DdmVmInternal_getRecentAllocationStatus(JNIEnv*, jclass) { return Dbg::IsAllocTrackingEnabled(); } -static jobject FindThreadByThinLockId(JNIEnv*, uint32_t thin_lock_id) { +static jobject FindThreadByThinLockId(JNIEnv* env, uint32_t thin_lock_id) { struct ThreadFinder { explicit ThreadFinder(uint32_t thin_lock_id) : thin_lock_id(thin_lock_id), thread(NULL) { } @@ -56,7 +56,8 @@ static jobject FindThreadByThinLockId(JNIEnv*, uint32_t thin_lock_id) { }; ThreadFinder finder(thin_lock_id); { - MutexLock mu(*Locks::thread_list_lock_); + Thread* self = static_cast<JNIEnvExt*>(env)->self; + MutexLock mu(self, *Locks::thread_list_lock_); Runtime::Current()->GetThreadList()->ForEach(ThreadFinder::Callback, &finder); } if (finder.thread != NULL) { @@ -133,10 +134,7 @@ static void ThreadStatsGetterCallback(Thread* t, void* context) { std::vector<uint8_t>& bytes = *reinterpret_cast<std::vector<uint8_t>*>(context); JDWP::Append4BE(bytes, t->GetThinLockId()); - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - JDWP::Append1BE(bytes, t->GetState()); - } + JDWP::Append1BE(bytes, t->GetState()); JDWP::Append4BE(bytes, t->GetTid()); JDWP::Append4BE(bytes, utime); JDWP::Append4BE(bytes, stime); @@ -145,8 +143,9 @@ static void ThreadStatsGetterCallback(Thread* t, void* context) { static jbyteArray DdmVmInternal_getThreadStats(JNIEnv* env, jclass) { std::vector<uint8_t> bytes; + Thread* self = static_cast<JNIEnvExt*>(env)->self; { - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(self, *Locks::thread_list_lock_); ThreadList* thread_list = Runtime::Current()->GetThreadList(); uint16_t thread_count = 0; diff --git a/src/oat/runtime/arm/stub_arm.cc b/src/oat/runtime/arm/stub_arm.cc index 7add255882..4099ddbc98 100644 --- a/src/oat/runtime/arm/stub_arm.cc +++ b/src/oat/runtime/arm/stub_arm.cc @@ -82,7 +82,8 @@ ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> resolution_trampoline(Thread::Current(), ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> resolution_trampoline(self, ByteArray::Alloc(self, cs)); CHECK(resolution_trampoline.get() != NULL); MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength()); assembler->FinalizeInstructions(code); @@ -128,7 +129,8 @@ ByteArray* CreateAbstractMethodErrorStub() { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> abstract_stub(Thread::Current(), ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> abstract_stub(self, ByteArray::Alloc(self, cs)); CHECK(abstract_stub.get() != NULL); MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); assembler->FinalizeInstructions(code); @@ -156,7 +158,8 @@ ByteArray* CreateJniDlsymLookupStub() { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> jni_stub(Thread::Current(), ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> jni_stub(self, ByteArray::Alloc(self, cs)); CHECK(jni_stub.get() != NULL); MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); assembler->FinalizeInstructions(code); diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc index d545e4ae6b..9691308092 100644 --- a/src/oat/runtime/mips/stub_mips.cc +++ b/src/oat/runtime/mips/stub_mips.cc @@ -112,7 +112,8 @@ ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> resolution_trampoline(Thread::Current(), ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> resolution_trampoline(self, ByteArray::Alloc(self, cs)); CHECK(resolution_trampoline.get() != NULL); MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength()); assembler->FinalizeInstructions(code); @@ -157,7 +158,8 @@ ByteArray* CreateAbstractMethodErrorStub() { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> abstract_stub(Thread::Current(), ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> abstract_stub(self, ByteArray::Alloc(self, cs)); CHECK(abstract_stub.get() != NULL); MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); assembler->FinalizeInstructions(code); @@ -197,7 +199,8 @@ ByteArray* CreateJniDlsymLookupStub() { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> jni_stub(Thread::Current(), ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> jni_stub(self, ByteArray::Alloc(self, cs)); CHECK(jni_stub.get() != NULL); MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); assembler->FinalizeInstructions(code); diff --git a/src/oat/runtime/support_alloc.cc b/src/oat/runtime/support_alloc.cc index fd7fb658e4..fb70285073 100644 --- a/src/oat/runtime/support_alloc.cc +++ b/src/oat/runtime/support_alloc.cc @@ -37,7 +37,7 @@ extern "C" Array* artAllocArrayFromCode(uint32_t type_idx, AbstractMethod* metho Thread* self, AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); - return AllocArrayFromCode(type_idx, method, component_count, false); + return AllocArrayFromCode(type_idx, method, component_count, self, false); } extern "C" Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, AbstractMethod* method, @@ -45,7 +45,7 @@ extern "C" Array* artAllocArrayFromCodeWithAccessCheck(uint32_t type_idx, Abstra Thread* self, AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly); - return AllocArrayFromCode(type_idx, method, component_count, true); + return AllocArrayFromCode(type_idx, method, component_count, self, true); } extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, diff --git a/src/oat/runtime/support_proxy.cc b/src/oat/runtime/support_proxy.cc index 4ff2e5f2e3..3d0c1c8d72 100644 --- a/src/oat/runtime/support_proxy.cc +++ b/src/oat/runtime/support_proxy.cc @@ -104,7 +104,7 @@ extern "C" void artProxyInvokeHandler(AbstractMethod* proxy_method, Object* rece args_jobj[2].l = NULL; ObjectArray<Object>* args = NULL; if ((num_params - 1) > 0) { - args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(num_params - 1); + args = Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(self, num_params - 1); if (args == NULL) { CHECK(self->IsExceptionPending()); return; @@ -120,7 +120,7 @@ extern "C" void artProxyInvokeHandler(AbstractMethod* proxy_method, Object* rece cur_arg = 0; // reset stack location to read to start // reset index, will index into param type array which doesn't include the receiver param_index = 0; - ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes(); + ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes(self); if (param_types == NULL) { CHECK(self->IsExceptionPending()); return; diff --git a/src/oat/runtime/x86/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc index 7941d158ea..cade99deb8 100644 --- a/src/oat/runtime/x86/stub_x86.cc +++ b/src/oat/runtime/x86/stub_x86.cc @@ -92,7 +92,8 @@ ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> resolution_trampoline(Thread::Current(), ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> resolution_trampoline(self, ByteArray::Alloc(self, cs)); CHECK(resolution_trampoline.get() != NULL); MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength()); assembler->FinalizeInstructions(code); @@ -146,7 +147,8 @@ ByteArray* CreateAbstractMethodErrorStub() { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> abstract_stub(Thread::Current(),ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> abstract_stub(self, ByteArray::Alloc(self, cs)); CHECK(abstract_stub.get() != NULL); MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength()); assembler->FinalizeInstructions(code); @@ -179,7 +181,8 @@ ByteArray* CreateJniDlsymLookupStub() { assembler->EmitSlowPaths(); size_t cs = assembler->CodeSize(); - SirtRef<ByteArray> jni_stub(Thread::Current(), ByteArray::Alloc(cs)); + Thread* self = Thread::Current(); + SirtRef<ByteArray> jni_stub(self, ByteArray::Alloc(self, cs)); CHECK(jni_stub.get() != NULL); MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength()); assembler->FinalizeInstructions(code); diff --git a/src/oatdump.cc b/src/oatdump.cc index 7e14199e18..01b204283d 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -575,11 +575,12 @@ class ImageDumper { // Loop through all the image spaces and dump their objects. Heap* heap = Runtime::Current()->GetHeap(); const Spaces& spaces = heap->GetSpaces(); + Thread* self = Thread::Current(); { - WriterMutexLock mu(*Locks::heap_bitmap_lock_); + WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); heap->FlushAllocStack(); } - ReaderMutexLock mu(*Locks::heap_bitmap_lock_); + ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); // TODO: C++0x auto for (Spaces::const_iterator it = spaces.begin(); it != spaces.end(); ++it) { Space* space = *it; diff --git a/src/object.cc b/src/object.cc index 8582a210f9..e8381dbf1c 100644 --- a/src/object.cc +++ b/src/object.cc @@ -47,7 +47,7 @@ String* Object::AsString() { return down_cast<String*>(this); } -Object* Object::Clone() { +Object* Object::Clone(Thread* self) { Class* c = GetClass(); DCHECK(!c->IsClassClass()); @@ -55,7 +55,7 @@ Object* Object::Clone() { // Using c->AllocObject() here would be wrong. size_t num_bytes = SizeOf(); Heap* heap = Runtime::Current()->GetHeap(); - SirtRef<Object> copy(Thread::Current(), heap->AllocObject(c, num_bytes)); + SirtRef<Object> copy(self, heap->AllocObject(self, c, num_bytes)); if (copy.get() == NULL) { return NULL; } @@ -727,13 +727,13 @@ void Class::SetDexCache(DexCache* new_dex_cache) { SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache, false); } -Object* Class::AllocObject() { +Object* Class::AllocObject(Thread* self) { DCHECK(!IsArrayClass()) << PrettyClass(this); DCHECK(IsInstantiable()) << PrettyClass(this); // TODO: decide whether we want this check. It currently fails during bootstrap. // DCHECK(!Runtime::Current()->IsStarted() || IsInitializing()) << PrettyClass(this); DCHECK_GE(this->object_size_, sizeof(Object)); - return Runtime::Current()->GetHeap()->AllocObject(this, this->object_size_); + return Runtime::Current()->GetHeap()->AllocObject(self, this, this->object_size_); } void Class::SetClassSize(size_t new_class_size) { @@ -768,7 +768,7 @@ String* Class::ComputeName() { default: LOG(FATAL) << "Unknown primitive type: " << PrintableChar(descriptor[0]); } - name = String::AllocFromModifiedUtf8(c_name); + name = String::AllocFromModifiedUtf8(Thread::Current(), c_name); } else { // Convert the UTF-8 name to a java.lang.String. The name must use '.' to separate package // components. @@ -777,7 +777,7 @@ String* Class::ComputeName() { descriptor.erase(descriptor.size() - 1); } std::replace(descriptor.begin(), descriptor.end(), '/', '.'); - name = String::AllocFromModifiedUtf8(descriptor.c_str()); + name = String::AllocFromModifiedUtf8(Thread::Current(), descriptor.c_str()); } SetName(name); return name; @@ -1288,7 +1288,8 @@ Field* Class::FindField(const StringPiece& name, const StringPiece& type) { return NULL; } -Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) { +Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count, + size_t component_size) { DCHECK(array_class != NULL); DCHECK_GE(component_count, 0); DCHECK(array_class->IsArrayClass()); @@ -1300,14 +1301,14 @@ Array* Array::Alloc(Class* array_class, int32_t component_count, size_t componen // Check for overflow and throw OutOfMemoryError if this was an unreasonable request. size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size); if (data_size >> component_shift != size_t(component_count) || size < data_size) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/OutOfMemoryError;", + self->ThrowNewExceptionF("Ljava/lang/OutOfMemoryError;", "%s of length %d would overflow", PrettyDescriptor(array_class).c_str(), component_count); return NULL; } Heap* heap = Runtime::Current()->GetHeap(); - Array* array = down_cast<Array*>(heap->AllocObject(array_class, size)); + Array* array = down_cast<Array*>(heap->AllocObject(self, array_class, size)); if (array != NULL) { DCHECK(array->IsArrayInstance()); array->SetLength(component_count); @@ -1315,9 +1316,9 @@ Array* Array::Alloc(Class* array_class, int32_t component_count, size_t componen return array; } -Array* Array::Alloc(Class* array_class, int32_t component_count) { +Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count) { DCHECK(array_class->IsArrayClass()); - return Alloc(array_class, component_count, array_class->GetComponentSize()); + return Alloc(self, array_class, component_count, array_class->GetComponentSize()); } bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const { @@ -1334,9 +1335,9 @@ bool Array::ThrowArrayStoreException(Object* object) const { } template<typename T> -PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) { +PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) { DCHECK(array_class_ != NULL); - Array* raw_array = Array::Alloc(array_class_, length, sizeof(T)); + Array* raw_array = Array::Alloc(self, array_class_, length, sizeof(T)); return down_cast<PrimitiveArray<T>*>(raw_array); } @@ -1402,11 +1403,12 @@ uint16_t String::CharAt(int32_t index) const { return GetCharArray()->Get(index + GetOffset()); } -String* String::AllocFromUtf16(int32_t utf16_length, +String* String::AllocFromUtf16(Thread* self, + int32_t utf16_length, const uint16_t* utf16_data_in, int32_t hash_code) { CHECK(utf16_data_in != NULL || utf16_length == 0); - String* string = Alloc(GetJavaLangString(), utf16_length); + String* string = Alloc(self, GetJavaLangString(), utf16_length); if (string == NULL) { return NULL; } @@ -1426,17 +1428,17 @@ String* String::AllocFromUtf16(int32_t utf16_length, return string; } -String* String::AllocFromModifiedUtf8(const char* utf) { + String* String::AllocFromModifiedUtf8(Thread* self, const char* utf) { if (utf == NULL) { return NULL; } size_t char_count = CountModifiedUtf8Chars(utf); - return AllocFromModifiedUtf8(char_count, utf); + return AllocFromModifiedUtf8(self, char_count, utf); } -String* String::AllocFromModifiedUtf8(int32_t utf16_length, +String* String::AllocFromModifiedUtf8(Thread* self, int32_t utf16_length, const char* utf8_data_in) { - String* string = Alloc(GetJavaLangString(), utf16_length); + String* string = Alloc(self, GetJavaLangString(), utf16_length); if (string == NULL) { return NULL; } @@ -1447,18 +1449,18 @@ String* String::AllocFromModifiedUtf8(int32_t utf16_length, return string; } -String* String::Alloc(Class* java_lang_String, int32_t utf16_length) { - SirtRef<CharArray> array(Thread::Current(), CharArray::Alloc(utf16_length)); +String* String::Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length) { + SirtRef<CharArray> array(self, CharArray::Alloc(self, utf16_length)); if (array.get() == NULL) { return NULL; } - return Alloc(java_lang_String, array.get()); + return Alloc(self, java_lang_String, array.get()); } -String* String::Alloc(Class* java_lang_String, CharArray* array) { +String* String::Alloc(Thread* self, Class* java_lang_String, CharArray* array) { // Hold reference in case AllocObject causes GC. - SirtRef<CharArray> array_ref(Thread::Current(), array); - String* string = down_cast<String*>(java_lang_String->AllocObject()); + SirtRef<CharArray> array_ref(self, array); + String* string = down_cast<String*>(java_lang_String->AllocObject(self)); if (string == NULL) { return NULL; } @@ -1610,12 +1612,13 @@ void StackTraceElement::ResetClass() { java_lang_StackTraceElement_ = NULL; } -StackTraceElement* StackTraceElement::Alloc(String* declaring_class, +StackTraceElement* StackTraceElement::Alloc(Thread* self, + String* declaring_class, String* method_name, String* file_name, int32_t line_number) { StackTraceElement* trace = - down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject()); + down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject(self)); trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), const_cast<String*>(declaring_class), false); trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), diff --git a/src/object.h b/src/object.h index 5fccb04079..baa7313bb2 100644 --- a/src/object.h +++ b/src/object.h @@ -177,7 +177,7 @@ class MANAGED Object { size_t SizeOf() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - Object* Clone() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); int32_t IdentityHashCode() const { #ifdef MOVING_GARBAGE_COLLECTOR @@ -1054,10 +1054,11 @@ class MANAGED Array : public Object { public: // A convenience for code that doesn't know the component size, // and doesn't want to have to work it out itself. - static Array* Alloc(Class* array_class, int32_t component_count) + static Array* Alloc(Thread* self, Class* array_class, int32_t component_count) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static Array* Alloc(Class* array_class, int32_t component_count, size_t component_size) + static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, + size_t component_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); size_t SizeOf() const; @@ -1121,7 +1122,7 @@ class MANAGED Array : public Object { template<class T> class MANAGED ObjectArray : public Array { public: - static ObjectArray<T>* Alloc(Class* object_array_class, int32_t length) + static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); T* Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -1139,7 +1140,7 @@ class MANAGED ObjectArray : public Array { size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ObjectArray<T>* CopyOf(int32_t new_length) + ObjectArray<T>* CopyOf(Thread* self, int32_t new_length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); private: @@ -1147,8 +1148,8 @@ class MANAGED ObjectArray : public Array { }; template<class T> -ObjectArray<T>* ObjectArray<T>::Alloc(Class* object_array_class, int32_t length) { - Array* array = Array::Alloc(object_array_class, length, sizeof(Object*)); +ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, int32_t length) { + Array* array = Array::Alloc(self, object_array_class, length, sizeof(Object*)); if (UNLIKELY(array == NULL)) { return NULL; } else { @@ -1166,8 +1167,8 @@ inline T* ObjectArray<T>::Get(int32_t i) const { } template<class T> -ObjectArray<T>* ObjectArray<T>::CopyOf(int32_t new_length) { - ObjectArray<T>* new_array = Alloc(GetClass(), new_length); +ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) { + ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length); Copy(this, 0, new_array, 0, std::min(GetLength(), new_length)); return new_array; } @@ -1450,7 +1451,7 @@ class MANAGED Class : public StaticStorageBase { } // Creates a raw object instance but does not invoke the default constructor. - Object* AllocObject() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + Object* AllocObject(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool IsVariableSize() const { // Classes and arrays vary in size, and so the object_size_ field cannot @@ -2282,7 +2283,7 @@ class MANAGED PrimitiveArray : public Array { public: typedef T ElementType; - static PrimitiveArray<T>* Alloc(size_t length) + static PrimitiveArray<T>* Alloc(Thread* self, size_t length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); const T* GetData() const { @@ -2370,22 +2371,23 @@ class MANAGED String : public Object { String* Intern() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static String* AllocFromUtf16(int32_t utf16_length, + static String* AllocFromUtf16(Thread* self, + int32_t utf16_length, const uint16_t* utf16_data_in, int32_t hash_code = 0) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static String* AllocFromModifiedUtf8(const char* utf) + static String* AllocFromModifiedUtf8(Thread* self, const char* utf) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static String* AllocFromModifiedUtf8(int32_t utf16_length, + static String* AllocFromModifiedUtf8(Thread* self, int32_t utf16_length, const char* utf8_data_in) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static String* Alloc(Class* java_lang_String, int32_t utf16_length) + static String* Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - static String* Alloc(Class* java_lang_String, CharArray* array) + static String* Alloc(Thread* self, Class* java_lang_String, CharArray* array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); bool Equals(const char* modified_utf8) const @@ -2617,7 +2619,8 @@ class MANAGED StackTraceElement : public Object { OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false); } - static StackTraceElement* Alloc(String* declaring_class, + static StackTraceElement* Alloc(Thread* self, + String* declaring_class, String* method_name, String* file_name, int32_t line_number) diff --git a/src/object_test.cc b/src/object_test.cc index f28c20b598..9ad0534f5f 100644 --- a/src/object_test.cc +++ b/src/object_test.cc @@ -44,7 +44,8 @@ class ObjectTest : public CommonTest { utf16_expected[i] = ch; } - SirtRef<String> string(Thread::Current(), String::AllocFromModifiedUtf8(length, utf8_in)); + Thread* self = Thread::Current(); + SirtRef<String> string(self, String::AllocFromModifiedUtf8(self, length, utf8_in)); ASSERT_EQ(length, string->GetLength()); ASSERT_TRUE(string->GetCharArray() != NULL); ASSERT_TRUE(string->GetCharArray()->GetData() != NULL); @@ -77,16 +78,18 @@ TEST_F(ObjectTest, IsInSamePackage) { TEST_F(ObjectTest, Clone) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<ObjectArray<Object> > a1(soa.Self(), class_linker_->AllocObjectArray<Object>(256)); + SirtRef<ObjectArray<Object> > a1(soa.Self(), + class_linker_->AllocObjectArray<Object>(soa.Self(), 256)); size_t s1 = a1->SizeOf(); - Object* clone = a1->Clone(); + Object* clone = a1->Clone(soa.Self()); EXPECT_EQ(s1, clone->SizeOf()); EXPECT_TRUE(clone->GetClass() == a1->GetClass()); } TEST_F(ObjectTest, AllocObjectArray) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<ObjectArray<Object> > oa(soa.Self(), class_linker_->AllocObjectArray<Object>(2)); + SirtRef<ObjectArray<Object> > oa(soa.Self(), + class_linker_->AllocObjectArray<Object>(soa.Self(), 2)); EXPECT_EQ(2, oa->GetLength()); EXPECT_TRUE(oa->Get(0) == NULL); EXPECT_TRUE(oa->Get(1) == NULL); @@ -119,15 +122,15 @@ TEST_F(ObjectTest, AllocObjectArray) { TEST_F(ObjectTest, AllocArray) { ScopedObjectAccess soa(Thread::Current()); Class* c = class_linker_->FindSystemClass("[I"); - SirtRef<Array> a(soa.Self(), Array::Alloc(c, 1)); + SirtRef<Array> a(soa.Self(), Array::Alloc(soa.Self(), c, 1)); ASSERT_TRUE(c == a->GetClass()); c = class_linker_->FindSystemClass("[Ljava/lang/Object;"); - a.reset(Array::Alloc(c, 1)); + a.reset(Array::Alloc(soa.Self(), c, 1)); ASSERT_TRUE(c == a->GetClass()); c = class_linker_->FindSystemClass("[[Ljava/lang/Object;"); - a.reset(Array::Alloc(c, 1)); + a.reset(Array::Alloc(soa.Self(), c, 1)); ASSERT_TRUE(c == a->GetClass()); } @@ -136,7 +139,7 @@ void TestPrimitiveArray(ClassLinker* cl) { ScopedObjectAccess soa(Thread::Current()); typedef typename ArrayT::ElementType T; - ArrayT* a = ArrayT::Alloc(2); + ArrayT* a = ArrayT::Alloc(soa.Self(), 2); EXPECT_EQ(2, a->GetLength()); EXPECT_EQ(0, a->Get(0)); EXPECT_EQ(0, a->Get(1)); @@ -238,7 +241,7 @@ TEST_F(ObjectTest, StaticFieldFromCode) { Object* s0 = field->GetObj(NULL); EXPECT_EQ(NULL, s0); - SirtRef<CharArray> char_array(soa.Self(), CharArray::Alloc(0)); + SirtRef<CharArray> char_array(soa.Self(), CharArray::Alloc(soa.Self(), 0)); field->SetObj(NULL, char_array.get()); EXPECT_EQ(char_array.get(), field->GetObj(NULL)); @@ -274,7 +277,7 @@ TEST_F(ObjectTest, String) { TEST_F(ObjectTest, StringEqualsUtf8) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8("android")); + SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "android")); EXPECT_TRUE(string->Equals("android")); EXPECT_FALSE(string->Equals("Android")); EXPECT_FALSE(string->Equals("ANDROID")); @@ -282,15 +285,15 @@ TEST_F(ObjectTest, StringEqualsUtf8) { EXPECT_FALSE(string->Equals("and")); EXPECT_FALSE(string->Equals("androids")); - SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8("")); + SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "")); EXPECT_TRUE(empty->Equals("")); EXPECT_FALSE(empty->Equals("a")); } TEST_F(ObjectTest, StringEquals) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8("android")); - SirtRef<String> string_2(soa.Self(), String::AllocFromModifiedUtf8("android")); + SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "android")); + SirtRef<String> string_2(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "android")); EXPECT_TRUE(string->Equals(string_2.get())); EXPECT_FALSE(string->Equals("Android")); EXPECT_FALSE(string->Equals("ANDROID")); @@ -298,14 +301,14 @@ TEST_F(ObjectTest, StringEquals) { EXPECT_FALSE(string->Equals("and")); EXPECT_FALSE(string->Equals("androids")); - SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8("")); + SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "")); EXPECT_TRUE(empty->Equals("")); EXPECT_FALSE(empty->Equals("a")); } TEST_F(ObjectTest, StringLength) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8("android")); + SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "android")); EXPECT_EQ(string->GetLength(), 7); EXPECT_EQ(string->GetUtfLength(), 7); @@ -380,9 +383,9 @@ TEST_F(ObjectTest, DescriptorCompare) { TEST_F(ObjectTest, StringHashCode) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8("")); - SirtRef<String> A(soa.Self(), String::AllocFromModifiedUtf8("A")); - SirtRef<String> ABC(soa.Self(), String::AllocFromModifiedUtf8("ABC")); + SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "")); + SirtRef<String> A(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "A")); + SirtRef<String> ABC(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "ABC")); EXPECT_EQ(0, empty->GetHashCode()); EXPECT_EQ(65, A->GetHashCode()); @@ -399,8 +402,8 @@ TEST_F(ObjectTest, InstanceOf) { ASSERT_TRUE(X != NULL); ASSERT_TRUE(Y != NULL); - SirtRef<Object> x(soa.Self(), X->AllocObject()); - SirtRef<Object> y(soa.Self(), Y->AllocObject()); + SirtRef<Object> x(soa.Self(), X->AllocObject(soa.Self())); + SirtRef<Object> y(soa.Self(), Y->AllocObject(soa.Self())); ASSERT_TRUE(x.get() != NULL); ASSERT_TRUE(y.get() != NULL); @@ -416,7 +419,7 @@ TEST_F(ObjectTest, InstanceOf) { EXPECT_TRUE(Object_array_class->InstanceOf(java_lang_Class)); // All array classes implement Cloneable and Serializable. - Object* array = ObjectArray<Object>::Alloc(Object_array_class, 1); + Object* array = ObjectArray<Object>::Alloc(soa.Self(), Object_array_class, 1); Class* java_lang_Cloneable = class_linker_->FindSystemClass("Ljava/lang/Cloneable;"); Class* java_io_Serializable = class_linker_->FindSystemClass("Ljava/io/Serializable;"); EXPECT_TRUE(array->InstanceOf(java_lang_Cloneable)); @@ -515,7 +518,7 @@ TEST_F(ObjectTest, IsAssignableFromArray) { TEST_F(ObjectTest, FindInstanceField) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8("ABC")); + SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "ABC")); ASSERT_TRUE(s.get() != NULL); Class* c = s->GetClass(); ASSERT_TRUE(c != NULL); @@ -548,7 +551,7 @@ TEST_F(ObjectTest, FindInstanceField) { TEST_F(ObjectTest, FindStaticField) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8("ABC")); + SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "ABC")); ASSERT_TRUE(s.get() != NULL); Class* c = s->GetClass(); ASSERT_TRUE(c != NULL); diff --git a/src/object_utils.h b/src/object_utils.h index 1d66c8fee0..297035f1a0 100644 --- a/src/object_utils.h +++ b/src/object_utils.h @@ -24,6 +24,7 @@ #include "monitor.h" #include "object.h" #include "runtime.h" +#include "sirt_ref.h" #include "UniquePtr.h" #include <string> @@ -486,12 +487,15 @@ class MethodHelper { return GetDexFile().GetProtoParameters(proto); } - ObjectArray<Class>* GetParameterTypes() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + ObjectArray<Class>* GetParameterTypes(Thread* self) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile::TypeList* params = GetParameterTypeList(); - Class* array_class = GetClassLinker()->FindSystemClass("[Ljava/lang/Class;"); uint32_t num_params = params == NULL ? 0 : params->Size(); - ObjectArray<Class>* result = ObjectArray<Class>::Alloc(array_class, num_params); + SirtRef<ObjectArray<Class> > result(self, GetClassLinker()->AllocClassArray(self, num_params)); + if (UNLIKELY(result.get() == NULL)) { + CHECK(self->IsExceptionPending()); + return NULL; + } for (uint32_t i = 0; i < num_params; i++) { Class* param_type = GetClassFromTypeIdx(params->GetTypeItem(i).type_idx_); if (param_type == NULL) { @@ -500,7 +504,7 @@ class MethodHelper { } result->Set(i, param_type); } - return result; + return result.get(); } Class* GetReturnType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { diff --git a/src/reference_table_test.cc b/src/reference_table_test.cc index b35110d21d..c400f83c3c 100644 --- a/src/reference_table_test.cc +++ b/src/reference_table_test.cc @@ -25,7 +25,7 @@ class ReferenceTableTest : public CommonTest { TEST_F(ReferenceTableTest, Basics) { ScopedObjectAccess soa(Thread::Current()); - Object* o1 = String::AllocFromModifiedUtf8("hello"); + Object* o1 = String::AllocFromModifiedUtf8(soa.Self(), "hello"); ReferenceTable rt("test", 0, 11); @@ -56,7 +56,7 @@ TEST_F(ReferenceTableTest, Basics) { } // Add a second object 10 times and check dumping is sane. - Object* o2 = ShortArray::Alloc(0); + Object* o2 = ShortArray::Alloc(soa.Self(), 0); for (size_t i = 0; i < 10; ++i) { rt.Add(o2); EXPECT_EQ(i + 2, rt.Size()); diff --git a/src/reflection.cc b/src/reflection.cc index 7d73ae2c0a..c793d2ccee 100644 --- a/src/reflection.cc +++ b/src/reflection.cc @@ -234,11 +234,10 @@ void BoxPrimitive(Primitive::Type src_class, JValue& value) { LOG(FATAL) << static_cast<int>(src_class); } + ScopedObjectAccessUnchecked soa(Thread::Current()); if (kIsDebugBuild) { - MutexLock mu(*Locks::thread_suspend_count_lock_); - CHECK_EQ(Thread::Current()->GetState(), kRunnable); + CHECK_EQ(soa.Self()->GetState(), kRunnable); } - ScopedObjectAccessUnchecked soa(Thread::Current()); JValue args[1] = { value }; soa.DecodeMethod(m)->Invoke(soa.Self(), NULL, args, &value); } diff --git a/src/runtime.cc b/src/runtime.cc index d10c351a45..3444f7830d 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -187,7 +187,7 @@ struct AbortState { void Runtime::Abort() { // Ensure that we don't have multiple threads trying to abort at once, // which would result in significantly worse diagnostics. - MutexLock mu(*Locks::abort_lock_); + MutexLock mu(Thread::Current(), *Locks::abort_lock_); // Get any pending output out of the way. fflush(NULL); @@ -661,10 +661,7 @@ void Runtime::StartDaemonThreads() { Thread* self = Thread::Current(); // Must be in the kNative state for calling native methods. - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - CHECK_EQ(self->GetState(), kNative); - } + CHECK_EQ(self->GetState(), kNative); JNIEnv* env = self->GetJniEnv(); env->CallStaticVoidMethod(WellKnownClasses::java_lang_Daemons, WellKnownClasses::java_lang_Daemons_start); @@ -762,10 +759,7 @@ void Runtime::InitNativeMethods() { JNIEnv* env = self->GetJniEnv(); // Must be in the kNative state for calling native methods (JNI_OnLoad code). - { - MutexLock mu(*Locks::thread_suspend_count_lock_); - CHECK_EQ(self->GetState(), kNative); - } + CHECK_EQ(self->GetState(), kNative); // First set up JniConstants, which is used by both the runtime's built-in native // methods and libcore. @@ -984,8 +978,8 @@ void Runtime::SetResolutionStubArray(ByteArray* resolution_stub_array, Trampolin AbstractMethod* Runtime::CreateResolutionMethod() { Class* method_class = AbstractMethod::GetMethodClass(); - SirtRef<AbstractMethod> method(Thread::Current(), - down_cast<AbstractMethod*>(method_class->AllocObject())); + Thread* self = Thread::Current(); + SirtRef<AbstractMethod> method(self, down_cast<AbstractMethod*>(method_class->AllocObject(self))); method->SetDeclaringClass(method_class); // TODO: use a special method for resolution method saves method->SetDexMethodIndex(DexFile::kDexNoIndex16); @@ -998,8 +992,8 @@ AbstractMethod* Runtime::CreateResolutionMethod() { AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) { Class* method_class = AbstractMethod::GetMethodClass(); - SirtRef<AbstractMethod> - method(Thread::Current(), down_cast<AbstractMethod*>(method_class->AllocObject())); + Thread* self = Thread::Current(); + SirtRef<AbstractMethod> method(self, down_cast<AbstractMethod*>(method_class->AllocObject(self))); method->SetDeclaringClass(method_class); // TODO: use a special method for callee saves method->SetDexMethodIndex(DexFile::kDexNoIndex16); diff --git a/src/runtime_linux.cc b/src/runtime_linux.cc index 85eeb8f0be..01c08d3110 100644 --- a/src/runtime_linux.cc +++ b/src/runtime_linux.cc @@ -23,6 +23,7 @@ #include "logging.h" #include "mutex.h" #include "stringprintf.h" +#include "thread.h" #include "utils.h" namespace art { @@ -227,7 +228,7 @@ struct UContext { }; static void HandleUnexpectedSignal(int signal_number, siginfo_t* info, void* raw_context) { - MutexLock mu(*Locks::unexpected_signal_lock_); + MutexLock mu(Thread::Current(), *Locks::unexpected_signal_lock_); bool has_address = (signal_number == SIGILL || signal_number == SIGBUS || signal_number == SIGFPE || signal_number == SIGSEGV); diff --git a/src/runtime_support.cc b/src/runtime_support.cc index 4af6fe591e..54baa42747 100644 --- a/src/runtime_support.cc +++ b/src/runtime_support.cc @@ -100,19 +100,19 @@ Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method); if (klass == NULL) { // Error - DCHECK(Thread::Current()->IsExceptionPending()); + DCHECK(self->IsExceptionPending()); return NULL; // Failure } } if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) { if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;", - "Bad filled array request for type %s", - PrettyDescriptor(klass).c_str()); + self->ThrowNewExceptionF("Ljava/lang/RuntimeException;", + "Bad filled array request for type %s", + PrettyDescriptor(klass).c_str()); } else { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;", - "Found type %s; filled-new-array not implemented for anything but \'int\'", - PrettyDescriptor(klass).c_str()); + self->ThrowNewExceptionF("Ljava/lang/InternalError;", + "Found type %s; filled-new-array not implemented for anything but \'int\'", + PrettyDescriptor(klass).c_str()); } return NULL; // Failure } else { @@ -124,7 +124,7 @@ Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int } } DCHECK(klass->IsArrayClass()) << PrettyClass(klass); - return Array::Alloc(klass, component_count); + return Array::Alloc(self, klass, component_count); } } diff --git a/src/runtime_support.h b/src/runtime_support.h index eff50b3710..0d24e488ad 100644 --- a/src/runtime_support.h +++ b/src/runtime_support.h @@ -78,7 +78,7 @@ static inline Object* AllocObjectFromCode(uint32_t type_idx, AbstractMethod* met DCHECK(self->IsExceptionPending()); return NULL; // Failure } - return klass->AllocObject(); + return klass->AllocObject(self); } // Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If @@ -86,11 +86,10 @@ static inline Object* AllocObjectFromCode(uint32_t type_idx, AbstractMethod* met // When verification/compiler hasn't been able to verify access, optionally perform an access // check. static inline Array* AllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count, - bool access_check) + Thread* self, bool access_check) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { if (UNLIKELY(component_count < 0)) { - Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", - component_count); + self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count); return NULL; // Failure } Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx); @@ -109,7 +108,7 @@ static inline Array* AllocArrayFromCode(uint32_t type_idx, AbstractMethod* metho return NULL; // Failure } } - return Array::Alloc(klass, component_count); + return Array::Alloc(self, klass, component_count); } extern Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count, diff --git a/src/scoped_thread_state_change.h b/src/scoped_thread_state_change.h index 9da41e057b..32c3685096 100644 --- a/src/scoped_thread_state_change.h +++ b/src/scoped_thread_state_change.h @@ -35,7 +35,7 @@ class ScopedThreadStateChange { if (self_ == NULL) { // Value chosen arbitrarily and won't be used in the destructor since thread_ == NULL. old_thread_state_ = kTerminated; - MutexLock mu(*Locks::runtime_shutdown_lock_); + MutexLock mu(NULL, *Locks::runtime_shutdown_lock_); Runtime* runtime = Runtime::Current(); CHECK(runtime == NULL || !runtime->IsStarted() || runtime->IsShuttingDown()); } else { @@ -63,7 +63,7 @@ class ScopedThreadStateChange { ~ScopedThreadStateChange() LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) { if (self_ == NULL) { if (!expected_has_no_thread_) { - MutexLock mu(*Locks::runtime_shutdown_lock_); + MutexLock mu(NULL, *Locks::runtime_shutdown_lock_); Runtime* runtime = Runtime::Current(); bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown(); CHECK(shutting_down); diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc index 8376bb615c..b6f6a415e8 100644 --- a/src/signal_catcher.cc +++ b/src/signal_catcher.cc @@ -85,12 +85,12 @@ SignalCatcher::~SignalCatcher() { } void SignalCatcher::SetHaltFlag(bool new_value) { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); halt_ = new_value; } bool SignalCatcher::ShouldHalt() { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); return halt_; } diff --git a/src/space.cc b/src/space.cc index 58476ad365..c1f438468b 100644 --- a/src/space.cc +++ b/src/space.cc @@ -208,13 +208,13 @@ Object* AllocSpace::AllocWithoutGrowthLocked(size_t num_bytes) { return result; } -Object* AllocSpace::AllocWithoutGrowth(size_t num_bytes) { - MutexLock mu(lock_); +Object* AllocSpace::AllocWithoutGrowth(Thread* self, size_t num_bytes) { + MutexLock mu(self, lock_); return AllocWithoutGrowthLocked(num_bytes); } -Object* AllocSpace::AllocWithGrowth(size_t num_bytes) { - MutexLock mu(lock_); +Object* AllocSpace::AllocWithGrowth(Thread* self, size_t num_bytes) { + MutexLock mu(self, lock_); // Grow as much as possible within the mspace. size_t max_allowed = Capacity(); mspace_set_footprint_limit(mspace_, max_allowed); @@ -284,8 +284,8 @@ AllocSpace* AllocSpace::CreateZygoteSpace() { return alloc_space; } -void AllocSpace::Free(Object* ptr) { - MutexLock mu(lock_); +void AllocSpace::Free(Thread* self, Object* ptr) { + MutexLock mu(self, lock_); if (kDebugSpaces) { CHECK(ptr != NULL); CHECK(Contains(ptr)) << "Free (" << ptr << ") not in bounds of heap " << *this; @@ -298,8 +298,8 @@ void AllocSpace::Free(Object* ptr) { mspace_free(mspace_, ptr); } -void AllocSpace::FreeList(size_t num_ptrs, Object** ptrs) { - MutexLock mu(lock_); +void AllocSpace::FreeList(Thread* self, size_t num_ptrs, Object** ptrs) { + MutexLock mu(self, lock_); if (kDebugSpaces) { CHECK(ptrs != NULL); size_t num_broken_ptrs = 0; @@ -329,7 +329,7 @@ extern "C" void* art_heap_morecore(void* mspace, intptr_t increment) { } void* AllocSpace::MoreCore(intptr_t increment) { - lock_.AssertHeld(); + lock_.AssertHeld(Thread::Current()); byte* original_end = end_; if (increment != 0) { VLOG(heap) << "AllocSpace::MoreCore " << PrettySize(increment); @@ -382,7 +382,7 @@ void MspaceMadviseCallback(void* start, void* end, size_t used_bytes, void* /* a } void AllocSpace::Trim() { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); // Trim to release memory at the end of the space. mspace_trim(mspace_, 0); // Visit space looking for page-sized holes to advise the kernel we don't need. @@ -391,18 +391,18 @@ void AllocSpace::Trim() { void AllocSpace::Walk(void(*callback)(void *start, void *end, size_t num_bytes, void* callback_arg), void* arg) { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); mspace_inspect_all(mspace_, callback, arg); callback(NULL, NULL, 0, arg); // Indicate end of a space. } size_t AllocSpace::GetFootprintLimit() { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); return mspace_footprint_limit(mspace_); } void AllocSpace::SetFootprintLimit(size_t new_size) { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); VLOG(heap) << "AllocSpace::SetFootprintLimit " << PrettySize(new_size); // Compare against the actual footprint, rather than the Size(), because the heap may not have // grown all the way to the allowed size yet. @@ -575,12 +575,12 @@ LargeObjectMapSpace* LargeObjectMapSpace::Create(const std::string& name) { return new LargeObjectMapSpace(name); } -Object* LargeObjectMapSpace::Alloc(size_t num_bytes) { - MutexLock mu(lock_); +Object* LargeObjectMapSpace::Alloc(Thread* self, size_t num_bytes) { MemMap* mem_map = MemMap::MapAnonymous("allocation", NULL, num_bytes, PROT_READ | PROT_WRITE); if (mem_map == NULL) { return NULL; } + MutexLock mu(self, lock_); Object* obj = reinterpret_cast<Object*>(mem_map->Begin()); large_objects_.push_back(obj); mem_maps_.Put(obj, mem_map); @@ -589,8 +589,8 @@ Object* LargeObjectMapSpace::Alloc(size_t num_bytes) { return obj; } -void LargeObjectMapSpace::Free(Object* ptr) { - MutexLock mu(lock_); +void LargeObjectMapSpace::Free(Thread* self, Object* ptr) { + MutexLock mu(self, lock_); MemMaps::iterator found = mem_maps_.find(ptr); CHECK(found != mem_maps_.end()) << "Attempted to free large object which was not live"; DCHECK_GE(num_bytes_allocated_, found->second->Size()); @@ -601,14 +601,14 @@ void LargeObjectMapSpace::Free(Object* ptr) { } size_t LargeObjectMapSpace::AllocationSize(const Object* obj) { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); MemMaps::iterator found = mem_maps_.find(const_cast<Object*>(obj)); CHECK(found != mem_maps_.end()) << "Attempted to get size of a large object which is not live"; return found->second->Size(); } void LargeObjectMapSpace::Walk(AllocSpace::WalkCallback callback, void* arg) { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); for (MemMaps::iterator it = mem_maps_.begin(); it != mem_maps_.end(); ++it) { MemMap* mem_map = it->second; callback(mem_map->Begin(), mem_map->End(), mem_map->Size(), arg); @@ -617,7 +617,7 @@ void LargeObjectMapSpace::Walk(AllocSpace::WalkCallback callback, void* arg) { } bool LargeObjectMapSpace::Contains(const Object* obj) const { - MutexLock mu(const_cast<Mutex&>(lock_)); + MutexLock mu(Thread::Current(), lock_); return mem_maps_.find(const_cast<Object*>(obj)) != mem_maps_.end(); } @@ -679,7 +679,7 @@ void FreeListSpace::RemoveFreeChunk(Chunk* chunk) { } void FreeListSpace::Walk(AllocSpace::WalkCallback callback, void* arg) { - MutexLock mu(lock_); + MutexLock mu(Thread::Current(), lock_); for (Chunk* chunk = &chunks_.front(); chunk < &chunks_.back(); ) { if (!chunk->IsFree()) { size_t size = chunk->GetSize(); @@ -692,8 +692,8 @@ void FreeListSpace::Walk(AllocSpace::WalkCallback callback, void* arg) { } } -void FreeListSpace::Free(Object* obj) { - MutexLock mu(lock_); +void FreeListSpace::Free(Thread* self, Object* obj) { + MutexLock mu(self, lock_); CHECK(Contains(obj)); // Check adjacent chunks to see if we need to combine. Chunk* chunk = ChunkFromAddr(obj); @@ -734,8 +734,8 @@ size_t FreeListSpace::AllocationSize(const Object* obj) { return chunk->GetSize(); } -Object* FreeListSpace::Alloc(size_t num_bytes) { - MutexLock mu(lock_); +Object* FreeListSpace::Alloc(Thread* self, size_t num_bytes) { + MutexLock mu(self, lock_); num_bytes = RoundUp(num_bytes, kAlignment); Chunk temp; temp.SetSize(num_bytes); @@ -762,9 +762,9 @@ Object* FreeListSpace::Alloc(size_t num_bytes) { return reinterpret_cast<Object*>(addr); } -void FreeListSpace::FreeList(size_t num_ptrs, Object** ptrs) { +void FreeListSpace::FreeList(Thread* self, size_t num_ptrs, Object** ptrs) { for (size_t i = 0; i < num_ptrs; ++i) { - Free(ptrs[i]); + Free(self, ptrs[i]); } } diff --git a/src/space.h b/src/space.h index 12682f96f1..af6ab3befe 100644 --- a/src/space.h +++ b/src/space.h @@ -241,15 +241,15 @@ class AllocSpace : public MemMapSpace { size_t capacity, byte* requested_begin); // Allocate num_bytes without allowing the underlying mspace to grow. - virtual Object* AllocWithGrowth(size_t num_bytes); + virtual Object* AllocWithGrowth(Thread* self, size_t num_bytes); // Allocate num_bytes allowing the underlying mspace to grow. - virtual Object* AllocWithoutGrowth(size_t num_bytes); + virtual Object* AllocWithoutGrowth(Thread* self, size_t num_bytes); // Return the storage space required by obj. virtual size_t AllocationSize(const Object* obj); - virtual void Free(Object* ptr); - virtual void FreeList(size_t num_ptrs, Object** ptrs); + virtual void Free(Thread* self, Object* ptr); + virtual void FreeList(Thread* self, size_t num_ptrs, Object** ptrs); void* MoreCore(intptr_t increment); @@ -435,8 +435,8 @@ class LargeObjectSpace : public DiscontinuousSpace { // Return the storage space required by obj. virtual size_t AllocationSize(const Object* obj) = 0; - virtual Object* Alloc(size_t num_bytes) = 0; - virtual void Free(Object* ptr) = 0; + virtual Object* Alloc(Thread* self, size_t num_bytes) = 0; + virtual void Free(Thread* self, Object* ptr) = 0; virtual void Walk(AllocSpace::WalkCallback, void* arg) = 0; virtual ~LargeObjectSpace() {} @@ -472,8 +472,8 @@ class LargeObjectMapSpace : public LargeObjectSpace { // Return the storage space required by obj. virtual size_t AllocationSize(const Object* obj); - virtual Object* Alloc(size_t num_bytes); - virtual void Free(Object* ptr); + virtual Object* Alloc(Thread* self, size_t num_bytes); + virtual void Free(Thread* self, Object* ptr); virtual void Walk(AllocSpace::WalkCallback, void* arg); virtual bool Contains(const Object* obj) const; private: @@ -481,7 +481,7 @@ private: virtual ~LargeObjectMapSpace() {} // Used to ensure mutual exclusion when the allocation spaces data structures are being modified. - Mutex lock_; + mutable Mutex lock_; std::vector<Object*> large_objects_; typedef SafeMap<Object*, MemMap*> MemMaps; MemMaps mem_maps_; @@ -493,9 +493,9 @@ class FreeListSpace : public LargeObjectSpace { static FreeListSpace* Create(const std::string& name, byte* requested_begin, size_t capacity); virtual size_t AllocationSize(const Object* obj); - virtual Object* Alloc(size_t num_bytes); - virtual void Free(Object* obj); - virtual void FreeList(size_t num_ptrs, Object** ptrs); + virtual Object* Alloc(Thread* self, size_t num_bytes); + virtual void Free(Thread* self, Object* obj); + virtual void FreeList(Thread* self, size_t num_ptrs, Object** ptrs); virtual bool Contains(const Object* obj) const; virtual void Walk(AllocSpace::WalkCallback callback, void* arg); diff --git a/src/space_test.cc b/src/space_test.cc index e9c45c45b5..03191471c4 100644 --- a/src/space_test.cc +++ b/src/space_test.cc @@ -80,106 +80,108 @@ TEST_F(SpaceTest, ZygoteSpace) { // Make space findable to the heap, will also delete space when runtime is cleaned up Runtime::Current()->GetHeap()->AddSpace(space); + Thread* self = Thread::Current(); // Succeeds, fits without adjusting the footprint limit. - Object* ptr1 = space->AllocWithoutGrowth(1 * MB); + Object* ptr1 = space->AllocWithoutGrowth(self, 1 * MB); EXPECT_TRUE(ptr1 != NULL); // Fails, requires a higher footprint limit. - Object* ptr2 = space->AllocWithoutGrowth(8 * MB); + Object* ptr2 = space->AllocWithoutGrowth(self, 8 * MB); EXPECT_TRUE(ptr2 == NULL); // Succeeds, adjusts the footprint. - Object* ptr3 = space->AllocWithGrowth(8 * MB); + Object* ptr3 = space->AllocWithGrowth(self, 8 * MB); EXPECT_TRUE(ptr3 != NULL); // Fails, requires a higher footprint limit. - Object* ptr4 = space->AllocWithoutGrowth(8 * MB); + Object* ptr4 = space->AllocWithoutGrowth(self, 8 * MB); EXPECT_TRUE(ptr4 == NULL); // Also fails, requires a higher allowed footprint. - Object* ptr5 = space->AllocWithGrowth(8 * MB); + Object* ptr5 = space->AllocWithGrowth(self, 8 * MB); EXPECT_TRUE(ptr5 == NULL); // Release some memory. size_t free3 = space->AllocationSize(ptr3); - space->Free(ptr3); + space->Free(self, ptr3); EXPECT_LE(8U * MB, free3); // Succeeds, now that memory has been freed. - void* ptr6 = space->AllocWithGrowth(9 * MB); + void* ptr6 = space->AllocWithGrowth(self, 9 * MB); EXPECT_TRUE(ptr6 != NULL); // Final clean up. size_t free1 = space->AllocationSize(ptr1); - space->Free(ptr1); + space->Free(self, ptr1); EXPECT_LE(1U * MB, free1); // Make sure that the zygote space isn't directly at the start of the space. - space->AllocWithoutGrowth(1U * MB); + space->AllocWithoutGrowth(self, 1U * MB); space = space->CreateZygoteSpace(); // Make space findable to the heap, will also delete space when runtime is cleaned up Runtime::Current()->GetHeap()->AddSpace(space); // Succeeds, fits without adjusting the footprint limit. - ptr1 = space->AllocWithoutGrowth(1 * MB); + ptr1 = space->AllocWithoutGrowth(self, 1 * MB); EXPECT_TRUE(ptr1 != NULL); // Fails, requires a higher footprint limit. - ptr2 = space->AllocWithoutGrowth(8 * MB); + ptr2 = space->AllocWithoutGrowth(self, 8 * MB); EXPECT_TRUE(ptr2 == NULL); // Succeeds, adjusts the footprint. - ptr3 = space->AllocWithGrowth(2 * MB); + ptr3 = space->AllocWithGrowth(self, 2 * MB); EXPECT_TRUE(ptr3 != NULL); - space->Free(ptr3); + space->Free(self, ptr3); // Final clean up. free1 = space->AllocationSize(ptr1); - space->Free(ptr1); + space->Free(self, ptr1); EXPECT_LE(1U * MB, free1); } TEST_F(SpaceTest, AllocAndFree) { AllocSpace* space(AllocSpace::Create("test", 4 * MB, 16 * MB, 16 * MB, NULL)); ASSERT_TRUE(space != NULL); + Thread* self = Thread::Current(); // Make space findable to the heap, will also delete space when runtime is cleaned up Runtime::Current()->GetHeap()->AddSpace(space); // Succeeds, fits without adjusting the footprint limit. - Object* ptr1 = space->AllocWithoutGrowth(1 * MB); + Object* ptr1 = space->AllocWithoutGrowth(self, 1 * MB); EXPECT_TRUE(ptr1 != NULL); // Fails, requires a higher footprint limit. - Object* ptr2 = space->AllocWithoutGrowth(8 * MB); + Object* ptr2 = space->AllocWithoutGrowth(self, 8 * MB); EXPECT_TRUE(ptr2 == NULL); // Succeeds, adjusts the footprint. - Object* ptr3 = space->AllocWithGrowth(8 * MB); + Object* ptr3 = space->AllocWithGrowth(self, 8 * MB); EXPECT_TRUE(ptr3 != NULL); // Fails, requires a higher footprint limit. - Object* ptr4 = space->AllocWithoutGrowth(8 * MB); + Object* ptr4 = space->AllocWithoutGrowth(self, 8 * MB); EXPECT_TRUE(ptr4 == NULL); // Also fails, requires a higher allowed footprint. - Object* ptr5 = space->AllocWithGrowth(8 * MB); + Object* ptr5 = space->AllocWithGrowth(self, 8 * MB); EXPECT_TRUE(ptr5 == NULL); // Release some memory. size_t free3 = space->AllocationSize(ptr3); - space->Free(ptr3); + space->Free(self, ptr3); EXPECT_LE(8U * MB, free3); // Succeeds, now that memory has been freed. - void* ptr6 = space->AllocWithGrowth(9 * MB); + void* ptr6 = space->AllocWithGrowth(self, 9 * MB); EXPECT_TRUE(ptr6 != NULL); // Final clean up. size_t free1 = space->AllocationSize(ptr1); - space->Free(ptr1); + space->Free(self, ptr1); EXPECT_LE(1U * MB, free1); } @@ -189,28 +191,29 @@ TEST_F(SpaceTest, AllocAndFreeList) { // Make space findable to the heap, will also delete space when runtime is cleaned up Runtime::Current()->GetHeap()->AddSpace(space); + Thread* self = Thread::Current(); // Succeeds, fits without adjusting the max allowed footprint. Object* lots_of_objects[1024]; for (size_t i = 0; i < arraysize(lots_of_objects); i++) { - lots_of_objects[i] = space->AllocWithoutGrowth(16); + lots_of_objects[i] = space->AllocWithoutGrowth(self, 16); EXPECT_TRUE(lots_of_objects[i] != NULL); } // Release memory and check pointers are NULL - space->FreeList(arraysize(lots_of_objects), lots_of_objects); + space->FreeList(self, arraysize(lots_of_objects), lots_of_objects); for (size_t i = 0; i < arraysize(lots_of_objects); i++) { EXPECT_TRUE(lots_of_objects[i] == NULL); } // Succeeds, fits by adjusting the max allowed footprint. for (size_t i = 0; i < arraysize(lots_of_objects); i++) { - lots_of_objects[i] = space->AllocWithGrowth(1024); + lots_of_objects[i] = space->AllocWithGrowth(self, 1024); EXPECT_TRUE(lots_of_objects[i] != NULL); } // Release memory and check pointers are NULL - space->FreeList(arraysize(lots_of_objects), lots_of_objects); + space->FreeList(self, arraysize(lots_of_objects), lots_of_objects); for (size_t i = 0; i < arraysize(lots_of_objects); i++) { EXPECT_TRUE(lots_of_objects[i] == NULL); } @@ -252,6 +255,7 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(AllocSpace* space, intptr_t UniquePtr<Object*[]> lots_of_objects(new Object*[max_objects]); size_t last_object = 0; // last object for which allocation succeeded size_t amount_allocated = 0; // amount of space allocated + Thread* self = Thread::Current(); for (size_t i = 0; i < max_objects; i++) { size_t alloc_fails = 0; // number of failed allocations size_t max_fails = 30; // number of times we fail allocation before giving up @@ -267,9 +271,9 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(AllocSpace* space, intptr_t } Object* object; if (round <= 1) { - object = space->AllocWithoutGrowth(alloc_size); + object = space->AllocWithoutGrowth(self, alloc_size); } else { - object = space->AllocWithGrowth(alloc_size); + object = space->AllocWithGrowth(self, alloc_size); } footprint = mspace_footprint(mspace); EXPECT_GE(space->Size(), footprint); // invariant @@ -332,7 +336,7 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(AllocSpace* space, intptr_t } else { EXPECT_GE(allocation_size, 8u); } - space->Free(object); + space->Free(self, object); lots_of_objects.get()[i] = NULL; amount_allocated -= allocation_size; footprint = mspace_footprint(mspace); @@ -346,9 +350,9 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(AllocSpace* space, intptr_t Object* large_object; size_t three_quarters_space = (growth_limit / 2) + (growth_limit / 4); if (round <= 1) { - large_object = space->AllocWithoutGrowth(three_quarters_space); + large_object = space->AllocWithoutGrowth(self, three_quarters_space); } else { - large_object = space->AllocWithGrowth(three_quarters_space); + large_object = space->AllocWithGrowth(self, three_quarters_space); } EXPECT_TRUE(large_object != NULL); @@ -359,7 +363,7 @@ void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(AllocSpace* space, intptr_t EXPECT_LE(space->Size(), growth_limit); // Clean up - space->Free(large_object); + space->Free(self, large_object); // Sanity check footprint footprint = mspace_footprint(mspace); diff --git a/src/thread.cc b/src/thread.cc index ba8763c0e5..a63a5aa5b8 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -110,7 +110,9 @@ void* Thread::CreateCallback(void* arg) { return NULL; } { - MutexLock mu(*Locks::runtime_shutdown_lock_); + // TODO: pass self to MutexLock - requires self to equal Thread::Current(), which is only true + // after self->Init(). + MutexLock mu(NULL, *Locks::runtime_shutdown_lock_); // Check that if we got here we cannot be shutting down (as shutdown should never have started // while threads are being born). CHECK(!runtime->IsShuttingDown()); @@ -719,7 +721,6 @@ void Thread::DumpState(std::ostream& os, const Thread* thread, pid_t tid) { if (is_daemon) { os << " daemon"; } - MutexLock mu(self, *Locks::thread_suspend_count_lock_); os << " prio=" << priority << " tid=" << thread->GetThinLockId() << " " << thread->GetState() << "\n"; @@ -874,7 +875,7 @@ void Thread::ThreadExitCallback(void* arg) { void Thread::Startup() { { - MutexLock mu(*Locks::thread_suspend_count_lock_); // Keep GCC happy. + MutexLock mu(Thread::Current(), *Locks::thread_suspend_count_lock_); // Keep GCC happy. resume_cond_ = new ConditionVariable("Thread resumption condition variable"); } @@ -1166,7 +1167,7 @@ Object* Thread::DecodeJObject(jobject obj) { // Implements java.lang.Thread.interrupted. bool Thread::Interrupted() { - MutexLock mu(*wait_mutex_); + MutexLock mu(Thread::Current(), *wait_mutex_); bool interrupted = interrupted_; interrupted_ = false; return interrupted; @@ -1174,12 +1175,12 @@ bool Thread::Interrupted() { // Implements java.lang.Thread.isInterrupted. bool Thread::IsInterrupted() { - MutexLock mu(*wait_mutex_); + MutexLock mu(Thread::Current(), *wait_mutex_); return interrupted_; } void Thread::Interrupt() { - MutexLock mu(*wait_mutex_); + MutexLock mu(Thread::Current(), *wait_mutex_); if (interrupted_) { return; } @@ -1188,7 +1189,7 @@ void Thread::Interrupt() { } void Thread::Notify() { - MutexLock mu(*wait_mutex_); + MutexLock mu(Thread::Current(), *wait_mutex_); NotifyLocked(); } @@ -1252,11 +1253,12 @@ class BuildInternalStackTraceVisitor : public StackVisitor { // Allocate method trace with an extra slot that will hold the PC trace SirtRef<ObjectArray<Object> > method_trace(self_, - Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(depth + 1)); + Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(self_, + depth + 1)); if (method_trace.get() == NULL) { return false; } - IntArray* dex_pc_trace = IntArray::Alloc(depth); + IntArray* dex_pc_trace = IntArray::Alloc(self_, depth); if (dex_pc_trace == NULL) { return false; } @@ -1350,7 +1352,7 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job depth = std::min(depth, java_traces->GetLength()); } else { // Create java_trace array and place in local reference table - java_traces = class_linker->AllocStackTraceElementArray(depth); + java_traces = class_linker->AllocStackTraceElementArray(soa.Self(), depth); if (java_traces == NULL) { return NULL; } @@ -1374,19 +1376,23 @@ jobjectArray Thread::InternalStackTraceToStackTraceElementArray(JNIEnv* env, job CHECK(descriptor != NULL); std::string class_name(PrettyDescriptor(descriptor)); SirtRef<String> class_name_object(soa.Self(), - String::AllocFromModifiedUtf8(class_name.c_str())); + String::AllocFromModifiedUtf8(soa.Self(), + class_name.c_str())); if (class_name_object.get() == NULL) { return NULL; } const char* method_name = mh.GetName(); CHECK(method_name != NULL); - SirtRef<String> method_name_object(soa.Self(), String::AllocFromModifiedUtf8(method_name)); + SirtRef<String> method_name_object(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), + method_name)); if (method_name_object.get() == NULL) { return NULL; } const char* source_file = mh.GetDeclaringClassSourceFile(); - SirtRef<String> source_name_object(soa.Self(), String::AllocFromModifiedUtf8(source_file)); - StackTraceElement* obj = StackTraceElement::Alloc(class_name_object.get(), + SirtRef<String> source_name_object(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), + source_file)); + StackTraceElement* obj = StackTraceElement::Alloc(soa.Self(), + class_name_object.get(), method_name_object.get(), source_name_object.get(), line_number); @@ -1450,7 +1456,7 @@ void Thread::ThrowNewWrappedException(const char* exception_class_descriptor, co if (exception.get() != NULL) { ScopedObjectAccessUnchecked soa(env); Throwable* t = reinterpret_cast<Throwable*>(soa.Self()->DecodeJObject(exception.get())); - t->SetDetailMessage(String::AllocFromModifiedUtf8(msg)); + t->SetDetailMessage(String::AllocFromModifiedUtf8(soa.Self(), msg)); soa.Self()->SetException(t); } else { LOG(ERROR) << "Couldn't throw new " << descriptor << " because JNI AllocObject failed: " diff --git a/src/thread_list.cc b/src/thread_list.cc index 83f2658e9e..4030be6d6c 100644 --- a/src/thread_list.cc +++ b/src/thread_list.cc @@ -66,7 +66,7 @@ pid_t ThreadList::GetLockOwner() { void ThreadList::DumpForSigQuit(std::ostream& os) { { - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); DumpLocked(os); } DumpUnattachedThreads(os); @@ -91,13 +91,14 @@ void ThreadList::DumpUnattachedThreads(std::ostream& os) { dirent de; dirent* e; + Thread* self = Thread::Current(); while (!readdir_r(d, &de, &e) && e != NULL) { char* end; pid_t tid = strtol(de.d_name, &end, 10); if (!*end) { bool contains; { - MutexLock mu(*Locks::thread_list_lock_); + MutexLock mu(self, *Locks::thread_list_lock_); contains = Contains(tid); } if (!contains) { @@ -109,7 +110,7 @@ void ThreadList::DumpUnattachedThreads(std::ostream& os) { } void ThreadList::DumpLocked(std::ostream& os) { - Locks::thread_list_lock_->AssertHeld(); + Locks::thread_list_lock_->AssertHeld(Thread::Current()); os << "DALVIK THREADS (" << list_.size() << "):\n"; for (It it = list_.begin(), end = list_.end(); it != end; ++it) { (*it)->Dump(os); @@ -117,9 +118,9 @@ void ThreadList::DumpLocked(std::ostream& os) { } } -void ThreadList::AssertThreadsAreSuspended(Thread* ignore1, Thread* ignore2) { - MutexLock mu(*Locks::thread_list_lock_); - MutexLock mu2(*Locks::thread_suspend_count_lock_); +void ThreadList::AssertThreadsAreSuspended(Thread* self, Thread* ignore1, Thread* ignore2) { + MutexLock mu(self, *Locks::thread_list_lock_); + MutexLock mu2(self, *Locks::thread_suspend_count_lock_); for (It it = list_.begin(), end = list_.end(); it != end; ++it) { Thread* thread = *it; if (thread != ignore1 || thread == ignore2) { @@ -194,7 +195,7 @@ void ThreadList::SuspendAll() { #endif // Debug check that all threads are suspended. - AssertThreadsAreSuspended(self); + AssertThreadsAreSuspended(self, self); VLOG(threads) << *self << " SuspendAll complete"; } @@ -205,7 +206,7 @@ void ThreadList::ResumeAll() { VLOG(threads) << *self << " ResumeAll starting"; // Debug check that all threads are suspended. - AssertThreadsAreSuspended(self); + AssertThreadsAreSuspended(self, self); Locks::mutator_lock_->ExclusiveUnlock(self); { @@ -297,7 +298,7 @@ void ThreadList::SuspendAllForDebugger() { Locks::mutator_lock_->ExclusiveLock(self); Locks::mutator_lock_->ExclusiveUnlock(self); #endif - AssertThreadsAreSuspended(self, debug_thread); + AssertThreadsAreSuspended(self, self, debug_thread); VLOG(threads) << *self << " SuspendAll complete"; } @@ -422,7 +423,6 @@ void ThreadList::SuspendAllDaemonThreads() { bool all_suspended = true; for (It it = list_.begin(), end = list_.end(); it != end; ++it) { Thread* thread = *it; - MutexLock mu2(self, *Locks::thread_suspend_count_lock_); if (thread != self && thread->GetState() == kRunnable) { if (!have_complained) { LOG(WARNING) << "daemon thread not yet suspended: " << *thread; diff --git a/src/thread_list.h b/src/thread_list.h index b5546e37dd..94e987f1fd 100644 --- a/src/thread_list.h +++ b/src/thread_list.h @@ -105,7 +105,7 @@ class ThreadList { LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_); - void AssertThreadsAreSuspended(Thread* ignore1, Thread* ignore2 = NULL) + void AssertThreadsAreSuspended(Thread* self, Thread* ignore1, Thread* ignore2 = NULL) LOCKS_EXCLUDED(Locks::thread_list_lock_, Locks::thread_suspend_count_lock_); diff --git a/src/thread_x86.cc b/src/thread_x86.cc index 6a72286553..c8412357de 100644 --- a/src/thread_x86.cc +++ b/src/thread_x86.cc @@ -21,6 +21,7 @@ #include "asm_support.h" #include "macros.h" +#include "thread.h" #include "thread_list.h" #if defined(__APPLE__) @@ -41,7 +42,7 @@ namespace art { void Thread::InitCpu() { static Mutex modify_ldt_lock("modify_ldt lock"); - MutexLock mu(modify_ldt_lock); + MutexLock mu(Thread::Current(), modify_ldt_lock); const uintptr_t base = reinterpret_cast<uintptr_t>(this); const size_t limit = kPageSize; diff --git a/src/utils_test.cc b/src/utils_test.cc index 1fcb4b3cd0..f1983be08d 100644 --- a/src/utils_test.cc +++ b/src/utils_test.cc @@ -89,15 +89,15 @@ TEST_F(UtilsTest, PrettyTypeOf) { ScopedObjectAccess soa(Thread::Current()); EXPECT_EQ("null", PrettyTypeOf(NULL)); - SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8("")); + SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8(soa.Self(), "")); EXPECT_EQ("java.lang.String", PrettyTypeOf(s.get())); - SirtRef<ShortArray> a(soa.Self(), ShortArray::Alloc(2)); + SirtRef<ShortArray> a(soa.Self(), ShortArray::Alloc(soa.Self(), 2)); EXPECT_EQ("short[]", PrettyTypeOf(a.get())); Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); - Object* o = ObjectArray<String>::Alloc(c, 0); + Object* o = ObjectArray<String>::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.String[]", PrettyTypeOf(o)); EXPECT_EQ("java.lang.Class<java.lang.String[]>", PrettyTypeOf(o->GetClass())); } @@ -107,7 +107,7 @@ TEST_F(UtilsTest, PrettyClass) { EXPECT_EQ("null", PrettyClass(NULL)); Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); - Object* o = ObjectArray<String>::Alloc(c, 0); + Object* o = ObjectArray<String>::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.Class<java.lang.String[]>", PrettyClass(o->GetClass())); } @@ -116,7 +116,7 @@ TEST_F(UtilsTest, PrettyClassAndClassLoader) { EXPECT_EQ("null", PrettyClassAndClassLoader(NULL)); Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;"); ASSERT_TRUE(c != NULL); - Object* o = ObjectArray<String>::Alloc(c, 0); + Object* o = ObjectArray<String>::Alloc(soa.Self(), c, 0); EXPECT_EQ("java.lang.Class<java.lang.String[],null>", PrettyClassAndClassLoader(o->GetClass())); } diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc index dd9aa8b656..ad238b8310 100644 --- a/src/verifier/method_verifier.cc +++ b/src/verifier/method_verifier.cc @@ -3229,7 +3229,7 @@ void MethodVerifier::VerifyGcMap(const std::vector<uint8_t>& data) { void MethodVerifier::SetDexGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map) { { - MutexLock mu(*dex_gc_maps_lock_); + MutexLock mu(Thread::Current(), *dex_gc_maps_lock_); DexGcMapTable::iterator it = dex_gc_maps_->find(ref); if (it != dex_gc_maps_->end()) { delete it->second; @@ -3241,7 +3241,7 @@ void MethodVerifier::SetDexGcMap(Compiler::MethodReference ref, const std::vecto } const std::vector<uint8_t>* MethodVerifier::GetDexGcMap(Compiler::MethodReference ref) { - MutexLock mu(*dex_gc_maps_lock_); + MutexLock mu(Thread::Current(), *dex_gc_maps_lock_); DexGcMapTable::const_iterator it = dex_gc_maps_->find(ref); if (it == dex_gc_maps_->end()) { return NULL; @@ -3263,29 +3263,31 @@ MethodVerifier::InferredRegCategoryMapTable* MethodVerifier::inferred_reg_catego void MethodVerifier::Init() { dex_gc_maps_lock_ = new Mutex("verifier GC maps lock"); + Thread* self = Thread::Current(); { - MutexLock mu(*dex_gc_maps_lock_); + MutexLock mu(self, *dex_gc_maps_lock_); dex_gc_maps_ = new MethodVerifier::DexGcMapTable; } rejected_classes_lock_ = new Mutex("verifier rejected classes lock"); { - MutexLock mu(*rejected_classes_lock_); + MutexLock mu(self, *rejected_classes_lock_); rejected_classes_ = new MethodVerifier::RejectedClassesTable; } #if defined(ART_USE_LLVM_COMPILER) || defined(ART_USE_GREENLAND_COMPILER) inferred_reg_category_maps_lock_ = new Mutex("verifier GC maps lock"); { - MutexLock mu(*inferred_reg_category_maps_lock_); + MutexLock mu(self, *inferred_reg_category_maps_lock_); inferred_reg_category_maps_ = new MethodVerifier::InferredRegCategoryMapTable; } #endif } void MethodVerifier::Shutdown() { + Thread* self = Thread::Current(); { - MutexLock mu(*dex_gc_maps_lock_); + MutexLock mu(self, *dex_gc_maps_lock_); STLDeleteValues(dex_gc_maps_); delete dex_gc_maps_; dex_gc_maps_ = NULL; @@ -3294,7 +3296,7 @@ void MethodVerifier::Shutdown() { dex_gc_maps_lock_ = NULL; { - MutexLock mu(*rejected_classes_lock_); + MutexLock mu(self, *rejected_classes_lock_); delete rejected_classes_; rejected_classes_ = NULL; } @@ -3303,7 +3305,7 @@ void MethodVerifier::Shutdown() { #if defined(ART_USE_LLVM_COMPILER) || defined(ART_USE_GREENLAND_COMPILER) { - MutexLock mu(*inferred_reg_category_maps_lock_); + MutexLock mu(self, *inferred_reg_category_maps_lock_); STLDeleteValues(inferred_reg_category_maps_); delete inferred_reg_category_maps_; inferred_reg_category_maps_ = NULL; @@ -3315,14 +3317,14 @@ void MethodVerifier::Shutdown() { void MethodVerifier::AddRejectedClass(Compiler::ClassReference ref) { { - MutexLock mu(*rejected_classes_lock_); + MutexLock mu(Thread::Current(), *rejected_classes_lock_); rejected_classes_->insert(ref); } CHECK(IsClassRejected(ref)); } bool MethodVerifier::IsClassRejected(Compiler::ClassReference ref) { - MutexLock mu(*rejected_classes_lock_); + MutexLock mu(Thread::Current(), *rejected_classes_lock_); return (rejected_classes_->find(ref) != rejected_classes_->end()); } @@ -3374,7 +3376,7 @@ const greenland::InferredRegCategoryMap* MethodVerifier::GenerateInferredRegCate void MethodVerifier::SetInferredRegCategoryMap(Compiler::MethodReference ref, const InferredRegCategoryMap& inferred_reg_category_map) { { - MutexLock mu(*inferred_reg_category_maps_lock_); + MutexLock mu(Thread::Current(), *inferred_reg_category_maps_lock_); InferredRegCategoryMapTable::iterator it = inferred_reg_category_maps_->find(ref); if (it == inferred_reg_category_maps_->end()) { inferred_reg_category_maps_->Put(ref, &inferred_reg_category_map); @@ -3388,7 +3390,7 @@ void MethodVerifier::SetInferredRegCategoryMap(Compiler::MethodReference ref, const greenland::InferredRegCategoryMap* MethodVerifier::GetInferredRegCategoryMap(Compiler::MethodReference ref) { - MutexLock mu(*inferred_reg_category_maps_lock_); + MutexLock mu(Thread::Current(), *inferred_reg_category_maps_lock_); InferredRegCategoryMapTable::const_iterator it = inferred_reg_category_maps_->find(ref); |