Explicitly pass Thread::Current to MutexLock and Alloc.

Change-Id: I8b75bc0617915465f102815b32306aa7760dcae4
diff --git a/src/atomic.cc b/src/atomic.cc
index 2638b21..008aa87 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 @@
 }
 
 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 @@
 }
 
 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 @@
 }
 
 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 448ad6a..9ce641f 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -235,47 +235,48 @@
   // 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 @@
   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 @@
   // 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 @@
   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 @@
   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 @@
 }
 
 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 @@
 }
 
 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 @@
 
 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::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::FindOatFileFromOatLocation(const std::string& oat_location) {
-  MutexLock mu(dex_lock_);
+  MutexLock mu(Thread::Current(), dex_lock_);
   return FindOatFileFromOatLocationLocked(oat_location);
 }
 
@@ -980,7 +984,7 @@
 
   // 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 @@
 // 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::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 @@
   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 @@
   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 @@
   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 @@
   // 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 @@
     } 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 @@
   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 @@
     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 @@
   // 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 @@
     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 @@
   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 @@
 
   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 @@
 }
 
 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::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 @@
   // 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, SirtRef<DexCache>& dex_cache) {
-  MutexLock mu(dex_lock_);
+  MutexLock mu(Thread::Current(), dex_lock_);
   RegisterDexFileLocked(dex_file, dex_cache);
 }
 
@@ -1783,7 +1789,7 @@
 }
 
 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 @@
 }
 
 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 @@
     }
   }
   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 @@
     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 @@
 
 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 @@
 
 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 @@
 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 @@
                                      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 @@
   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 @@
   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::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 @@
   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 @@
     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 @@
     // 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 @@
       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 @@
     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 @@
     }
     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 @@
           }
         }
         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 @@
   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 @@
         }
         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 @@
     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 @@
   // 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::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::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 b07157a..38b402f 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -313,38 +313,38 @@
 
   // 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 @@
   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 @@
   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 @@
       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 d0b9e16..02512eb 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -773,7 +773,7 @@
 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, 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 @@
   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 10b4939..3899ce9 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 @@
     }
   }
 
-// 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() {
+  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 @@
 }
 
 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 @@
                             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 @@
                               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 @@
 
   // 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 @@
                  << " 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 @@
   }
 #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(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 @@
 
 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 @@
 
 #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 @@
 
 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 @@
 #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 @@
 }
 
 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 f65f684..85ae794 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -126,7 +126,7 @@
 
 
 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 3bb4ae5..d7e146a 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -230,17 +230,17 @@
 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 @@
   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 @@
   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 @@
 
   // 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 @@
     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 @@
   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 @@
   } 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 @@
         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 e28845f..c8e7381 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -55,19 +55,19 @@
       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 @@
       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 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 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 @@
 
   {
     // 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::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 @@
   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 @@
   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 @@
 }
 
 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 @@
   }
 
   // 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 @@
 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 @@
 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 @@
   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 @@
   };
 
   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 @@
 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 @@
   }
   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 @@
   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 @@
 
   // 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::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 @@
     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 @@
         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 @@
     // 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 @@
     }
 
     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 @@
     }
 
     ~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 @@
 }
 
 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 @@
   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 @@
      */
     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 @@
 
     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 @@
   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 @@
     // 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 @@
   } 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::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 @@
   Thread* self = Thread::Current();
   CHECK(self != NULL);
 
-  MutexLock mu(gAllocTrackerLock);
+  MutexLock mu(self, gAllocTrackerLock);
   if (recent_allocation_records_ == NULL) {
     return;
   }
@@ -3203,7 +3203,7 @@
 
 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 @@
     DumpRecentAllocations();
   }
 
-  MutexLock mu(gAllocTrackerLock);
+  Thread* self = Thread::Current();
+  MutexLock mu(self, gAllocTrackerLock);
 
   //
   // Part 1: generate string tables.
@@ -3428,7 +3429,7 @@
   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 6c0107c..b131e4c 100644
--- a/src/dex_cache_test.cc
+++ b/src/dex_cache_test.cc
@@ -29,7 +29,8 @@
 
 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 fa044c2..f7cb68d 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -277,7 +277,7 @@
 };
 
 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 @@
   }
 }
 
-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 @@
   // 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 @@
              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 @@
       // 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 @@
 
   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 @@
     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::VerifyHeap() {
-  ReaderMutexLock mu(*Locks::heap_bitmap_lock_);
+  ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
   GetLiveBitmap()->Walk(Heap::VerificationCallback, this);
 }
 
@@ -561,44 +560,38 @@
   }
 }
 
-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 @@
       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 @@
 
   // 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 @@
   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 @@
 };
 
 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 @@
     {
       // 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 5fe491f..7a96fd6 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -77,7 +77,7 @@
 };
 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 @@
   ~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 @@
  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 881a765..6db7416 100644
--- a/src/heap_test.cc
+++ b/src/heap_test.cc
@@ -39,9 +39,10 @@
 
     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 0cad709..125b19a 100644
--- a/src/hprof/hprof.cc
+++ b/src/hprof/hprof.cc
@@ -407,12 +407,13 @@
     // 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 @@
       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 @@
     // 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 c876329..fe12baf 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -192,7 +192,7 @@
     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 @@
   }
 
   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 @@
   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 @@
 
   // 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 @@
   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::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 971e42a..b5a05ec 100644
--- a/src/indirect_reference_table_test.cc
+++ b/src/indirect_reference_table_test.cc
@@ -49,13 +49,13 @@
 
   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 10dd7f0..5ad3958 100644
--- a/src/intern_table.cc
+++ b/src/intern_table.cc
@@ -25,19 +25,19 @@
 }
 
 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 @@
 }
 
 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::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 @@
 }
 
 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::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 @@
 }
 
 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 2833f6e..ee9165e 100644
--- a/src/intern_table_test.cc
+++ b/src/intern_table_test.cc
@@ -29,7 +29,7 @@
   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 @@
   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 @@
   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 @@
   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 @@
   {
     // 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 @@
   {
     // 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 @@
     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 19f10eb..2865f3a 100644
--- a/src/jdwp/jdwp_event.cc
+++ b/src/jdwp/jdwp_event.cc
@@ -141,7 +141,7 @@
  * 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 @@
  * 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 @@
  * 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 @@
     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 @@
    * 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 @@
 
   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 @@
   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 @@
   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 @@
   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 @@
   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 0c3a9a0..69fc2fc 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -47,7 +47,7 @@
  * 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 @@
  * 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 @@
  * 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 @@
  * 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 @@
    * 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 @@
       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 @@
 
   UnregisterAll();
   {
-    MutexLock mu(event_list_lock_);
+    MutexLock mu(Thread::Current(), event_list_lock_);
     CHECK(event_list_ == NULL);
   }
 
@@ -302,11 +302,8 @@
   }
 
   /* 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 @@
        */
       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 81941c0..16976d4 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -115,11 +115,8 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 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 @@
 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 @@
 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 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 @@
 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 75ab1f0..22438a0 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -195,7 +195,7 @@
   }
   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 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 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 @@
     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 @@
   }
 
   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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
 
   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 @@
       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 @@
 
     // 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 @@
   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 @@
     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 @@
   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 @@
   // 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 @@
 
   // 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 @@
   // 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 @@
 
   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 bc1be28..d94da1e 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -93,7 +93,7 @@
                        : 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 48785c5..5680ed0 100644
--- a/src/logging.cc
+++ b/src/logging.cc
@@ -105,7 +105,7 @@
 
   // 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 e9056f5..96223a9 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -378,7 +378,7 @@
   }
 
   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 @@
   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 @@
 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 @@
       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::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 @@
   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 @@
       ++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 @@
   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 @@
   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 @@
   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 c0484af..9890822 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -284,7 +284,7 @@
   {
     // 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 @@
     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 @@
   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 @@
      * 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 @@
     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 @@
     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 @@
     ThrowIllegalMonitorStateExceptionF("object not locked by thread before notifyAll()");
     return;
   }
-  monitor_lock_.AssertHeld();
+  monitor_lock_.AssertHeld(self);
   NotifyAllWithLock();
 }
 
@@ -872,10 +872,7 @@
 
 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 @@
     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() {
-  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 4a62728..4277d2c 100644
--- a/src/monitor.h
+++ b/src/monitor.h
@@ -115,7 +115,7 @@
   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 522f849..96e04ef 100644
--- a/src/mutex.cc
+++ b/src/mutex.cc
@@ -196,7 +196,7 @@
   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 @@
   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 @@
   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 32aeaf9..d51e2cc 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 @@
     }
   }
   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 @@
     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 @@
     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 @@
     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 7184e48..91b7b5f 100644
--- a/src/native/dalvik_system_VMRuntime.cc
+++ b/src/native/dalvik_system_VMRuntime.cc
@@ -54,11 +54,11 @@
 
   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 @@
   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 @@
   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 @@
 }
 #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 @@
 #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 @@
 
     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 c023b7e..488df80 100644
--- a/src/native/java_lang_Class.cc
+++ b/src/native/java_lang_Class.cc
@@ -199,7 +199,8 @@
     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 @@
     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 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 @@
     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 89019f7..a6ae49d 100644
--- a/src/native/java_lang_Object.cc
+++ b/src/native/java_lang_Object.cc
@@ -23,7 +23,7 @@
 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 edf55c3..cf475e2 100644
--- a/src/native/java_lang_Thread.cc
+++ b/src/native/java_lang_Thread.cc
@@ -34,7 +34,7 @@
 
 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 @@
 
   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 @@
     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_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 d3a57bf..863f9fc 100644
--- a/src/native/java_lang_reflect_Array.cc
+++ b/src/native/java_lang_reflect_Array.cc
@@ -29,7 +29,7 @@
                                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 @@
     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 44b459d..ed0d1f1 100644
--- a/src/native/java_lang_reflect_Constructor.cc
+++ b/src/native/java_lang_reflect_Constructor.cc
@@ -45,7 +45,7 @@
     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 63a277b..b1eb6e0 100644
--- a/src/native/java_lang_reflect_Method.cc
+++ b/src/native/java_lang_reflect_Method.cc
@@ -44,7 +44,7 @@
   }
   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 66c27e4..0ed964b 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 @@
   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 @@
   };
   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 @@
 
   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 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 7add255..4099ddb 100644
--- a/src/oat/runtime/arm/stub_arm.cc
+++ b/src/oat/runtime/arm/stub_arm.cc
@@ -82,7 +82,8 @@
 
   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 @@
   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 @@
   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 d545e4a..9691308 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -112,7 +112,8 @@
   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 @@
   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 @@
   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 fd7fb65..fb70285 100644
--- a/src/oat/runtime/support_alloc.cc
+++ b/src/oat/runtime/support_alloc.cc
@@ -37,7 +37,7 @@
                                         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 @@
                                                        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 4ff2e5f..3d0c1c8 100644
--- a/src/oat/runtime/support_proxy.cc
+++ b/src/oat/runtime/support_proxy.cc
@@ -104,7 +104,7 @@
   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 @@
   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 7941d15..cade99d 100644
--- a/src/oat/runtime/x86/stub_x86.cc
+++ b/src/oat/runtime/x86/stub_x86.cc
@@ -92,7 +92,8 @@
 
   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 @@
   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 @@
   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 7e14199..01b2042 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -575,11 +575,12 @@
     // 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 8582a21..e8381db 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -47,7 +47,7 @@
   return down_cast<String*>(this);
 }
 
-Object* Object::Clone() {
+Object* Object::Clone(Thread* self) {
   Class* c = GetClass();
   DCHECK(!c->IsClassClass());
 
@@ -55,7 +55,7 @@
   // 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 @@
   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 @@
     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 @@
       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 @@
   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 @@
   // 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 @@
   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 @@
 }
 
 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 @@
   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 @@
   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 @@
   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 @@
   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 5fccb04..baa7313 100644
--- a/src/object.h
+++ b/src/object.h
@@ -177,7 +177,7 @@
 
   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 @@
  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 @@
 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 @@
                    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 @@
 };
 
 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 @@
 }
 
 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 @@
   }
 
   // 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 @@
  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 @@
 
   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 @@
         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 f28c20b..9ad0534 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -44,7 +44,8 @@
       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, 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, 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 @@
   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 @@
   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, 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 @@
   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 @@
   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, 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 @@
   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 @@
   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, 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, 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 1d66c8f..297035f 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 @@
     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 @@
       }
       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 b35110d..c400f83 100644
--- a/src/reference_table_test.cc
+++ b/src/reference_table_test.cc
@@ -25,7 +25,7 @@
 
 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 @@
   }
 
   // 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 7d73ae2..c793d2c 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -234,11 +234,10 @@
     LOG(FATAL) << static_cast<int>(src_class);
   }
 
-  if (kIsDebugBuild) {
-    MutexLock mu(*Locks::thread_suspend_count_lock_);
-    CHECK_EQ(Thread::Current()->GetState(), kRunnable);
-  }
   ScopedObjectAccessUnchecked soa(Thread::Current());
+  if (kIsDebugBuild) {
+    CHECK_EQ(soa.Self()->GetState(), kRunnable);
+  }
   JValue args[1] = { value };
   soa.DecodeMethod(m)->Invoke(soa.Self(), NULL, args, &value);
 }
diff --git a/src/runtime.cc b/src/runtime.cc
index d10c351..3444f78 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -187,7 +187,7 @@
 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 @@
   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 @@
   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 @@
 
 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::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 85eeb8f..01c08d3 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 @@
 };
 
 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 4af6fe5..54baa42 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -100,19 +100,19 @@
   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 @@
       }
     }
     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 eff50b3..0d24e48 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -78,7 +78,7 @@
     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 @@
 // 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 @@
       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 9da41e0..32c3685 100644
--- a/src/scoped_thread_state_change.h
+++ b/src/scoped_thread_state_change.h
@@ -35,7 +35,7 @@
     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 @@
   ~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 8376bb6..b6f6a41 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -85,12 +85,12 @@
 }
 
 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 58476ad..c1f4384 100644
--- a/src/space.cc
+++ b/src/space.cc
@@ -208,13 +208,13 @@
   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 @@
   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 @@
   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 @@
 }
 
 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 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::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 @@
   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 @@
   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 @@
 }
 
 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 @@
 }
 
 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::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::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 @@
   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 @@
   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 12682f9..af6ab3b 100644
--- a/src/space.h
+++ b/src/space.h
@@ -241,15 +241,15 @@
                             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 @@
 
   // 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 @@
 
   // 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 @@
   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 @@
   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 e9c45c4..0319147 100644
--- a/src/space_test.cc
+++ b/src/space_test.cc
@@ -80,106 +80,108 @@
 
     // 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 @@
 
   // 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 @@
   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 @@
       }
       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 @@
       } 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 @@
   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 @@
   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 ba8763c..a63a5aa 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -110,7 +110,9 @@
     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 @@
     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::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 @@
 
 // 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 @@
 
 // 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::Notify() {
-  MutexLock mu(*wait_mutex_);
+  MutexLock mu(Thread::Current(), *wait_mutex_);
   NotifyLocked();
 }
 
@@ -1252,11 +1253,12 @@
     // 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 @@
     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 @@
     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 @@
     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 83f2658..4030be6 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -66,7 +66,7 @@
 
 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 @@
 
   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::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::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 @@
 #endif
 
   // Debug check that all threads are suspended.
-  AssertThreadsAreSuspended(self);
+  AssertThreadsAreSuspended(self, self);
 
   VLOG(threads) << *self << " SuspendAll complete";
 }
@@ -205,7 +206,7 @@
   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 @@
   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 @@
     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 b5546e3..94e987f 100644
--- a/src/thread_list.h
+++ b/src/thread_list.h
@@ -105,7 +105,7 @@
       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 6a72286..c841235 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 @@
 
 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 1fcb4b3..f1983be 100644
--- a/src/utils_test.cc
+++ b/src/utils_test.cc
@@ -89,15 +89,15 @@
   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 @@
   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 @@
   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 dd9aa8b..ad238b8 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -3229,7 +3229,7 @@
 
 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 @@
 }
 
 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 @@
 
 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 @@
   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 @@
 
 #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::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 @@
 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 @@
 
 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);