Compacting collector.

The compacting collector is currently similar to semispace. It works by
copying objects back and forth between two bump pointer spaces. There
are types of objects which are "non-movable" due to current runtime
limitations. These are Classes, Methods, and Fields.

Bump pointer spaces are a new type of continuous alloc space which have
no lock in the allocation code path. When you allocate from these it uses
atomic operations to increase an index. Traversing the objects in the bump
pointer space relies on Object::SizeOf matching the allocated size exactly.

Runtime changes:
JNI::GetArrayElements returns copies objects if you attempt to get the
backing data of a movable array. For GetArrayElementsCritical, we return
direct backing storage for any types of arrays, but temporarily disable
the GC until the critical region is completed.

Added a new runtime call called VisitObjects, this is used in place of
the old pattern which was flushing the allocation stack and walking
the bitmaps.

Changed image writer to be compaction safe and use object monitor word
for forwarding addresses.

Added a bunch of added SIRTs to ClassLinker, MethodLinker, etc..

TODO: Enable switching allocators, compacting on background, etc..

Bug: 8981901

Change-Id: I3c886fd322a6eef2b99388d19a765042ec26ab99
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index c60e714..ef73e4d 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -66,36 +66,36 @@
   return array;
 }
 
-inline Array* Array::AllocInstrumented(Thread* self, Class* array_class, int32_t component_count,
-                                       size_t component_size) {
+template <bool kIsMovable, bool kIsInstrumented>
+inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count,
+                           size_t component_size) {
   size_t size = ComputeArraySize(self, array_class, component_count, component_size);
   if (UNLIKELY(size == 0)) {
     return NULL;
   }
   gc::Heap* heap = Runtime::Current()->GetHeap();
-  Array* array = down_cast<Array*>(heap->AllocObjectInstrumented(self, array_class, size));
-  return SetArrayLength(array, component_count);
-}
-
-inline Array* Array::AllocUninstrumented(Thread* self, Class* array_class, int32_t component_count,
-                                         size_t component_size) {
-  size_t size = ComputeArraySize(self, array_class, component_count, component_size);
-  if (UNLIKELY(size == 0)) {
-    return NULL;
+  Array* array = nullptr;
+  if (kIsMovable) {
+    if (kIsInstrumented) {
+      array = down_cast<Array*>(heap->AllocMovableObjectInstrumented(self, array_class, size));
+    } else {
+      array = down_cast<Array*>(heap->AllocMovableObjectUninstrumented(self, array_class, size));
+    }
+  } else {
+    if (kIsInstrumented) {
+      array = down_cast<Array*>(heap->AllocNonMovableObjectInstrumented(self, array_class, size));
+    } else {
+      array = down_cast<Array*>(heap->AllocNonMovableObjectUninstrumented(self, array_class, size));
+    }
   }
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  Array* array = down_cast<Array*>(heap->AllocObjectUninstrumented(self, array_class, size));
   return SetArrayLength(array, component_count);
 }
 
-inline Array* Array::AllocInstrumented(Thread* self, Class* array_class, int32_t component_count) {
+template <bool kIsMovable, bool kIsInstrumented>
+inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count) {
   DCHECK(array_class->IsArrayClass());
-  return AllocInstrumented(self, array_class, component_count, array_class->GetComponentSize());
-}
-
-inline Array* Array::AllocUninstrumented(Thread* self, Class* array_class, int32_t component_count) {
-  DCHECK(array_class->IsArrayClass());
-  return AllocUninstrumented(self, array_class, component_count, array_class->GetComponentSize());
+  return Alloc<kIsMovable, kIsInstrumented>(self, array_class, component_count,
+                                            array_class->GetComponentSize());
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 020085d..f8a2832 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -41,15 +41,16 @@
 // Recursively create an array with multiple dimensions.  Elements may be
 // Objects or primitive types.
 static Array* RecursiveCreateMultiArray(Thread* self, Class* array_class, int current_dimension,
-                                        IntArray* dimensions)
+                                        SirtRef<mirror::IntArray>& dimensions)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   int32_t array_length = dimensions->Get(current_dimension);
-  SirtRef<Array> new_array(self, Array::Alloc(self, array_class, array_length));
+  SirtRef<Array> new_array(self, Array::Alloc<kMovingCollector, true>(self, array_class,
+                                                                      array_length));
   if (UNLIKELY(new_array.get() == NULL)) {
     CHECK(self->IsExceptionPending());
     return NULL;
   }
-  if ((current_dimension + 1) < dimensions->GetLength()) {
+  if (current_dimension + 1 < dimensions->GetLength()) {
     // Create a new sub-array in every element of the array.
     for (int32_t i = 0; i < array_length; i++) {
       Array* sub_array = RecursiveCreateMultiArray(self, array_class->GetComponentType(),
@@ -87,13 +88,15 @@
 
   // Find/generate the array class.
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Class* array_class = class_linker->FindClass(descriptor.c_str(), element_class->GetClassLoader());
+  SirtRef<mirror::ClassLoader> class_loader(self, element_class->GetClassLoader());
+  Class* array_class = class_linker->FindClass(descriptor.c_str(), class_loader);
   if (UNLIKELY(array_class == NULL)) {
     CHECK(self->IsExceptionPending());
     return NULL;
   }
   // create the array
-  Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions);
+  SirtRef<mirror::IntArray> sirt_dimensions(self, dimensions);
+  Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, sirt_dimensions);
   if (UNLIKELY(new_array == NULL)) {
     CHECK(self->IsExceptionPending());
     return NULL;
@@ -112,7 +115,7 @@
 template<typename T>
 PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
   DCHECK(array_class_ != NULL);
-  Array* raw_array = Array::Alloc(self, array_class_, length, sizeof(T));
+  Array* raw_array = Array::Alloc<kMovingCollector, true>(self, array_class_, length, sizeof(T));
   return down_cast<PrimitiveArray<T>*>(raw_array);
 }
 
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index 570dcaa..584a4c0 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -24,28 +24,15 @@
 
 class MANAGED Array : public Object {
  public:
-  // A convenience for code that doesn't know the component size,
-  // and doesn't want to have to work it out itself.
+  // A convenience for code that doesn't know the component size, and doesn't want to have to work
+  // it out itself.
+  template <bool kIsMovable, bool kIsInstrumented>
   static Array* Alloc(Thread* self, Class* array_class, int32_t component_count)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return AllocInstrumented(self, array_class, component_count);
-  }
-  static Array* AllocUninstrumented(Thread* self, Class* array_class, int32_t component_count)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static Array* AllocInstrumented(Thread* self, Class* array_class, int32_t component_count)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  template <bool kIsMovable, bool kIsInstrumented>
   static Array* Alloc(Thread* self, Class* array_class, int32_t component_count,
-                      size_t component_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return AllocInstrumented(self, array_class, component_count, component_size);
-  }
-  static Array* AllocUninstrumented(Thread* self, Class* array_class, int32_t component_count,
-                                    size_t component_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  static Array* AllocInstrumented(Thread* self, Class* array_class, int32_t component_count,
-                                  size_t component_size)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+                      size_t component_size) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 7f3a302..406ab1b 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -357,14 +357,23 @@
   DCHECK_GE(this->object_size_, sizeof(Object));
 }
 
-inline Object* Class::AllocObjectInstrumented(Thread* self) {
+template <bool kIsMovable, bool kIsInstrumented>
+inline Object* Class::Alloc(Thread* self) {
   CheckObjectAlloc();
-  return Runtime::Current()->GetHeap()->AllocObjectInstrumented(self, this, this->object_size_);
-}
-
-inline Object* Class::AllocObjectUninstrumented(Thread* self) {
-  CheckObjectAlloc();
-  return Runtime::Current()->GetHeap()->AllocObjectUninstrumented(self, this, this->object_size_);
+  gc::Heap* heap = Runtime::Current()->GetHeap();
+  if (kIsMovable) {
+    if (kIsInstrumented) {
+      return heap->AllocMovableObjectInstrumented(self, this, this->object_size_);
+    } else {
+      return heap->AllocMovableObjectUninstrumented(self, this, this->object_size_);
+    }
+  } else {
+    if (kIsInstrumented) {
+      return heap->AllocNonMovableObjectInstrumented(self, this, this->object_size_);
+    } else {
+      return heap->AllocNonMovableObjectUninstrumented(self, this, this->object_size_);
+    }
+  }
 }
 
 }  // namespace mirror
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index f3cb54a..cdc5ab2 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -52,7 +52,8 @@
 
 void Class::SetStatus(Status new_status, Thread* self) {
   Status old_status = GetStatus();
-  bool class_linker_initialized = Runtime::Current()->GetClassLinker() != nullptr;
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  bool class_linker_initialized = class_linker != nullptr && class_linker->IsInitialized();
   if (LIKELY(class_linker_initialized)) {
     if (UNLIKELY(new_status <= old_status && new_status != kStatusError)) {
       LOG(FATAL) << "Unexpected change back of class status for " << PrettyClass(this) << " "
@@ -588,7 +589,6 @@
 ArtField* Class::FindStaticField(const StringPiece& name, const StringPiece& type) {
   // Is the field in this class (or its interfaces), or any of its
   // superclasses (or their interfaces)?
-  ClassHelper kh;
   for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
     // Is the field in this class?
     ArtField* f = k->FindDeclaredStaticField(name, type);
@@ -596,7 +596,7 @@
       return f;
     }
     // Is this field in any of this class' interfaces?
-    kh.ChangeClass(k);
+    ClassHelper kh(k);
     for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
       Class* interface = kh.GetDirectInterface(i);
       f = interface->FindStaticField(name, type);
@@ -609,7 +609,6 @@
 }
 
 ArtField* Class::FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx) {
-  ClassHelper kh;
   for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
     // Is the field in this class?
     ArtField* f = k->FindDeclaredStaticField(dex_cache, dex_field_idx);
@@ -617,7 +616,7 @@
       return f;
     }
     // Is this field in any of this class' interfaces?
-    kh.ChangeClass(k);
+    ClassHelper kh(k);
     for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
       Class* interface = kh.GetDirectInterface(i);
       f = interface->FindStaticField(dex_cache, dex_field_idx);
@@ -631,7 +630,6 @@
 
 ArtField* Class::FindField(const StringPiece& name, const StringPiece& type) {
   // Find a field using the JLS field resolution order
-  ClassHelper kh;
   for (Class* k = this; k != NULL; k = k->GetSuperClass()) {
     // Is the field in this class?
     ArtField* f = k->FindDeclaredInstanceField(name, type);
@@ -643,7 +641,7 @@
       return f;
     }
     // Is this field in any of this class' interfaces?
-    kh.ChangeClass(k);
+    ClassHelper kh(k);
     for (uint32_t i = 0; i < kh.NumDirectInterfaces(); ++i) {
       Class* interface = kh.GetDirectInterface(i);
       f = interface->FindStaticField(name, type);
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index ed1aad3..82077dc 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -378,11 +378,12 @@
 
   // Creates a raw object instance but does not invoke the default constructor.
   Object* AllocObject(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return AllocObjectInstrumented(self);
+    return Alloc<kMovingCollector, true>(self);
   }
 
-  Object* AllocObjectUninstrumented(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  Object* AllocObjectInstrumented(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  // Creates a raw object instance but does not invoke the default constructor.
+  template <bool kIsMovable, bool kIsInstrumented>
+  Object* Alloc(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsVariableSize() const {
     // Classes and arrays vary in size, and so the object_size_ field cannot
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 87d02c9..385ef5f 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -39,38 +39,48 @@
 namespace art {
 namespace mirror {
 
-Object* Object::Clone(Thread* self) {
-  mirror::Class* c = GetClass();
-  DCHECK(!c->IsClassClass());
-  // Object::SizeOf gets the right size even if we're an array.
-  // Using c->AllocObject() here would be wrong.
-  size_t num_bytes = SizeOf();
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  SirtRef<mirror::Object> sirt_this(self, this);
-  Object* copy = heap->AllocObject(self, c, num_bytes);
-  if (UNLIKELY(copy == nullptr)) {
-    return nullptr;
-  }
+static Object* CopyObject(Thread* self, mirror::Object* dest, mirror::Object* src, size_t num_bytes)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // Copy instance data.  We assume memcpy copies by words.
   // TODO: expose and use move32.
-  byte* src_bytes = reinterpret_cast<byte*>(sirt_this.get());
-  byte* dst_bytes = reinterpret_cast<byte*>(copy);
+  byte* src_bytes = reinterpret_cast<byte*>(src);
+  byte* dst_bytes = reinterpret_cast<byte*>(dest);
   size_t offset = sizeof(Object);
   memcpy(dst_bytes + offset, src_bytes + offset, num_bytes - offset);
+  gc::Heap* heap = Runtime::Current()->GetHeap();
   // Perform write barriers on copied object references.
-  c = copy->GetClass();  // Re-read Class in case it moved.
+  Class* c = src->GetClass();
   if (c->IsArrayClass()) {
     if (!c->GetComponentType()->IsPrimitive()) {
-      const ObjectArray<Object>* array = copy->AsObjectArray<Object>();
-      heap->WriteBarrierArray(copy, 0, array->GetLength());
+      const ObjectArray<Object>* array = dest->AsObjectArray<Object>();
+      heap->WriteBarrierArray(dest, 0, array->GetLength());
     }
   } else {
-    heap->WriteBarrierEveryFieldOf(copy);
+    heap->WriteBarrierEveryFieldOf(dest);
   }
   if (c->IsFinalizable()) {
-    SirtRef<mirror::Object> sirt_copy(self, copy);
-    heap->AddFinalizerReference(self, copy);
-    return sirt_copy.get();
+    SirtRef<Object> sirt_dest(self, dest);
+    heap->AddFinalizerReference(self, dest);
+    return sirt_dest.get();
+  }
+  return dest;
+}
+
+Object* Object::Clone(Thread* self) {
+  CHECK(!IsClass()) << "Can't clone classes.";
+  // Object::SizeOf gets the right size even if we're an array. Using c->AllocObject() here would
+  // be wrong.
+  gc::Heap* heap = Runtime::Current()->GetHeap();
+  size_t num_bytes = SizeOf();
+  SirtRef<Object> this_object(self, this);
+  Object* copy;
+  if (heap->IsMovableObject(this)) {
+    copy = heap->AllocObject(self, GetClass(), num_bytes);
+  } else {
+    copy = heap->AllocNonMovableObject(self, GetClass(), num_bytes);
+  }
+  if (LIKELY(copy != nullptr)) {
+    return CopyObject(self, copy, this_object.get(), num_bytes);
   }
   return copy;
 }
@@ -87,8 +97,9 @@
 }
 
 int32_t Object::IdentityHashCode() const {
+  mirror::Object* current_this = const_cast<mirror::Object*>(this);
   while (true) {
-    LockWord lw = GetLockWord();
+    LockWord lw = current_this->GetLockWord();
     switch (lw.GetState()) {
       case LockWord::kUnlocked: {
         // Try to compare and swap in a new hash, if we succeed we will return the hash on the next
@@ -103,7 +114,10 @@
       case LockWord::kThinLocked: {
         // Inflate the thin lock to a monitor and stick the hash code inside of the monitor.
         Thread* self = Thread::Current();
-        Monitor::InflateThinLocked(self, const_cast<Object*>(this), lw, GenerateIdentityHashCode());
+        SirtRef<mirror::Object> sirt_this(self, current_this);
+        Monitor::InflateThinLocked(self, sirt_this, lw, GenerateIdentityHashCode());
+        // A GC may have occurred when we switched to kBlocked.
+        current_this = sirt_this.get();
         break;
       }
       case LockWord::kFatLocked: {
@@ -115,6 +129,10 @@
       case LockWord::kHashCode: {
         return lw.GetHashCode();
       }
+      default: {
+        LOG(FATAL) << "Invalid state during hashcode " << lw.GetState();
+        break;
+      }
     }
   }
   LOG(FATAL) << "Unreachable";
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index e8ea3f2..0fb2039 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -30,6 +30,7 @@
 class Monitor;
 struct ObjectOffsets;
 class Thread;
+template <typename T> class SirtRef;
 
 namespace mirror {
 
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index abc88a3..478f4ec 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -23,6 +23,7 @@
 #include "mirror/art_field.h"
 #include "mirror/class.h"
 #include "runtime.h"
+#include "sirt_ref.h"
 #include "thread.h"
 
 namespace art {
@@ -30,7 +31,7 @@
 
 template<class T>
 inline 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*));
+  Array* array = Array::Alloc<kMovingCollector, true>(self, object_array_class, length, sizeof(Object*));
   if (UNLIKELY(array == NULL)) {
     return NULL;
   } else {
@@ -134,9 +135,11 @@
 
 template<class T>
 inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
+  // We may get copied by a compacting GC.
+  SirtRef<ObjectArray<T> > sirt_this(self, this);
   ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length);
-  if (LIKELY(new_array != NULL)) {
-    Copy(this, 0, new_array, 0, std::min(GetLength(), new_length));
+  if (LIKELY(new_array != nullptr)) {
+    Copy(sirt_this.get(), 0, new_array, 0, std::min(sirt_this->GetLength(), new_length));
   }
   return new_array;
 }
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index d0d1ee4..8530317 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -144,15 +144,15 @@
 TEST_F(ObjectTest, AllocArray) {
   ScopedObjectAccess soa(Thread::Current());
   Class* c = class_linker_->FindSystemClass("[I");
-  SirtRef<Array> a(soa.Self(), Array::Alloc(soa.Self(), c, 1));
+  SirtRef<Array> a(soa.Self(), Array::Alloc<kMovingCollector, true>(soa.Self(), c, 1));
   ASSERT_TRUE(c == a->GetClass());
 
   c = class_linker_->FindSystemClass("[Ljava/lang/Object;");
-  a.reset(Array::Alloc(soa.Self(), c, 1));
+  a.reset(Array::Alloc<kMovingCollector, true>(soa.Self(), c, 1));
   ASSERT_TRUE(c == a->GetClass());
 
   c = class_linker_->FindSystemClass("[[Ljava/lang/Object;");
-  a.reset(Array::Alloc(soa.Self(), c, 1));
+  a.reset(Array::Alloc<kMovingCollector, true>(soa.Self(), c, 1));
   ASSERT_TRUE(c == a->GetClass());
 }
 
@@ -269,8 +269,9 @@
   const DexFile* dex_file = Runtime::Current()->GetCompileTimeClassPath(class_loader)[0];
   CHECK(dex_file != NULL);
 
+  SirtRef<mirror::ClassLoader> loader(soa.Self(), soa.Decode<ClassLoader*>(class_loader));
   Class* klass =
-      class_linker_->FindClass("LStaticsFromCode;", soa.Decode<ClassLoader*>(class_loader));
+      class_linker_->FindClass("LStaticsFromCode;", loader);
   ArtMethod* clinit = klass->FindClassInitializer();
   const DexFile::StringId* klass_string_id = dex_file->FindStringId("LStaticsFromCode;");
   ASSERT_TRUE(klass_string_id != NULL);
@@ -392,6 +393,7 @@
 }
 
 TEST_F(ObjectTest, DescriptorCompare) {
+  // Two classloaders conflicts in compile_time_class_paths_.
   ScopedObjectAccess soa(Thread::Current());
   ClassLinker* linker = class_linker_;
 
@@ -400,9 +402,9 @@
   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());
+  Class* klass1 = linker->FindClass("LProtoCompare;", class_loader_1);
   ASSERT_TRUE(klass1 != NULL);
-  Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2.get());
+  Class* klass2 = linker->FindClass("LProtoCompare2;", class_loader_2);
   ASSERT_TRUE(klass2 != NULL);
 
   ArtMethod* m1_1 = klass1->GetVirtualMethod(0);
@@ -468,8 +470,8 @@
   jobject jclass_loader = LoadDex("XandY");
   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());
+  Class* X = class_linker_->FindClass("LX;", class_loader);
+  Class* Y = class_linker_->FindClass("LY;", class_loader);
   ASSERT_TRUE(X != NULL);
   ASSERT_TRUE(Y != NULL);
 
@@ -501,8 +503,8 @@
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("XandY");
   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());
+  Class* X = class_linker_->FindClass("LX;", class_loader);
+  Class* Y = class_linker_->FindClass("LY;", class_loader);
 
   EXPECT_TRUE(X->IsAssignableFrom(X));
   EXPECT_TRUE(X->IsAssignableFrom(Y));
@@ -538,17 +540,17 @@
   ScopedObjectAccess soa(Thread::Current());
   jobject jclass_loader = LoadDex("XandY");
   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());
+  Class* X = class_linker_->FindClass("LX;", class_loader);
+  Class* Y = class_linker_->FindClass("LY;", class_loader);
   ASSERT_TRUE(X != NULL);
   ASSERT_TRUE(Y != NULL);
 
-  Class* YA = class_linker_->FindClass("[LY;", class_loader.get());
-  Class* YAA = class_linker_->FindClass("[[LY;", class_loader.get());
+  Class* YA = class_linker_->FindClass("[LY;", class_loader);
+  Class* YAA = class_linker_->FindClass("[[LY;", class_loader);
   ASSERT_TRUE(YA != NULL);
   ASSERT_TRUE(YAA != NULL);
 
-  Class* XAA = class_linker_->FindClass("[[LX;", class_loader.get());
+  Class* XAA = class_linker_->FindClass("[[LX;", class_loader);
   ASSERT_TRUE(XAA != NULL);
 
   Class* O = class_linker_->FindSystemClass("Ljava/lang/Object;");
diff --git a/runtime/mirror/stack_trace_element.cc b/runtime/mirror/stack_trace_element.cc
index 9d76c6b..32a50fe 100644
--- a/runtime/mirror/stack_trace_element.cc
+++ b/runtime/mirror/stack_trace_element.cc
@@ -39,19 +39,19 @@
 }
 
 StackTraceElement* StackTraceElement::Alloc(Thread* self,
-                                            String* declaring_class,
-                                            String* method_name,
-                                            String* file_name,
+                                            SirtRef<String>& declaring_class,
+                                            SirtRef<String>& method_name,
+                                            SirtRef<String>& file_name,
                                             int32_t line_number) {
   StackTraceElement* trace =
       down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject(self));
   if (LIKELY(trace != NULL)) {
     trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
-                          const_cast<String*>(declaring_class), false);
+                          declaring_class.get(), false);
     trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
-                          const_cast<String*>(method_name), false);
+                          method_name.get(), false);
     trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
-                          const_cast<String*>(file_name), false);
+                          file_name.get(), false);
     trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_),
                       line_number, false);
   }
diff --git a/runtime/mirror/stack_trace_element.h b/runtime/mirror/stack_trace_element.h
index a9751f9..2af5128 100644
--- a/runtime/mirror/stack_trace_element.h
+++ b/runtime/mirror/stack_trace_element.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_MIRROR_STACK_TRACE_ELEMENT_H_
 
 #include "object.h"
+#include "sirt_ref.h"
 
 namespace art {
 
@@ -49,9 +50,9 @@
   }
 
   static StackTraceElement* Alloc(Thread* self,
-                                  String* declaring_class,
-                                  String* method_name,
-                                  String* file_name,
+                                  SirtRef<String>& declaring_class,
+                                  SirtRef<String>& method_name,
+                                  SirtRef<String>& file_name,
                                   int32_t line_number)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
diff --git a/runtime/mirror/string.cc b/runtime/mirror/string.cc
index 9c93f17..b372fe7 100644
--- a/runtime/mirror/string.cc
+++ b/runtime/mirror/string.cc
@@ -123,8 +123,8 @@
                                int32_t hash_code) {
   CHECK(utf16_data_in != NULL || utf16_length == 0);
   String* string = Alloc(self, GetJavaLangString(), utf16_length);
-  if (string == NULL) {
-    return NULL;
+  if (UNLIKELY(string == nullptr)) {
+    return nullptr;
   }
   // TODO: use 16-bit wide memset variant
   CharArray* array = const_cast<CharArray*>(string->GetCharArray());
@@ -143,8 +143,8 @@
 }
 
 String* String::AllocFromModifiedUtf8(Thread* self, const char* utf) {
-  if (utf == NULL) {
-    return NULL;
+  if (UNLIKELY(utf == nullptr)) {
+    return nullptr;
   }
   size_t char_count = CountModifiedUtf8Chars(utf);
   return AllocFromModifiedUtf8(self, char_count, utf);
@@ -153,8 +153,8 @@
 String* String::AllocFromModifiedUtf8(Thread* self, int32_t utf16_length,
                                       const char* utf8_data_in) {
   String* string = Alloc(self, GetJavaLangString(), utf16_length);
-  if (string == NULL) {
-    return NULL;
+  if (UNLIKELY(string == nullptr)) {
+    return nullptr;
   }
   uint16_t* utf16_data_out =
       const_cast<uint16_t*>(string->GetCharArray()->GetData());
@@ -164,22 +164,21 @@
 }
 
 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;
+  CharArray* array = CharArray::Alloc(self, utf16_length);
+  if (UNLIKELY(array == nullptr)) {
+    return nullptr;
   }
-  return Alloc(self, java_lang_String, array.get());
+  return Alloc(self, java_lang_String, array);
 }
 
 String* String::Alloc(Thread* self, Class* java_lang_String, CharArray* array) {
   // Hold reference in case AllocObject causes GC.
   SirtRef<CharArray> array_ref(self, array);
   String* string = down_cast<String*>(java_lang_String->AllocObject(self));
-  if (string == NULL) {
-    return NULL;
+  if (LIKELY(string != nullptr)) {
+    string->SetArray(array_ref.get());
+    string->SetCount(array_ref->GetLength());
   }
-  string->SetArray(array);
-  string->SetCount(array->GetLength());
   return string;
 }
 
diff --git a/runtime/mirror/string.h b/runtime/mirror/string.h
index 01d8f31..7520c4d 100644
--- a/runtime/mirror/string.h
+++ b/runtime/mirror/string.h
@@ -117,10 +117,8 @@
 
  private:
   void SetHashCode(int32_t new_hash_code) {
-    DCHECK_EQ(0u,
-              GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false));
-    SetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_),
-               new_hash_code, false);
+    DCHECK_EQ(0u, GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false));
+    SetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), new_hash_code, false);
   }
 
   void SetCount(int32_t new_count) {