Make PopSirt inlinable, pass self to SirtRef.

Change-Id: Ieb91526b1cb1f8644ceb3c5b99649f658f43bbc1
diff --git a/src/class_linker.cc b/src/class_linker.cc
index fdcbf20..448ad6a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -47,6 +47,7 @@
 #endif
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
 #include "space.h"
 #include "space_bitmap.h"
 #include "stack_indirect_reference_table.h"
@@ -232,42 +233,43 @@
   CHECK(!init_done_);
 
   // java_lang_Class comes first, it's needed for AllocClass
+  Thread* self = Thread::Current();
   Heap* heap = Runtime::Current()->GetHeap();
-  SirtRef<Class> java_lang_Class(down_cast<Class*>(heap->AllocObject(NULL, sizeof(ClassClass))));
+  SirtRef<Class> java_lang_Class(self, down_cast<Class*>(heap->AllocObject(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(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> class_array_class(self, AllocClass(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(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> java_lang_Object(self, AllocClass(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(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> object_array_class(self, AllocClass(java_lang_Class.get(), sizeof(Class)));
   object_array_class->SetComponentType(java_lang_Object.get());
 
   // Object[][] needed for iftables.
-  SirtRef<Class> object_array_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> object_array_array_class(self, AllocClass(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(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> char_class(self, AllocClass(java_lang_Class.get(), sizeof(Class)));
 
   // Setup the char[] class to be used for String.
-  SirtRef<Class> char_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> char_array_class(self, AllocClass(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(AllocClass(java_lang_Class.get(), sizeof(StringClass)));
+  SirtRef<Class> java_lang_String(self, AllocClass(java_lang_Class.get(), sizeof(StringClass)));
   String::SetClass(java_lang_String.get());
   java_lang_String->SetObjectSize(sizeof(String));
   java_lang_String->SetStatus(Class::kStatusResolved);
@@ -297,7 +299,7 @@
   array_iftable_ = AllocIfTable(2);
 
   // Create int array type for AllocDexCache (done in AppendToBootClassPath).
-  SirtRef<Class> int_array_class(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> int_array_class(self, AllocClass(java_lang_Class.get(), sizeof(Class)));
   int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
   IntArray::SetArrayClass(int_array_class.get());
   SetClassRoot(kIntArrayClass, int_array_class.get());
@@ -305,33 +307,33 @@
   // 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(AllocClass(java_lang_Class.get(), sizeof(DexCacheClass)));
+  SirtRef<Class> java_lang_DexCache(self, AllocClass(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(AllocClass(java_lang_Class.get(),
+  SirtRef<Class> java_lang_reflect_Constructor(self, AllocClass(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(AllocClass(java_lang_Class.get(), sizeof(FieldClass)));
+  SirtRef<Class> java_lang_reflect_Field(self, AllocClass(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(AllocClass(java_lang_Class.get(), sizeof(MethodClass)));
+  SirtRef<Class> java_lang_reflect_Method(self, AllocClass(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(AllocClass(java_lang_Class.get(),
+  SirtRef<Class> java_lang_reflect_AbstractMethod(self, AllocClass(java_lang_Class.get(),
                                                              sizeof(MethodClass)));
   CHECK(java_lang_reflect_AbstractMethod.get() != NULL);
   java_lang_reflect_AbstractMethod->SetObjectSize(sizeof(AbstractMethod));
@@ -340,15 +342,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(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> object_array_string(self, AllocClass(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(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> object_array_field(self, AllocClass(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(AllocClass(java_lang_Class.get(), sizeof(Class)));
+  SirtRef<Class> object_array_abstract_method(self, AllocClass(java_lang_Class.get(), sizeof(Class)));
   object_array_abstract_method->SetComponentType(java_lang_reflect_AbstractMethod.get());
   SetClassRoot(kJavaLangReflectAbstractMethodArrayClass, object_array_abstract_method.get());
 
@@ -960,8 +962,9 @@
 
   CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(),
            static_cast<uint32_t>(dex_caches->GetLength()));
+  Thread* self = Thread::Current();
   for (int i = 0; i < dex_caches->GetLength(); i++) {
-    SirtRef<DexCache> dex_cache(dex_caches->Get(i));
+    SirtRef<DexCache> dex_cache(self, dex_caches->Get(i));
     const std::string& dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8());
     const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file_location);
     const DexFile* dex_file = oat_dex_file->OpenDexFile();
@@ -1110,32 +1113,35 @@
 DexCache* ClassLinker::AllocDexCache(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())));
   if (dex_cache.get() == NULL) {
     return NULL;
   }
-  SirtRef<String> location(intern_table_->InternStrong(dex_file.GetLocation().c_str()));
+  SirtRef<String> location(self, intern_table_->InternStrong(dex_file.GetLocation().c_str()));
   if (location.get() == NULL) {
     return NULL;
   }
-  SirtRef<ObjectArray<String> > strings(AllocStringArray(dex_file.NumStringIds()));
+  SirtRef<ObjectArray<String> > strings(self, AllocStringArray(dex_file.NumStringIds()));
   if (strings.get() == NULL) {
     return NULL;
   }
-  SirtRef<ObjectArray<Class> > types(AllocClassArray(dex_file.NumTypeIds()));
+  SirtRef<ObjectArray<Class> > types(self, AllocClassArray(dex_file.NumTypeIds()));
   if (types.get() == NULL) {
     return NULL;
   }
-  SirtRef<ObjectArray<AbstractMethod> > methods(AllocMethodArray(dex_file.NumMethodIds()));
+  SirtRef<ObjectArray<AbstractMethod> > methods(self, AllocMethodArray(dex_file.NumMethodIds()));
   if (methods.get() == NULL) {
     return NULL;
   }
-  SirtRef<ObjectArray<Field> > fields(AllocFieldArray(dex_file.NumFieldIds()));
+  SirtRef<ObjectArray<Field> > fields(self, AllocFieldArray(dex_file.NumFieldIds()));
   if (fields.get() == NULL) {
     return NULL;
   }
-  SirtRef<ObjectArray<StaticStorageBase> > initialized_static_storage(AllocObjectArray<StaticStorageBase>(dex_file.NumTypeIds()));
+  SirtRef<ObjectArray<StaticStorageBase> >
+      initialized_static_storage(self, AllocObjectArray<StaticStorageBase>(dex_file.NumTypeIds()));
   if (initialized_static_storage.get() == NULL) {
     return NULL;
   }
@@ -1152,8 +1158,9 @@
 
 InterfaceEntry* ClassLinker::AllocInterfaceEntry(Class* interface) {
   DCHECK(interface->IsInterface());
-  SirtRef<ObjectArray<Object> > array(AllocObjectArray<Object>(InterfaceEntry::LengthAsArray()));
-  SirtRef<InterfaceEntry> interface_entry(down_cast<InterfaceEntry*>(array.get()));
+  Thread* self = Thread::Current();
+  SirtRef<ObjectArray<Object> > array(self, AllocObjectArray<Object>(InterfaceEntry::LengthAsArray()));
+  SirtRef<InterfaceEntry> interface_entry(self, down_cast<InterfaceEntry*>(array.get()));
   interface_entry->SetInterface(interface);
   return interface_entry.get();
 }
@@ -1161,7 +1168,8 @@
 Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) {
   DCHECK_GE(class_size, sizeof(Class));
   Heap* heap = Runtime::Current()->GetHeap();
-  SirtRef<Class> klass(heap->AllocObject(java_lang_Class, class_size)->AsClass());
+  SirtRef<Class> klass(Thread::Current(),
+                       heap->AllocObject(java_lang_Class, class_size)->AsClass());
   klass->SetPrimitiveType(Primitive::kPrimNot);  // default to not being primitive
   klass->SetClassSize(class_size);
   return klass.get();
@@ -1195,7 +1203,7 @@
   // Wait for the class if it has not already been linked.
   Thread* self = Thread::Current();
   if (!klass->IsResolved() && !klass->IsErroneous()) {
-    ObjectLock lock(klass);
+    ObjectLock lock(self, klass);
     // Check for circular dependencies between classes.
     if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
       self->ThrowNewException("Ljava/lang/ClassCircularityError;",
@@ -1311,7 +1319,8 @@
                                 ClassLoader* class_loader,
                                 const DexFile& dex_file,
                                 const DexFile::ClassDef& dex_class_def) {
-  SirtRef<Class> klass(NULL);
+  Thread* self = Thread::Current();
+  SirtRef<Class> klass(self, NULL);
   // Load the class from the dex file.
   if (!init_done_) {
     // finish up init of hand crafted class_roots_
@@ -1340,15 +1349,14 @@
   klass->SetDexCache(FindDexCache(dex_file));
   LoadClass(dex_file, dex_class_def, klass, class_loader);
   // Check for a pending exception during load
-  Thread* self = Thread::Current();
   if (self->IsExceptionPending()) {
     klass->SetStatus(Class::kStatusError);
     return NULL;
   }
-  ObjectLock lock(klass.get());
+  ObjectLock lock(self, klass.get());
   klass->SetClinitThreadId(self->GetTid());
   // Add the newly loaded class to the loaded classes table.
-  SirtRef<Class> existing(InsertClass(descriptor, klass.get(), false));
+  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());
@@ -1586,13 +1594,14 @@
   if (it.NumInstanceFields() != 0) {
     klass->SetIFields(AllocObjectArray<Field>(it.NumInstanceFields()));
   }
+  Thread* self = Thread::Current();
   for (size_t i = 0; it.HasNextStaticField(); i++, it.Next()) {
-    SirtRef<Field> sfield(AllocField());
+    SirtRef<Field> sfield(self, AllocField());
     klass->SetStaticField(i, sfield.get());
     LoadField(dex_file, it, klass, sfield);
   }
   for (size_t i = 0; it.HasNextInstanceField(); i++, it.Next()) {
-    SirtRef<Field> ifield(AllocField());
+    SirtRef<Field> ifield(self, AllocField());
     klass->SetInstanceField(i, ifield.get());
     LoadField(dex_file, it, klass, ifield);
   }
@@ -1613,7 +1622,7 @@
   }
   size_t class_def_method_index = 0;
   for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
-    SirtRef<AbstractMethod> method(LoadMethod(dex_file, it, klass));
+    SirtRef<AbstractMethod> method(self, LoadMethod(dex_file, it, klass));
     klass->SetDirectMethod(i, method.get());
     if (oat_class.get() != NULL) {
       LinkCode(method, oat_class.get(), class_def_method_index);
@@ -1622,7 +1631,7 @@
     class_def_method_index++;
   }
   for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
-    SirtRef<AbstractMethod> method(LoadMethod(dex_file, it, klass));
+    SirtRef<AbstractMethod> method(self, LoadMethod(dex_file, it, klass));
     klass->SetVirtualMethod(i, method.get());
     DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
     if (oat_class.get() != NULL) {
@@ -1704,7 +1713,7 @@
 }
 
 void ClassLinker::AppendToBootClassPath(const DexFile& dex_file) {
-  SirtRef<DexCache> dex_cache(AllocDexCache(dex_file));
+  SirtRef<DexCache> dex_cache(Thread::Current(), AllocDexCache(dex_file));
   AppendToBootClassPath(dex_file, dex_cache);
 }
 
@@ -1738,8 +1747,9 @@
 }
 
 void ClassLinker::RegisterDexFile(const DexFile& dex_file) {
+  Thread* self = Thread::Current();
   {
-    MutexLock mu(dex_lock_);
+    MutexLock mu(self, dex_lock_);
     if (IsDexFileRegisteredLocked(dex_file)) {
       return;
     }
@@ -1747,9 +1757,9 @@
   // 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(AllocDexCache(dex_file));
+  SirtRef<DexCache> dex_cache(self, AllocDexCache(dex_file));
   {
-    MutexLock mu(dex_lock_);
+    MutexLock mu(self, dex_lock_);
     if (IsDexFileRegisteredLocked(dex_file)) {
       return;
     }
@@ -1793,7 +1803,8 @@
 
 Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class, Primitive::Type type) {
   CHECK(primitive_class != NULL);
-  ObjectLock lock(primitive_class);  // Must hold lock on object when initializing.
+  // Must hold lock on object when initializing.
+  ObjectLock lock(Thread::Current(), primitive_class);
   primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
   primitive_class->SetPrimitiveType(type);
   primitive_class->SetStatus(Class::kStatusInitialized);
@@ -1857,8 +1868,8 @@
   //
   // Array classes are simple enough that we don't need to do a full
   // link step.
-
-  SirtRef<Class> new_class(NULL);
+  Thread* self = Thread::Current();
+  SirtRef<Class> new_class(self, NULL);
   if (!init_done_) {
     // Classes that were hand created, ie not by FindSystemClass
     if (descriptor == "[Ljava/lang/Class;") {
@@ -1886,7 +1897,7 @@
     }
     new_class->SetComponentType(component_type);
   }
-  ObjectLock lock(new_class.get());  // Must hold lock on object when initializing.
+  ObjectLock lock(self, new_class.get());  // Must hold lock on object when initializing.
   DCHECK(new_class->GetComponentType() != NULL);
   Class* java_lang_Object = GetClassRoot(kJavaLangObject);
   new_class->SetSuperClass(java_lang_Object);
@@ -2074,7 +2085,8 @@
 
 void ClassLinker::VerifyClass(Class* klass) {
   // TODO: assert that the monitor on the Class is held
-  ObjectLock lock(klass);
+  Thread* self = Thread::Current();
+  ObjectLock lock(self, klass);
 
   // Don't attempt to re-verify if already sufficiently verified.
   if (klass->IsVerified() ||
@@ -2102,7 +2114,7 @@
   std::string error_msg;
   if (super != NULL) {
     // Acquire lock to prevent races on verifying the super class.
-    ObjectLock lock(super);
+    ObjectLock lock(self, super);
 
     if (!super->IsVerified() && !super->IsErroneous()) {
       Runtime::Current()->GetClassLinker()->VerifyClass(super);
@@ -2113,8 +2125,7 @@
       error_msg += " that attempts to sub-class erroneous class ";
       error_msg += PrettyDescriptor(super);
       LOG(ERROR) << error_msg  << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
-      Thread* self = Thread::Current();
-      SirtRef<Throwable> cause(self->GetException());
+      SirtRef<Throwable> cause(self, self->GetException());
       if (cause.get() != NULL) {
         self->ClearException();
       }
@@ -2151,7 +2162,7 @@
           << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
           << " because: " << error_msg;
     }
-    Thread::Current()->AssertNoPendingException();
+    self->AssertNoPendingException();
     // Make sure all classes referenced by catch blocks are resolved.
     ResolveClassExceptionHandlerTypes(dex_file, klass);
     if (verifier_failure == verifier::MethodVerifier::kNoFailure) {
@@ -2171,7 +2182,6 @@
     LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(klass)
         << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
         << " because: " << error_msg;
-    Thread* self = Thread::Current();
     self->AssertNoPendingException();
     self->ThrowNewException("Ljava/lang/VerifyError;", error_msg.c_str());
     klass->SetStatus(Class::kStatusError);
@@ -2284,7 +2294,8 @@
 Class* ClassLinker::CreateProxyClass(String* name, ObjectArray<Class>* interfaces,
                                      ClassLoader* loader, ObjectArray<AbstractMethod>* methods,
                                      ObjectArray<ObjectArray<Class> >* throws) {
-  SirtRef<Class> klass(AllocClass(GetClassRoot(kJavaLangClass), sizeof(SynthesizedProxyClass)));
+  Thread* self = Thread::Current();
+  SirtRef<Class> klass(self, AllocClass(GetClassRoot(kJavaLangClass), sizeof(SynthesizedProxyClass)));
   CHECK(klass.get() != NULL);
   DCHECK(klass->GetClass() != NULL);
   klass->SetObjectSize(sizeof(Proxy));
@@ -2303,13 +2314,13 @@
   klass->SetSFields(AllocObjectArray<Field>(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(AllocField());
+  SirtRef<Field> interfaces_sfield(self, AllocField());
   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(AllocField());
+  SirtRef<Field> throws_sfield(self, AllocField());
   klass->SetStaticField(1, throws_sfield.get());
   throws_sfield->SetDexFieldIndex(1);
   throws_sfield->SetDeclaringClass(klass.get());
@@ -2323,7 +2334,7 @@
   size_t num_virtual_methods = methods->GetLength();
   klass->SetVirtualMethods(AllocObjectArray<AbstractMethod>(num_virtual_methods));
   for (size_t i = 0; i < num_virtual_methods; ++i) {
-    SirtRef<AbstractMethod> prototype(methods->Get(i));
+    SirtRef<AbstractMethod> prototype(self, methods->Get(i));
     klass->SetVirtualMethod(i, CreateProxyMethod(klass, prototype));
   }
 
@@ -2337,7 +2348,7 @@
     return NULL;
   }
   {
-    ObjectLock lock(klass.get());  // Must hold lock on object when initializing.
+    ObjectLock lock(self, klass.get());  // Must hold lock on object when initializing.
     interfaces_sfield->SetObject(NULL, interfaces);
     throws_sfield->SetObject(NULL, throws);
     klass->SetStatus(Class::kStatusInitialized);
@@ -2348,7 +2359,7 @@
     CHECK(klass->GetIFields() == NULL);
     CheckProxyConstructor(klass->GetDirectMethod(0));
     for (size_t i = 0; i < num_virtual_methods; ++i) {
-      SirtRef<AbstractMethod> prototype(methods->Get(i));
+      SirtRef<AbstractMethod> prototype(self, methods->Get(i));
       CheckProxyMethod(klass->GetVirtualMethod(i), prototype);
     }
 
@@ -2483,7 +2494,7 @@
   AbstractMethod* clinit = NULL;
   {
     // see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
-    ObjectLock lock(klass);
+    ObjectLock lock(self, klass);
 
     if (klass->GetStatus() == Class::kStatusInitialized) {
       return true;
@@ -2555,7 +2566,7 @@
       CHECK(klass->IsErroneous());
     }
     // Signal to any waiting threads that saw this class as initializing.
-    ObjectLock lock(klass);
+    ObjectLock lock(self, klass);
     lock.NotifyAll();
     return false;
   }
@@ -2572,7 +2583,7 @@
 
   bool success = true;
   {
-    ObjectLock lock(klass);
+    ObjectLock lock(self, klass);
 
     if (self->IsExceptionPending()) {
       WrapExceptionInInitializer();
@@ -2739,7 +2750,8 @@
     Class* super_class = klass->GetSuperClass();
     if (!super_class->IsInitialized()) {
       CHECK(!super_class->IsInterface());
-      ObjectLock lock(klass);  // Must hold lock on object when initializing and setting status.
+      // Must hold lock on object when initializing and setting status.
+      ObjectLock lock(Thread::Current(), klass);
       bool super_initialized = InitializeClass(super_class, can_run_clinit, can_init_fields);
       // TODO: check for a pending exception
       if (!super_initialized) {
@@ -2961,12 +2973,14 @@
 }
 
 bool ClassLinker::LinkVirtualMethods(SirtRef<Class>& klass) {
+  Thread* self = Thread::Current();
   if (klass->HasSuperClass()) {
     uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->GetVTable()->GetLength();
     size_t actual_count = klass->GetSuperClass()->GetVTable()->GetLength();
     CHECK_LE(actual_count, max_count);
     // TODO: do not assign to the vtable field until it is fully constructed.
-    SirtRef<ObjectArray<AbstractMethod> > vtable(klass->GetSuperClass()->GetVTable()->CopyOf(max_count));
+    SirtRef<ObjectArray<AbstractMethod> >
+        vtable(self, klass->GetSuperClass()->GetVTable()->CopyOf(max_count));
     // See if any of our virtual methods override the superclass.
     MethodHelper local_mh(NULL, this);
     MethodHelper super_mh(NULL, this);
@@ -3019,7 +3033,8 @@
       ThrowClassFormatError("Too many methods: %d", num_virtual_methods);
       return false;
     }
-    SirtRef<ObjectArray<AbstractMethod> > vtable(AllocObjectArray<AbstractMethod>(num_virtual_methods));
+    SirtRef<ObjectArray<AbstractMethod> >
+        vtable(self, AllocObjectArray<AbstractMethod>(num_virtual_methods));
     for (size_t i = 0; i < num_virtual_methods; ++i) {
       AbstractMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i);
       vtable->Set(i, virtual_method);
@@ -3051,7 +3066,8 @@
     // DCHECK(klass->GetIfTable() == NULL);
     return true;
   }
-  SirtRef<ObjectArray<InterfaceEntry> > iftable(AllocIfTable(ifcount));
+  Thread* self = Thread::Current();
+  SirtRef<ObjectArray<InterfaceEntry> > iftable(self, AllocIfTable(ifcount));
   if (super_ifcount != 0) {
     ObjectArray<InterfaceEntry>* super_iftable = klass->GetSuperClass()->GetIfTable();
     for (size_t i = 0; i < super_ifcount; i++) {
@@ -3066,7 +3082,6 @@
     DCHECK(interface != NULL);
     if (!interface->IsInterface()) {
       ClassHelper ih(interface);
-      Thread* self = Thread::Current();
       self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
           "Class %s implements non-interface class %s",
           PrettyDescriptor(klass.get()).c_str(),
@@ -3150,7 +3165,7 @@
         }
       }
       if (k < 0) {
-        SirtRef<AbstractMethod> miranda_method(NULL);
+        SirtRef<AbstractMethod> miranda_method(self, NULL);
         for (size_t mir = 0; mir < miranda_list.size(); mir++) {
           AbstractMethod* mir_method = miranda_list[mir];
           vtable_mh.ChangeMethod(mir_method);
@@ -3175,7 +3190,7 @@
                              ? AllocObjectArray<AbstractMethod>(new_method_count)
                              : klass->GetVirtualMethods()->CopyOf(new_method_count));
 
-    SirtRef<ObjectArray<AbstractMethod> > vtable(klass->GetVTableDuringLinking());
+    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();
diff --git a/src/class_linker.h b/src/class_linker.h
index d75e1b2..b07157a 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -30,7 +30,6 @@
 #include "oat_file.h"
 #include "object.h"
 #include "safe_map.h"
-#include "stack_indirect_reference_table.h"
 
 namespace art {
 
@@ -38,12 +37,13 @@
 class ImageSpace;
 class InternTable;
 class ObjectLock;
+template<class T> class SirtRef;
 
 typedef bool (ClassVisitor)(Class* c, void* arg);
 
 class ClassLinker {
  public:
-  // Creates the class linker by boot strapping from dex files.
+  // Creates the class linker by bootstrapping from dex files.
   static ClassLinker* CreateFromCompiler(const std::vector<const DexFile*>& boot_class_path,
                                          InternTable* intern_table)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 106598e..d0b9e16 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -24,6 +24,7 @@
 #include "dex_file.h"
 #include "heap.h"
 #include "runtime_support.h"
+#include "sirt_ref.h"
 
 namespace art {
 
@@ -654,7 +655,7 @@
 
 TEST_F(ClassLinkerTest, FindClassNested) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(LoadDex("Nested")));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(LoadDex("Nested")));
 
   Class* outer = class_linker_->FindClass("LNested;", class_loader.get());
   ASSERT_TRUE(outer != NULL);
@@ -718,7 +719,7 @@
   EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
   EXPECT_EQ(0U, kh.NumDirectInterfaces());
 
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(LoadDex("MyClass")));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(LoadDex("MyClass")));
   AssertNonExistentClass("LMyClass;");
   Class* MyClass = class_linker_->FindClass("LMyClass;", class_loader.get());
   kh.ChangeClass(MyClass);
@@ -785,27 +786,27 @@
 
 TEST_F(ClassLinkerTest, ValidatePrimitiveArrayElementsOffset) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<LongArray> long_array(LongArray::Alloc(0));
+  SirtRef<LongArray> long_array(soa.Self(), LongArray::Alloc(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(DoubleArray::Alloc(0));
+  SirtRef<DoubleArray> double_array(soa.Self(), DoubleArray::Alloc(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(IntArray::Alloc(0));
+  SirtRef<IntArray> int_array(soa.Self(), IntArray::Alloc(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(CharArray::Alloc(0));
+  SirtRef<CharArray> char_array(soa.Self(), CharArray::Alloc(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(ShortArray::Alloc(0));
+  SirtRef<ShortArray> short_array(soa.Self(), ShortArray::Alloc(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
@@ -846,8 +847,8 @@
 
 TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<ClassLoader> class_loader_1(soa.Decode<ClassLoader*>(LoadDex("MyClass")));
-  SirtRef<ClassLoader> class_loader_2(soa.Decode<ClassLoader*>(LoadDex("MyClass")));
+  SirtRef<ClassLoader> class_loader_1(soa.Self(), soa.Decode<ClassLoader*>(LoadDex("MyClass")));
+  SirtRef<ClassLoader> class_loader_2(soa.Self(), soa.Decode<ClassLoader*>(LoadDex("MyClass")));
   Class* MyClass_1 = class_linker_->FindClass("LMyClass;", class_loader_1.get());
   Class* MyClass_2 = class_linker_->FindClass("LMyClass;", class_loader_2.get());
   EXPECT_TRUE(MyClass_1 != NULL);
@@ -857,7 +858,7 @@
 
 TEST_F(ClassLinkerTest, StaticFields) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(LoadDex("Statics")));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(LoadDex("Statics")));
   Class* statics = class_linker_->FindClass("LStatics;", class_loader.get());
   class_linker_->EnsureInitialized(statics, true, true);
 
@@ -939,7 +940,7 @@
 
 TEST_F(ClassLinkerTest, Interfaces) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(LoadDex("Interfaces")));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(LoadDex("Interfaces")));
   Class* I = class_linker_->FindClass("LInterfaces$I;", class_loader.get());
   Class* J = class_linker_->FindClass("LInterfaces$J;", class_loader.get());
   Class* K = class_linker_->FindClass("LInterfaces$K;", class_loader.get());
@@ -999,7 +1000,7 @@
 
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("StaticsFromCode");
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(jclass_loader));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
   const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(jclass_loader)[0];
   CHECK(dex_file != NULL);
 
diff --git a/src/compiler.cc b/src/compiler.cc
index edadc12..10b4939 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -1271,8 +1271,9 @@
   ClassLoader* class_loader = soa.Decode<ClassLoader*>(context->GetClassLoader());
   const char* descriptor = context->GetDexFile()->GetClassDescriptor(class_def);
   Class* klass = context->GetClassLinker()->FindClass(descriptor, class_loader);
+  Thread* self = Thread::Current();
   if (klass != NULL) {
-    ObjectLock lock(klass);
+    ObjectLock lock(self, klass);
     if (klass->IsVerified()) {
       // Only try to initialize classes that were successfully verified.
       bool compiling_boot = Runtime::Current()->GetHeap()->GetSpaces().size() == 1;
@@ -1295,8 +1296,8 @@
       DCHECK_EQ(status, compiled_class->GetStatus());
     }
   }
-  // clear any class not found or verification exceptions
-  Thread::Current()->ClearException();
+  // Clear any class not found or verification exceptions.
+  self->ClearException();
 }
 
 void Compiler::InitializeClassesWithoutClinit(jobject jni_class_loader, const DexFile& dex_file,
diff --git a/src/debugger.cc b/src/debugger.cc
index ee52984..e28845f 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -31,6 +31,7 @@
 #include "ScopedLocalRef.h"
 #include "ScopedPrimitiveArray.h"
 #include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
 #include "space.h"
 #include "stack_indirect_reference_table.h"
 #include "thread_list.h"
@@ -2464,7 +2465,7 @@
 
   // We can be called while an exception is pending. We need
   // to preserve that across the method invocation.
-  SirtRef<Throwable> old_exception(soa.Self()->GetException());
+  SirtRef<Throwable> old_exception(soa.Self(), soa.Self()->GetException());
   soa.Self()->ClearException();
 
   // Translate the method through the vtable, unless the debugger wants to suppress it.
@@ -2677,7 +2678,7 @@
   } else {
     CHECK(type == CHUNK_TYPE("THCR") || type == CHUNK_TYPE("THNM")) << type;
     ScopedObjectAccessUnchecked soa(Thread::Current());
-    SirtRef<String> name(t->GetThreadName(soa));
+    SirtRef<String> name(soa.Self(), t->GetThreadName(soa));
     size_t char_count = (name.get() != NULL) ? name->GetLength() : 0;
     const jchar* chars = name->GetCharArray()->GetData();
 
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 05ff0c0..28960b9 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -35,6 +35,7 @@
 #include "runtime.h"
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
 #include "stl_util.h"
 #include "stringpiece.h"
 #include "timing_logger.h"
@@ -148,6 +149,7 @@
 
     // Load all the classes specified in the file
     ClassLinker* class_linker = runtime_->GetClassLinker();
+    Thread* self = Thread::Current();
     while (image_classes_file->good()) {
       std::string dot;
       std::getline(*image_classes_file.get(), dot);
@@ -155,7 +157,7 @@
         continue;
       }
       std::string descriptor(DotToDescriptor(dot.c_str()));
-      SirtRef<Class> klass(class_linker->FindSystemClass(descriptor.c_str()));
+      SirtRef<Class> klass(self, class_linker->FindSystemClass(descriptor.c_str()));
       if (klass.get() == NULL) {
         LOG(WARNING) << "Failed to find class " << descriptor;
         Thread::Current()->ClearException();
@@ -167,7 +169,8 @@
     // exceptions are resolved by the verifier when there is a catch block in an interested method.
     // Do this here so that exception classes appear to have been specified image classes.
     std::set<std::pair<uint16_t, const DexFile*> > unresolved_exception_types;
-    SirtRef<Class> java_lang_Throwable(class_linker->FindSystemClass("Ljava/lang/Throwable;"));
+    SirtRef<Class> java_lang_Throwable(self,
+                                       class_linker->FindSystemClass("Ljava/lang/Throwable;"));
     do {
       unresolved_exception_types.clear();
       class_linker->VisitClasses(ResolveCatchBlockExceptionsClassVisitor,
@@ -180,8 +183,8 @@
         const DexFile* dex_file = it->second;
         DexCache* dex_cache = class_linker->FindDexCache(*dex_file);
         ClassLoader* class_loader = NULL;
-        SirtRef<Class> klass(class_linker->ResolveType(*dex_file, exception_type_idx, dex_cache,
-                                                       class_loader));
+        SirtRef<Class> klass(self, class_linker->ResolveType(*dex_file, exception_type_idx,
+                                                             dex_cache, class_loader));
         if (klass.get() == NULL) {
           const DexFile::TypeId& type_id = dex_file->GetTypeId(exception_type_idx);
           const char* descriptor = dex_file->GetTypeDescriptor(type_id);
diff --git a/src/dex_cache_test.cc b/src/dex_cache_test.cc
index da02125..6c0107c 100644
--- a/src/dex_cache_test.cc
+++ b/src/dex_cache_test.cc
@@ -19,6 +19,7 @@
 #include "dex_cache.h"
 #include "heap.h"
 #include "object.h"
+#include "sirt_ref.h"
 
 #include <stdio.h>
 
@@ -28,7 +29,7 @@
 
 TEST_F(DexCacheTest, Open) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<DexCache> dex_cache(class_linker_->AllocDexCache(*java_lang_dex_file_));
+  SirtRef<DexCache> dex_cache(soa.Self(), class_linker_->AllocDexCache(*java_lang_dex_file_));
   ASSERT_TRUE(dex_cache.get() != NULL);
 
   EXPECT_EQ(java_lang_dex_file_->NumStringIds(), dex_cache->NumStrings());
diff --git a/src/exception_test.cc b/src/exception_test.cc
index b82f8f7..c35572d 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -20,6 +20,7 @@
 #include "gtest/gtest.h"
 #include "runtime.h"
 #include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
 #include "thread.h"
 #include "UniquePtr.h"
 
@@ -31,7 +32,8 @@
     CommonTest::SetUp();
 
     ScopedObjectAccess soa(Thread::Current());
-    SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(LoadDex("ExceptionHandle")));
+    SirtRef<ClassLoader> class_loader(soa.Self(),
+                                      soa.Decode<ClassLoader*>(LoadDex("ExceptionHandle")));
     my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader.get());
     ASSERT_TRUE(my_klass_ != NULL);
     class_linker_->EnsureInitialized(my_klass_, false, true);
diff --git a/src/heap.cc b/src/heap.cc
index 703549f..5c6a606 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -34,6 +34,7 @@
 #include "os.h"
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
 #include "space.h"
 #include "stl_util.h"
 #include "thread_list.h"
@@ -420,8 +421,9 @@
       concurrent_start_bytes_ = std::numeric_limits<size_t>::max();
       bytes_since_last_gc_ = 0;
       // The SirtRef is necessary since the calls in RequestConcurrentGC are a safepoint.
-      SirtRef<Object> ref(obj);
-      RequestConcurrentGC();
+      Thread* self = Thread::Current();
+      SirtRef<Object> ref(self, obj);
+      RequestConcurrentGC(self);
     }
     VerifyObject(obj);
 
@@ -1923,14 +1925,13 @@
   }
 }
 
-void Heap::RequestConcurrentGC() {
+void Heap::RequestConcurrentGC(Thread* self) {
   // Make sure that we can do a concurrent GC.
   Runtime* runtime = Runtime::Current();
   if (requesting_gc_ || runtime == NULL || !runtime->IsFinishedStarting() ||
       !runtime->IsConcurrentGcEnabled()) {
     return;
   }
-  Thread* self = Thread::Current();
   {
     MutexLock mu(self, *Locks::runtime_shutdown_lock_);
     if (runtime->IsShuttingDown()) {
diff --git a/src/heap.h b/src/heap.h
index 0a054e2..76206c4 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -301,7 +301,7 @@
   void EnqueueClearedReferences(Object** cleared_references);
 
   void RequestHeapTrim();
-  void RequestConcurrentGC();
+  void RequestConcurrentGC(Thread* self);
 
   // Swap bitmaps (if we are a full Gc then we swap the zygote bitmap too).
   void SwapBitmaps(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(GlobalSynchronization::heap_bitmap_lock_);
diff --git a/src/heap_test.cc b/src/heap_test.cc
index d846db5..881a765 100644
--- a/src/heap_test.cc
+++ b/src/heap_test.cc
@@ -15,6 +15,7 @@
  */
 
 #include "common_test.h"
+#include "sirt_ref.h"
 
 namespace art {
 
@@ -38,7 +39,7 @@
 
     Class* c = class_linker_->FindSystemClass("[Ljava/lang/Object;");
     for (size_t i = 0; i < 1024; ++i) {
-      SirtRef<ObjectArray<Object> > array(ObjectArray<Object>::Alloc(c, 2048));
+      SirtRef<ObjectArray<Object> > array(soa.Self(), ObjectArray<Object>::Alloc(c, 2048));
       for (size_t j = 0; j < 2048; ++j) {
         array->Set(j, String::AllocFromModifiedUtf8("hello, world!"));
       }
diff --git a/src/image_writer.cc b/src/image_writer.cc
index e883599..33d37c7 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -36,6 +36,7 @@
 #include "object_utils.h"
 #include "runtime.h"
 #include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
 #include "space.h"
 #include "UniquePtr.h"
 #include "utils.h"
@@ -320,7 +321,7 @@
       DCHECK_EQ(obj, obj->AsString()->Intern());
       return;
     }
-    SirtRef<String> interned(obj->AsString()->Intern());
+    SirtRef<String> interned(Thread::Current(), obj->AsString()->Intern());
     if (obj != interned.get()) {
       if (!image_writer->IsImageOffsetAssigned(interned.get())) {
         // interned obj is after us, allocate its location early
@@ -351,8 +352,9 @@
   }
 
   // build an Object[] of the roots needed to restore the runtime
-  SirtRef<ObjectArray<Object> > image_roots(
-      ObjectArray<Object>::Alloc(object_array_class, ImageHeader::kImageRootsMax));
+  SirtRef<ObjectArray<Object> >
+      image_roots(Thread::Current(),
+                  ObjectArray<Object>::Alloc(object_array_class, ImageHeader::kImageRootsMax));
   image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniDlsymLookupStub());
   image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray,
                    runtime->GetAbstractMethodErrorStubArray());
@@ -380,7 +382,8 @@
 }
 
 void ImageWriter::CalculateNewObjectOffsets() {
-  SirtRef<ObjectArray<Object> > image_roots(CreateImageRoots());
+  Thread* self = Thread::Current();
+  SirtRef<ObjectArray<Object> > image_roots(self, CreateImageRoots());
 
   Heap* heap = Runtime::Current()->GetHeap();
   const Spaces& spaces = heap->GetSpaces();
@@ -392,20 +395,20 @@
   image_end_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment
 
   {
-    ReaderMutexLock mu(*Locks::heap_bitmap_lock_);
+    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
     heap->FlushAllocStack();
   }
 
   {
     // TODO: Image spaces only?
     // TODO: Add InOrderWalk to heap bitmap.
-    const char* old = Thread::Current()->StartAssertNoThreadSuspension("ImageWriter");
+    const char* old = self->StartAssertNoThreadSuspension("ImageWriter");
     DCHECK(heap->GetLargeObjectsSpace()->GetLiveObjects()->IsEmpty());
     for (Spaces::const_iterator it = spaces.begin(); it != spaces.end(); ++it) {
       (*it)->GetLiveBitmap()->InOrderWalk(CalculateNewObjectOffsetsCallback, this);
       DCHECK_LT(image_end_, image_->Size());
     }
-    Thread::Current()->EndAssertNoThreadSuspension(old);
+    self->EndAssertNoThreadSuspension(old);
   }
 
   // Note that image_top_ is left at end of used space
diff --git a/src/intern_table_test.cc b/src/intern_table_test.cc
index 15fa259..2833f6e 100644
--- a/src/intern_table_test.cc
+++ b/src/intern_table_test.cc
@@ -18,6 +18,7 @@
 
 #include "common_test.h"
 #include "object.h"
+#include "sirt_ref.h"
 
 namespace art {
 
@@ -26,10 +27,10 @@
 TEST_F(InternTableTest, Intern) {
   ScopedObjectAccess soa(Thread::Current());
   InternTable intern_table;
-  SirtRef<String> foo_1(intern_table.InternStrong(3, "foo"));
-  SirtRef<String> foo_2(intern_table.InternStrong(3, "foo"));
-  SirtRef<String> foo_3(String::AllocFromModifiedUtf8("foo"));
-  SirtRef<String> bar(intern_table.InternStrong(3, "bar"));
+  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> bar(soa.Self(), intern_table.InternStrong(3, "bar"));
   EXPECT_TRUE(foo_1->Equals("foo"));
   EXPECT_TRUE(foo_2->Equals("foo"));
   EXPECT_TRUE(foo_3->Equals("foo"));
@@ -46,7 +47,7 @@
   InternTable t;
   EXPECT_EQ(0U, t.Size());
   t.InternStrong(3, "foo");
-  SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
+  SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8("foo"));
   t.InternWeak(foo.get());
   EXPECT_EQ(1U, t.Size());
   t.InternStrong(3, "bar");
@@ -90,10 +91,10 @@
   InternTable t;
   t.InternStrong(3, "foo");
   t.InternStrong(3, "bar");
-  SirtRef<String> hello(String::AllocFromModifiedUtf8("hello"));
-  SirtRef<String> world(String::AllocFromModifiedUtf8("world"));
-  SirtRef<String> s0(t.InternWeak(hello.get()));
-  SirtRef<String> s1(t.InternWeak(world.get()));
+  SirtRef<String> hello(soa.Self(), String::AllocFromModifiedUtf8("hello"));
+  SirtRef<String> world(soa.Self(), String::AllocFromModifiedUtf8("world"));
+  SirtRef<String> s0(soa.Self(), t.InternWeak(hello.get()));
+  SirtRef<String> s1(soa.Self(), t.InternWeak(world.get()));
 
   EXPECT_EQ(4U, t.Size());
 
@@ -102,14 +103,14 @@
   p.Expect(s0.get());
   p.Expect(s1.get());
   {
-    ReaderMutexLock mu(*Locks::heap_bitmap_lock_);
+    ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_);
     t.SweepInternTableWeaks(IsMarked, &p);
   }
 
   EXPECT_EQ(2U, t.Size());
 
   // Just check that we didn't corrupt the map.
-  SirtRef<String> still_here(String::AllocFromModifiedUtf8("still here"));
+  SirtRef<String> still_here(soa.Self(), String::AllocFromModifiedUtf8("still here"));
   t.InternWeak(still_here.get());
   EXPECT_EQ(3U, t.Size());
 }
@@ -119,9 +120,9 @@
   {
     // Strongs are never weak.
     InternTable t;
-    SirtRef<String> interned_foo_1(t.InternStrong(3, "foo"));
+    SirtRef<String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo"));
     EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
-    SirtRef<String> interned_foo_2(t.InternStrong(3, "foo"));
+    SirtRef<String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo"));
     EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
     EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
   }
@@ -129,11 +130,11 @@
   {
     // Weaks are always weak.
     InternTable t;
-    SirtRef<String> foo_1(String::AllocFromModifiedUtf8("foo"));
-    SirtRef<String> foo_2(String::AllocFromModifiedUtf8("foo"));
+    SirtRef<String> foo_1(soa.Self(), String::AllocFromModifiedUtf8("foo"));
+    SirtRef<String> foo_2(soa.Self(), String::AllocFromModifiedUtf8("foo"));
     EXPECT_NE(foo_1.get(), foo_2.get());
-    SirtRef<String> interned_foo_1(t.InternWeak(foo_1.get()));
-    SirtRef<String> interned_foo_2(t.InternWeak(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()));
     EXPECT_TRUE(t.ContainsWeak(interned_foo_2.get()));
     EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
   }
@@ -141,10 +142,10 @@
   {
     // A weak can be promoted to a strong.
     InternTable t;
-    SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
-    SirtRef<String> interned_foo_1(t.InternWeak(foo.get()));
+    SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8("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(t.InternStrong(3, "foo"));
+    SirtRef<String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo"));
     EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
     EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
   }
@@ -152,10 +153,10 @@
   {
     // Interning a weak after a strong gets you the strong.
     InternTable t;
-    SirtRef<String> interned_foo_1(t.InternStrong(3, "foo"));
+    SirtRef<String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo"));
     EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
-    SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
-    SirtRef<String> interned_foo_2(t.InternWeak(foo.get()));
+    SirtRef<String> foo(soa.Self(), String::AllocFromModifiedUtf8("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/jni_internal_test.cc b/src/jni_internal_test.cc
index 469a26c..bc1be28 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -20,6 +20,7 @@
 
 #include "common_test.h"
 #include "ScopedLocalRef.h"
+#include "sirt_ref.h"
 
 namespace art {
 
@@ -73,7 +74,10 @@
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     const char* class_name = is_static ? "StaticLeafMethods" : "NonStaticLeafMethods";
     jobject jclass_loader(LoadDex(class_name));
-    SirtRef<ClassLoader> class_loader(ScopedObjectAccessUnchecked(Thread::Current()).Decode<ClassLoader*>(jclass_loader));
+    Thread* self = Thread::Current();
+    SirtRef<ClassLoader>
+        class_loader(self,
+                     ScopedObjectAccessUnchecked(self).Decode<ClassLoader*>(jclass_loader));
     if (is_static) {
       CompileDirectMethod(class_loader.get(), class_name, method_name, method_signature);
     } else {
@@ -1382,7 +1386,7 @@
 TEST_F(JniInternalTest, StaticMainMethod) {
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("Main");
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(jclass_loader));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
   CompileDirectMethod(class_loader.get(), "Main", "main", "([Ljava/lang/String;)V");
 
   Class* klass = class_linker_->FindClass("LMain;", class_loader.get());
diff --git a/src/native/java_lang_reflect_Array.cc b/src/native/java_lang_reflect_Array.cc
index 49a4694..d3a57bf 100644
--- a/src/native/java_lang_reflect_Array.cc
+++ b/src/native/java_lang_reflect_Array.cc
@@ -19,17 +19,19 @@
 #include "object.h"
 #include "object_utils.h"
 #include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
 
 namespace art {
 
 // Recursively create an array with multiple dimensions.  Elements may be
 // Objects or primitive types.
-static Array* CreateMultiArray(Class* array_class, int current_dimension, IntArray* dimensions)
+static Array* CreateMultiArray(Thread* self, Class* array_class, int current_dimension,
+                               IntArray* dimensions)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   int32_t array_length = dimensions->Get(current_dimension++);
-  SirtRef<Array> new_array(Array::Alloc(array_class, array_length));
+  SirtRef<Array> new_array(self, Array::Alloc(array_class, array_length));
   if (new_array.get() == NULL) {
-    CHECK(Thread::Current()->IsExceptionPending());
+    CHECK(self->IsExceptionPending());
     return NULL;
   }
   if (current_dimension == dimensions->GetLength()) {
@@ -46,16 +48,17 @@
   Class* sub_array_class = class_linker->FindClass(sub_array_descriptor.c_str(),
                                                    array_class->GetClassLoader());
   if (sub_array_class == NULL) {
-    CHECK(Thread::Current()->IsExceptionPending());
+    CHECK(self->IsExceptionPending());
     return NULL;
   }
   DCHECK(sub_array_class->IsArrayClass());
   // Create a new sub-array in every element of the array.
-  SirtRef<ObjectArray<Array> > object_array(new_array->AsObjectArray<Array>());
+  SirtRef<ObjectArray<Array> > object_array(self, new_array->AsObjectArray<Array>());
   for (int32_t i = 0; i < array_length; i++) {
-    SirtRef<Array> sub_array(CreateMultiArray(sub_array_class, current_dimension, dimensions));
+    SirtRef<Array> sub_array(self, CreateMultiArray(self, sub_array_class, current_dimension,
+                                                    dimensions));
     if (sub_array.get() == NULL) {
-      CHECK(Thread::Current()->IsExceptionPending());
+      CHECK(self->IsExceptionPending());
       return NULL;
     }
     object_array->Set(i, sub_array.get());
@@ -105,13 +108,13 @@
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Class* array_class = class_linker->FindClass(descriptor.c_str(), element_class->GetClassLoader());
   if (array_class == NULL) {
-    CHECK(Thread::Current()->IsExceptionPending());
+    CHECK(soa.Self()->IsExceptionPending());
     return NULL;
   }
   // create the array
-  Array* new_array = CreateMultiArray(array_class, 0, dimensions_array);
+  Array* new_array = CreateMultiArray(soa.Self(), array_class, 0, dimensions_array);
   if (new_array == NULL) {
-    CHECK(Thread::Current()->IsExceptionPending());
+    CHECK(soa.Self()->IsExceptionPending());
     return NULL;
   }
   return soa.AddLocalReference<jobject>(new_array);
diff --git a/src/oat/runtime/arm/stub_arm.cc b/src/oat/runtime/arm/stub_arm.cc
index dca6d02..7add255 100644
--- a/src/oat/runtime/arm/stub_arm.cc
+++ b/src/oat/runtime/arm/stub_arm.cc
@@ -20,6 +20,7 @@
 #include "oat/runtime/stub.h"
 #include "object.h"
 #include "stack_indirect_reference_table.h"
+#include "sirt_ref.h"
 
 #define __ assembler->
 
@@ -81,7 +82,7 @@
 
   assembler->EmitSlowPaths();
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> resolution_trampoline(Thread::Current(), ByteArray::Alloc(cs));
   CHECK(resolution_trampoline.get() != NULL);
   MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
   assembler->FinalizeInstructions(code);
@@ -127,7 +128,7 @@
   assembler->EmitSlowPaths();
 
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> abstract_stub(Thread::Current(), ByteArray::Alloc(cs));
   CHECK(abstract_stub.get() != NULL);
   MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
   assembler->FinalizeInstructions(code);
@@ -155,7 +156,7 @@
   assembler->EmitSlowPaths();
 
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> jni_stub(Thread::Current(), ByteArray::Alloc(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 7b4c85e..d545e4a 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -20,6 +20,7 @@
 #include "oat/utils/mips/assembler_mips.h"
 #include "object.h"
 #include "stack_indirect_reference_table.h"
+#include "sirt_ref.h"
 
 #define __ assembler->
 
@@ -111,7 +112,7 @@
   assembler->EmitSlowPaths();
 
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> resolution_trampoline(Thread::Current(), ByteArray::Alloc(cs));
   CHECK(resolution_trampoline.get() != NULL);
   MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
   assembler->FinalizeInstructions(code);
@@ -156,7 +157,7 @@
   assembler->EmitSlowPaths();
 
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> abstract_stub(Thread::Current(), ByteArray::Alloc(cs));
   CHECK(abstract_stub.get() != NULL);
   MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
   assembler->FinalizeInstructions(code);
@@ -196,7 +197,7 @@
   assembler->EmitSlowPaths();
 
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> jni_stub(Thread::Current(), ByteArray::Alloc(cs));
   CHECK(jni_stub.get() != NULL);
   MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
   assembler->FinalizeInstructions(code);
diff --git a/src/oat/runtime/x86/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc
index 97b686f..7941d15 100644
--- a/src/oat/runtime/x86/stub_x86.cc
+++ b/src/oat/runtime/x86/stub_x86.cc
@@ -20,6 +20,7 @@
 #include "oat/utils/x86/assembler_x86.h"
 #include "object.h"
 #include "stack_indirect_reference_table.h"
+#include "sirt_ref.h"
 
 #define __ assembler->
 
@@ -91,7 +92,7 @@
 
   assembler->EmitSlowPaths();
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> resolution_trampoline(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> resolution_trampoline(Thread::Current(), ByteArray::Alloc(cs));
   CHECK(resolution_trampoline.get() != NULL);
   MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
   assembler->FinalizeInstructions(code);
@@ -145,7 +146,7 @@
   assembler->EmitSlowPaths();
 
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> abstract_stub(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> abstract_stub(Thread::Current(),ByteArray::Alloc(cs));
   CHECK(abstract_stub.get() != NULL);
   MemoryRegion code(abstract_stub->GetData(), abstract_stub->GetLength());
   assembler->FinalizeInstructions(code);
@@ -178,7 +179,7 @@
   assembler->EmitSlowPaths();
 
   size_t cs = assembler->CodeSize();
-  SirtRef<ByteArray> jni_stub(ByteArray::Alloc(cs));
+  SirtRef<ByteArray> jni_stub(Thread::Current(), ByteArray::Alloc(cs));
   CHECK(jni_stub.get() != NULL);
   MemoryRegion code(jni_stub->GetData(), jni_stub->GetLength());
   assembler->FinalizeInstructions(code);
diff --git a/src/object.cc b/src/object.cc
index 0cf2aa8..8582a21 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -35,6 +35,7 @@
 #include "object_utils.h"
 #include "runtime.h"
 #include "runtime_support.h"
+#include "sirt_ref.h"
 #include "stack.h"
 #include "utils.h"
 #include "well_known_classes.h"
@@ -54,7 +55,7 @@
   // Using c->AllocObject() here would be wrong.
   size_t num_bytes = SizeOf();
   Heap* heap = Runtime::Current()->GetHeap();
-  SirtRef<Object> copy(heap->AllocObject(c, num_bytes));
+  SirtRef<Object> copy(Thread::Current(), heap->AllocObject(c, num_bytes));
   if (copy.get() == NULL) {
     return NULL;
   }
@@ -696,7 +697,7 @@
 
     // stash current exception
     Thread* self = Thread::Current();
-    SirtRef<Throwable> exception(self->GetException());
+    SirtRef<Throwable> exception(self, self->GetException());
     CHECK(exception.get() != NULL);
 
     // clear exception to call FindSystemClass
@@ -1447,7 +1448,7 @@
 }
 
 String* String::Alloc(Class* java_lang_String, int32_t utf16_length) {
-  SirtRef<CharArray> array(CharArray::Alloc(utf16_length));
+  SirtRef<CharArray> array(Thread::Current(), CharArray::Alloc(utf16_length));
   if (array.get() == NULL) {
     return NULL;
   }
@@ -1455,7 +1456,8 @@
 }
 
 String* String::Alloc(Class* java_lang_String, CharArray* array) {
-  SirtRef<CharArray> array_ref(array);  // hold reference in case AllocObject causes GC
+  // Hold reference in case AllocObject causes GC.
+  SirtRef<CharArray> array_ref(Thread::Current(), array);
   String* string = down_cast<String*>(java_lang_String->AllocObject());
   if (string == NULL) {
     return NULL;
diff --git a/src/object_test.cc b/src/object_test.cc
index 3dfa0a9..f28c20b 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -19,13 +19,14 @@
 #include <stdint.h>
 #include <stdio.h>
 
-#include "UniquePtr.h"
+#include "asm_support.h"
 #include "class_linker.h"
 #include "common_test.h"
 #include "dex_file.h"
 #include "heap.h"
 #include "runtime_support.h"
-#include "asm_support.h"
+#include "sirt_ref.h"
+#include "UniquePtr.h"
 
 namespace art {
 
@@ -43,7 +44,7 @@
       utf16_expected[i] = ch;
     }
 
-    SirtRef<String> string(String::AllocFromModifiedUtf8(length, utf8_in));
+    SirtRef<String> string(Thread::Current(), String::AllocFromModifiedUtf8(length, utf8_in));
     ASSERT_EQ(length, string->GetLength());
     ASSERT_TRUE(string->GetCharArray() != NULL);
     ASSERT_TRUE(string->GetCharArray()->GetData() != NULL);
@@ -76,7 +77,7 @@
 
 TEST_F(ObjectTest, Clone) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<ObjectArray<Object> > a1(class_linker_->AllocObjectArray<Object>(256));
+  SirtRef<ObjectArray<Object> > a1(soa.Self(), class_linker_->AllocObjectArray<Object>(256));
   size_t s1 = a1->SizeOf();
   Object* clone = a1->Clone();
   EXPECT_EQ(s1, clone->SizeOf());
@@ -85,7 +86,7 @@
 
 TEST_F(ObjectTest, AllocObjectArray) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<ObjectArray<Object> > oa(class_linker_->AllocObjectArray<Object>(2));
+  SirtRef<ObjectArray<Object> > oa(soa.Self(), class_linker_->AllocObjectArray<Object>(2));
   EXPECT_EQ(2, oa->GetLength());
   EXPECT_TRUE(oa->Get(0) == NULL);
   EXPECT_TRUE(oa->Get(1) == NULL);
@@ -96,18 +97,17 @@
   EXPECT_TRUE(oa->Get(0) == oa.get());
   EXPECT_TRUE(oa->Get(1) == oa.get());
 
-  Thread* self = Thread::Current();
   Class* aioobe = class_linker_->FindSystemClass("Ljava/lang/ArrayIndexOutOfBoundsException;");
 
   EXPECT_TRUE(oa->Get(-1) == NULL);
-  EXPECT_TRUE(self->IsExceptionPending());
-  EXPECT_EQ(aioobe, self->GetException()->GetClass());
-  self->ClearException();
+  EXPECT_TRUE(soa.Self()->IsExceptionPending());
+  EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
+  soa.Self()->ClearException();
 
   EXPECT_TRUE(oa->Get(2) == NULL);
-  EXPECT_TRUE(self->IsExceptionPending());
-  EXPECT_EQ(aioobe, self->GetException()->GetClass());
-  self->ClearException();
+  EXPECT_TRUE(soa.Self()->IsExceptionPending());
+  EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
+  soa.Self()->ClearException();
 
   ASSERT_TRUE(oa->GetClass() != NULL);
   ClassHelper oa_ch(oa->GetClass());
@@ -119,7 +119,7 @@
 TEST_F(ObjectTest, AllocArray) {
   ScopedObjectAccess soa(Thread::Current());
   Class* c = class_linker_->FindSystemClass("[I");
-  SirtRef<Array> a(Array::Alloc(c, 1));
+  SirtRef<Array> a(soa.Self(), Array::Alloc(c, 1));
   ASSERT_TRUE(c == a->GetClass());
 
   c = class_linker_->FindSystemClass("[Ljava/lang/Object;");
@@ -147,18 +147,17 @@
   EXPECT_EQ(T(123), a->Get(0));
   EXPECT_EQ(T(321), a->Get(1));
 
-  Thread* self = Thread::Current();
   Class* aioobe = cl->FindSystemClass("Ljava/lang/ArrayIndexOutOfBoundsException;");
 
   EXPECT_EQ(0, a->Get(-1));
-  EXPECT_TRUE(self->IsExceptionPending());
-  EXPECT_EQ(aioobe, self->GetException()->GetClass());
-  self->ClearException();
+  EXPECT_TRUE(soa.Self()->IsExceptionPending());
+  EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
+  soa.Self()->ClearException();
 
   EXPECT_EQ(0, a->Get(2));
-  EXPECT_TRUE(self->IsExceptionPending());
-  EXPECT_EQ(aioobe, self->GetException()->GetClass());
-  self->ClearException();
+  EXPECT_TRUE(soa.Self()->IsExceptionPending());
+  EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
+  soa.Self()->ClearException();
 }
 
 TEST_F(ObjectTest, PrimitiveArray_Boolean_Alloc) {
@@ -239,7 +238,7 @@
   Object* s0 = field->GetObj(NULL);
   EXPECT_EQ(NULL, s0);
 
-  SirtRef<CharArray> char_array(CharArray::Alloc(0));
+  SirtRef<CharArray> char_array(soa.Self(), CharArray::Alloc(0));
   field->SetObj(NULL, char_array.get());
   EXPECT_EQ(char_array.get(), field->GetObj(NULL));
 
@@ -275,7 +274,7 @@
 
 TEST_F(ObjectTest, StringEqualsUtf8) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<String> string(String::AllocFromModifiedUtf8("android"));
+  SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8("android"));
   EXPECT_TRUE(string->Equals("android"));
   EXPECT_FALSE(string->Equals("Android"));
   EXPECT_FALSE(string->Equals("ANDROID"));
@@ -283,15 +282,15 @@
   EXPECT_FALSE(string->Equals("and"));
   EXPECT_FALSE(string->Equals("androids"));
 
-  SirtRef<String> empty(String::AllocFromModifiedUtf8(""));
+  SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8(""));
   EXPECT_TRUE(empty->Equals(""));
   EXPECT_FALSE(empty->Equals("a"));
 }
 
 TEST_F(ObjectTest, StringEquals) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<String> string(String::AllocFromModifiedUtf8("android"));
-  SirtRef<String> string_2(String::AllocFromModifiedUtf8("android"));
+  SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8("android"));
+  SirtRef<String> string_2(soa.Self(), String::AllocFromModifiedUtf8("android"));
   EXPECT_TRUE(string->Equals(string_2.get()));
   EXPECT_FALSE(string->Equals("Android"));
   EXPECT_FALSE(string->Equals("ANDROID"));
@@ -299,14 +298,14 @@
   EXPECT_FALSE(string->Equals("and"));
   EXPECT_FALSE(string->Equals("androids"));
 
-  SirtRef<String> empty(String::AllocFromModifiedUtf8(""));
+  SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8(""));
   EXPECT_TRUE(empty->Equals(""));
   EXPECT_FALSE(empty->Equals("a"));
 }
 
 TEST_F(ObjectTest, StringLength) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<String> string(String::AllocFromModifiedUtf8("android"));
+  SirtRef<String> string(soa.Self(), String::AllocFromModifiedUtf8("android"));
   EXPECT_EQ(string->GetLength(), 7);
   EXPECT_EQ(string->GetUtfLength(), 7);
 
@@ -323,8 +322,8 @@
 
   jobject jclass_loader_1 = LoadDex("ProtoCompare");
   jobject jclass_loader_2 = LoadDex("ProtoCompare2");
-  SirtRef<ClassLoader> class_loader_1(soa.Decode<ClassLoader*>(jclass_loader_1));
-  SirtRef<ClassLoader> class_loader_2(soa.Decode<ClassLoader*>(jclass_loader_2));
+  SirtRef<ClassLoader> class_loader_1(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader_1));
+  SirtRef<ClassLoader> class_loader_2(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader_2));
 
   Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1.get());
   ASSERT_TRUE(klass1 != NULL);
@@ -381,9 +380,9 @@
 
 TEST_F(ObjectTest, StringHashCode) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<String> empty(String::AllocFromModifiedUtf8(""));
-  SirtRef<String> A(String::AllocFromModifiedUtf8("A"));
-  SirtRef<String> ABC(String::AllocFromModifiedUtf8("ABC"));
+  SirtRef<String> empty(soa.Self(), String::AllocFromModifiedUtf8(""));
+  SirtRef<String> A(soa.Self(), String::AllocFromModifiedUtf8("A"));
+  SirtRef<String> ABC(soa.Self(), String::AllocFromModifiedUtf8("ABC"));
 
   EXPECT_EQ(0, empty->GetHashCode());
   EXPECT_EQ(65, A->GetHashCode());
@@ -393,15 +392,15 @@
 TEST_F(ObjectTest, InstanceOf) {
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("XandY");
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(jclass_loader));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
 
   Class* X = class_linker_->FindClass("LX;", class_loader.get());
   Class* Y = class_linker_->FindClass("LY;", class_loader.get());
   ASSERT_TRUE(X != NULL);
   ASSERT_TRUE(Y != NULL);
 
-  SirtRef<Object> x(X->AllocObject());
-  SirtRef<Object> y(Y->AllocObject());
+  SirtRef<Object> x(soa.Self(), X->AllocObject());
+  SirtRef<Object> y(soa.Self(), Y->AllocObject());
   ASSERT_TRUE(x.get() != NULL);
   ASSERT_TRUE(y.get() != NULL);
 
@@ -427,7 +426,7 @@
 TEST_F(ObjectTest, IsAssignableFrom) {
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("XandY");
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(jclass_loader));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
   Class* X = class_linker_->FindClass("LX;", class_loader.get());
   Class* Y = class_linker_->FindClass("LY;", class_loader.get());
 
@@ -464,7 +463,7 @@
 TEST_F(ObjectTest, IsAssignableFromArray) {
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("XandY");
-  SirtRef<ClassLoader> class_loader(soa.Decode<ClassLoader*>(jclass_loader));
+  SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
   Class* X = class_linker_->FindClass("LX;", class_loader.get());
   Class* Y = class_linker_->FindClass("LY;", class_loader.get());
   ASSERT_TRUE(X != NULL);
@@ -516,7 +515,7 @@
 
 TEST_F(ObjectTest, FindInstanceField) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<String> s(String::AllocFromModifiedUtf8("ABC"));
+  SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8("ABC"));
   ASSERT_TRUE(s.get() != NULL);
   Class* c = s->GetClass();
   ASSERT_TRUE(c != NULL);
@@ -549,7 +548,7 @@
 
 TEST_F(ObjectTest, FindStaticField) {
   ScopedObjectAccess soa(Thread::Current());
-  SirtRef<String> s(String::AllocFromModifiedUtf8("ABC"));
+  SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8("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 035f689..1d66c8f 100644
--- a/src/object_utils.h
+++ b/src/object_utils.h
@@ -32,8 +32,8 @@
 
 class ObjectLock {
  public:
-  explicit ObjectLock(Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : self_(Thread::Current()), obj_(object) {
+  explicit ObjectLock(Thread* self, Object* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : self_(self), obj_(object) {
     CHECK(object != NULL);
     obj_->MonitorEnter(self_);
   }
diff --git a/src/runtime.cc b/src/runtime.cc
index 61d93f8..d10c351 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -40,6 +40,7 @@
 #include "scoped_thread_state_change.h"
 #include "signal_catcher.h"
 #include "signal_set.h"
+#include "sirt_ref.h"
 #include "space.h"
 #include "thread.h"
 #include "thread_list.h"
@@ -983,7 +984,8 @@
 
 AbstractMethod* Runtime::CreateResolutionMethod() {
   Class* method_class = AbstractMethod::GetMethodClass();
-  SirtRef<AbstractMethod> method(down_cast<AbstractMethod*>(method_class->AllocObject()));
+  SirtRef<AbstractMethod> method(Thread::Current(),
+                                 down_cast<AbstractMethod*>(method_class->AllocObject()));
   method->SetDeclaringClass(method_class);
   // TODO: use a special method for resolution method saves
   method->SetDexMethodIndex(DexFile::kDexNoIndex16);
@@ -993,9 +995,11 @@
   return method.get();
 }
 
-AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set, CalleeSaveType type) {
+AbstractMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_set,
+                                                CalleeSaveType type) {
   Class* method_class = AbstractMethod::GetMethodClass();
-  SirtRef<AbstractMethod> method(down_cast<AbstractMethod*>(method_class->AllocObject()));
+  SirtRef<AbstractMethod>
+      method(Thread::Current(), down_cast<AbstractMethod*>(method_class->AllocObject()));
   method->SetDeclaringClass(method_class);
   // TODO: use a special method for callee saves
   method->SetDexMethodIndex(DexFile::kDexNoIndex16);
diff --git a/src/sirt_ref.h b/src/sirt_ref.h
new file mode 100644
index 0000000..ea0b9a3
--- /dev/null
+++ b/src/sirt_ref.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_SIRT_REF_H_
+#define ART_SRC_SIRT_REF_H_
+
+#include "logging.h"
+#include "macros.h"
+#include "thread.h"
+
+namespace art {
+
+template<class T>
+class SirtRef {
+ public:
+  SirtRef(Thread* self, T* object) : self_(self), sirt_(object) {
+    self_->PushSirt(&sirt_);
+  }
+  ~SirtRef() {
+    CHECK(self_->PopSirt() == &sirt_);
+  }
+
+  T& operator*() const { return *get(); }
+  T* operator->() const { return get(); }
+  T* get() const {
+    return down_cast<T*>(sirt_.GetReference(0));
+  }
+
+  void reset(T* object = NULL) {
+    sirt_.SetReference(0, object);
+  }
+
+ private:
+  Thread* const self_;
+  StackIndirectReferenceTable sirt_;
+
+  DISALLOW_COPY_AND_ASSIGN(SirtRef);
+};
+
+}  // namespace art
+
+#endif  // ART_SRC_SIRT_REF_H_
diff --git a/src/stack_indirect_reference_table.h b/src/stack_indirect_reference_table.h
index 681405f..506f00a 100644
--- a/src/stack_indirect_reference_table.h
+++ b/src/stack_indirect_reference_table.h
@@ -17,30 +17,24 @@
 #ifndef ART_SRC_STACK_INDIRECT_REFERENCE_TABLE_H_
 #define ART_SRC_STACK_INDIRECT_REFERENCE_TABLE_H_
 
-#include "casts.h"
 #include "logging.h"
 #include "macros.h"
-#include "thread.h"
 
 namespace art {
 
 class Object;
+class Thread;
 
 // Stack allocated indirect reference table. It can allocated within
 // the bridge frame between managed and native code backed by stack
 // storage or manually allocated by SirtRef to hold one reference.
 class StackIndirectReferenceTable {
  public:
-  explicit StackIndirectReferenceTable(Object* object) {
-    number_of_references_ = 1;
+  explicit StackIndirectReferenceTable(Object* object) : number_of_references_(1), link_(NULL) {
     references_[0] = object;
-    Thread::Current()->PushSirt(this);
   }
 
-  ~StackIndirectReferenceTable() {
-    StackIndirectReferenceTable* sirt = Thread::Current()->PopSirt();
-    CHECK_EQ(this, sirt);
-  }
+  ~StackIndirectReferenceTable() {}
 
   // Number of references contained within this SIRT
   size_t NumberOfReferences() const {
@@ -98,28 +92,6 @@
   DISALLOW_COPY_AND_ASSIGN(StackIndirectReferenceTable);
 };
 
-template<class T>
-class SirtRef {
- public:
-  explicit SirtRef(T* object) : sirt_(object) {}
-  ~SirtRef() {}
-
-  T& operator*() const { return *get(); }
-  T* operator->() const { return get(); }
-  T* get() const {
-    return down_cast<T*>(sirt_.GetReference(0));
-  }
-
-  void reset(T* object = NULL) {
-    sirt_.SetReference(0, object);
-  }
-
- private:
-  StackIndirectReferenceTable sirt_;
-
-  DISALLOW_COPY_AND_ASSIGN(SirtRef);
-};
-
 }  // namespace art
 
 #endif  // ART_SRC_STACK_INDIRECT_REFERENCE_TABLE_H_
diff --git a/src/thread.cc b/src/thread.cc
index bd58e6a..15a4f1b 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -46,6 +46,7 @@
 #include "runtime_support.h"
 #include "scoped_thread_state_change.h"
 #include "ScopedLocalRef.h"
+#include "sirt_ref.h"
 #include "space.h"
 #include "stack.h"
 #include "stack_indirect_reference_table.h"
@@ -119,7 +120,7 @@
   {
     ScopedObjectAccess soa(self);
     {
-      SirtRef<String> thread_name(self->GetThreadName(soa));
+      SirtRef<String> thread_name(self, self->GetThreadName(soa));
       self->SetThreadName(thread_name->ToModifiedUtf8().c_str());
     }
     Dbg::PostThreadStart(self);
@@ -378,7 +379,7 @@
                         reinterpret_cast<jint>(self));
 
   ScopedObjectAccess soa(self);
-  SirtRef<String> peer_thread_name(GetThreadName(soa));
+  SirtRef<String> peer_thread_name(soa.Self(), GetThreadName(soa));
   if (peer_thread_name.get() == NULL) {
     Object* native_peer = soa.Decode<Object*>(peer.get());
     // The Thread constructor should have set the Thread.name to a
@@ -1240,17 +1241,18 @@
 
 class BuildInternalStackTraceVisitor : public StackVisitor {
  public:
-  explicit BuildInternalStackTraceVisitor(const ManagedStack* stack,
+  explicit BuildInternalStackTraceVisitor(Thread* self, const ManagedStack* stack,
                                           const std::vector<TraceStackFrame>* trace_stack,
                                           int skip_depth)
-      : StackVisitor(stack, trace_stack, NULL),
+      : StackVisitor(stack, trace_stack, NULL), self_(self),
         skip_depth_(skip_depth), count_(0), dex_pc_trace_(NULL), method_trace_(NULL) {}
 
-  bool Init(int depth, const ScopedObjectAccess& soa)
+  bool Init(int depth)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     // Allocate method trace with an extra slot that will hold the PC trace
     SirtRef<ObjectArray<Object> >
-      method_trace(Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(depth + 1));
+        method_trace(self_,
+                     Runtime::Current()->GetClassLinker()->AllocObjectArray<Object>(depth + 1));
     if (method_trace.get() == NULL) {
       return false;
     }
@@ -1263,7 +1265,7 @@
     method_trace->Set(depth, dex_pc_trace);
     // Set the Object*s and assert that no thread suspension is now possible.
     const char* last_no_suspend_cause =
-        soa.Self()->StartAssertNoThreadSuspension("Building internal stack trace");
+        self_->StartAssertNoThreadSuspension("Building internal stack trace");
     CHECK(last_no_suspend_cause == NULL) << last_no_suspend_cause;
     method_trace_ = method_trace.get();
     dex_pc_trace_ = dex_pc_trace;
@@ -1272,7 +1274,7 @@
 
   virtual ~BuildInternalStackTraceVisitor() {
     if (method_trace_ != NULL) {
-      Thread::Current()->EndAssertNoThreadSuspension(NULL);
+      self_->EndAssertNoThreadSuspension(NULL);
     }
   }
 
@@ -1299,6 +1301,7 @@
   }
 
  private:
+  Thread* const self_;
   // How many more frames to skip.
   int32_t skip_depth_;
   // Current position down stack trace.
@@ -1309,18 +1312,6 @@
   ObjectArray<Object>* method_trace_;
 };
 
-void Thread::PushSirt(StackIndirectReferenceTable* sirt) {
-  sirt->SetLink(top_sirt_);
-  top_sirt_ = sirt;
-}
-
-StackIndirectReferenceTable* Thread::PopSirt() {
-  CHECK(top_sirt_ != NULL);
-  StackIndirectReferenceTable* sirt = top_sirt_;
-  top_sirt_ = top_sirt_->GetLink();
-  return sirt;
-}
-
 jobject Thread::CreateInternalStackTrace(const ScopedObjectAccess& soa) const {
   // Compute depth of stack
   CountStackDepthVisitor count_visitor(GetManagedStack(), GetTraceStack());
@@ -1328,11 +1319,11 @@
   int32_t depth = count_visitor.GetDepth();
   int32_t skip_depth = count_visitor.GetSkipDepth();
 
-  // Build internal stack trace
-  BuildInternalStackTraceVisitor build_trace_visitor(GetManagedStack(), GetTraceStack(),
+  // Build internal stack trace.
+  BuildInternalStackTraceVisitor build_trace_visitor(soa.Self(), GetManagedStack(), GetTraceStack(),
                                                      skip_depth);
-  if (!build_trace_visitor.Init(depth, soa)) {
-    return NULL;  // Allocation failed
+  if (!build_trace_visitor.Init(depth)) {
+    return NULL;  // Allocation failed.
   }
   build_trace_visitor.WalkStack();
   return soa.AddLocalReference<jobjectArray>(build_trace_visitor.GetInternalStackTrace());
@@ -1382,18 +1373,19 @@
     const char* descriptor = mh.GetDeclaringClassDescriptor();
     CHECK(descriptor != NULL);
     std::string class_name(PrettyDescriptor(descriptor));
-    SirtRef<String> class_name_object(String::AllocFromModifiedUtf8(class_name.c_str()));
+    SirtRef<String> class_name_object(soa.Self(),
+                                      String::AllocFromModifiedUtf8(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(String::AllocFromModifiedUtf8(method_name));
+    SirtRef<String> method_name_object(soa.Self(), String::AllocFromModifiedUtf8(method_name));
     if (method_name_object.get() == NULL) {
       return NULL;
     }
     const char* source_file = mh.GetDeclaringClassSourceFile();
-    SirtRef<String> source_name_object(String::AllocFromModifiedUtf8(source_file));
+    SirtRef<String> source_name_object(soa.Self(), String::AllocFromModifiedUtf8(source_file));
     StackTraceElement* obj = StackTraceElement::Alloc(class_name_object.get(),
                                                       method_name_object.get(),
                                                       source_name_object.get(),
diff --git a/src/thread.h b/src/thread.h
index 1e80a80..06798cd 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -32,6 +32,7 @@
 #include "offsets.h"
 #include "runtime_stats.h"
 #include "stack.h"
+#include "stack_indirect_reference_table.h"
 #include "trace.h"
 #include "UniquePtr.h"
 #ifdef ART_USE_GREENLAND_COMPILER
@@ -518,8 +519,17 @@
 
   void SirtVisitRoots(Heap::RootVisitor* visitor, void* arg);
 
-  void PushSirt(StackIndirectReferenceTable* sirt);
-  StackIndirectReferenceTable* PopSirt();
+  void PushSirt(StackIndirectReferenceTable* sirt) {
+    sirt->SetLink(top_sirt_);
+    top_sirt_ = sirt;
+  }
+
+  StackIndirectReferenceTable* PopSirt() {
+    StackIndirectReferenceTable* sirt = top_sirt_;
+    DCHECK(sirt != NULL);
+    top_sirt_ = top_sirt_->GetLink();
+    return sirt;
+  }
 
   static ThreadOffset TopSirtOffset() {
     return ThreadOffset(OFFSETOF_MEMBER(Thread, top_sirt_));
diff --git a/src/utils_test.cc b/src/utils_test.cc
index 0b27fc5..1fcb4b3 100644
--- a/src/utils_test.cc
+++ b/src/utils_test.cc
@@ -17,6 +17,7 @@
 #include "object.h"
 #include "common_test.h"
 #include "scoped_thread_state_change.h"
+#include "sirt_ref.h"
 #include "utils.h"
 
 namespace art {
@@ -88,10 +89,10 @@
   ScopedObjectAccess soa(Thread::Current());
   EXPECT_EQ("null", PrettyTypeOf(NULL));
 
-  SirtRef<String> s(String::AllocFromModifiedUtf8(""));
+  SirtRef<String> s(soa.Self(), String::AllocFromModifiedUtf8(""));
   EXPECT_EQ("java.lang.String", PrettyTypeOf(s.get()));
 
-  SirtRef<ShortArray> a(ShortArray::Alloc(2));
+  SirtRef<ShortArray> a(soa.Self(), ShortArray::Alloc(2));
   EXPECT_EQ("short[]", PrettyTypeOf(a.get()));
 
   Class* c = class_linker_->FindSystemClass("[Ljava/lang/String;");