Merge "Fix infinite loop when calling SetStatus after OOM."
diff --git a/runtime/gc/accounting/card_table.cc b/runtime/gc/accounting/card_table.cc
index a95c003..ceb42e5 100644
--- a/runtime/gc/accounting/card_table.cc
+++ b/runtime/gc/accounting/card_table.cc
@@ -83,8 +83,6 @@
 
 CardTable::CardTable(MemMap* mem_map, byte* biased_begin, size_t offset)
     : mem_map_(mem_map), biased_begin_(biased_begin), offset_(offset) {
-  byte* __attribute__((unused)) begin = mem_map_->Begin() + offset_;
-  byte* __attribute__((unused)) end = mem_map_->End();
 }
 
 void CardTable::ClearSpaceCards(space::ContinuousSpace* space) {
diff --git a/runtime/gc/heap-inl.h b/runtime/gc/heap-inl.h
index 419af30..7d3fd2d 100644
--- a/runtime/gc/heap-inl.h
+++ b/runtime/gc/heap-inl.h
@@ -63,6 +63,7 @@
   // If we have a thread local allocation we don't need to update bytes allocated.
   if (allocator == kAllocatorTypeTLAB && byte_count <= self->TlabSize()) {
     obj = self->AllocTlab(byte_count);
+    DCHECK(obj != nullptr) << "AllocTlab can't fail";
     obj->SetClass(klass);
     if (kUseBakerOrBrooksReadBarrier) {
       if (kUseBrooksReadBarrier) {
@@ -71,7 +72,8 @@
       obj->AssertReadBarrierPointer();
     }
     bytes_allocated = byte_count;
-    pre_fence_visitor(obj, bytes_allocated);
+    usable_size = bytes_allocated;
+    pre_fence_visitor(obj, usable_size);
     QuasiAtomic::ThreadFenceForConstructor();
   } else {
     obj = TryToAllocate<kInstrumented, false>(self, allocator, byte_count, &bytes_allocated,
@@ -111,13 +113,13 @@
       WriteBarrierField(obj, mirror::Object::ClassOffset(), klass);
     }
     pre_fence_visitor(obj, usable_size);
-    if (kIsDebugBuild && Runtime::Current()->IsStarted()) {
-      CHECK_LE(obj->SizeOf(), usable_size);
-    }
     new_num_bytes_allocated =
         static_cast<size_t>(num_bytes_allocated_.FetchAndAddSequentiallyConsistent(bytes_allocated))
         + bytes_allocated;
   }
+  if (kIsDebugBuild && Runtime::Current()->IsStarted()) {
+    CHECK_LE(obj->SizeOf(), usable_size);
+  }
   // TODO: Deprecate.
   if (kInstrumented) {
     if (Runtime::Current()->HasStatsEnabled()) {
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 371e984..be05fb8 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -88,18 +88,22 @@
     Handle<mirror::ArtMethod> old_throw_method(hs.NewHandle(old_throw_location.GetMethod()));
     uint32_t old_throw_dex_pc = old_throw_location.GetDexPc();
     bool is_exception_reported = self->IsExceptionReportedToInstrumentation();
-    // clear exception to call FindSystemClass
-    self->ClearException();
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    Class* eiie_class = class_linker->FindSystemClass(self,
-                                                      "Ljava/lang/ExceptionInInitializerError;");
-    CHECK(!self->IsExceptionPending());
-
-    // Only verification errors, not initialization problems, should set a verify error.
-    // This is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case.
-    Class* exception_class = old_exception->GetClass();
-    if (!eiie_class->IsAssignableFrom(exception_class)) {
-      SetVerifyErrorClass(exception_class);
+    Class* eiie_class;
+    // Do't attempt to use FindClass if we have an OOM error since this can try to do more
+    // allocations and may cause infinite loops.
+    if (old_exception.Get() == nullptr ||
+        old_exception->GetClass()->GetDescriptor() != "Ljava/lang/OutOfMemoryError;") {
+      // Clear exception to call FindSystemClass.
+      self->ClearException();
+      eiie_class = Runtime::Current()->GetClassLinker()->FindSystemClass(
+          self, "Ljava/lang/ExceptionInInitializerError;");
+      CHECK(!self->IsExceptionPending());
+      // Only verification errors, not initialization problems, should set a verify error.
+      // This is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case.
+      Class* exception_class = old_exception->GetClass();
+      if (!eiie_class->IsAssignableFrom(exception_class)) {
+        SetVerifyErrorClass(exception_class);
+      }
     }
 
     // Restore exception.