Merge changes Ia8b678ab,I823201e3

* changes:
  ART: Move FillHeap to CommonRuntimeTest
  ART: Account for OOME during array merging
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 8dda04e..7e762c3 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -785,6 +785,60 @@
   return classpath;
 }
 
+void CommonRuntimeTestImpl::FillHeap(Thread* self,
+                                     ClassLinker* class_linker,
+                                     VariableSizedHandleScope* handle_scope) {
+  DCHECK(handle_scope != nullptr);
+
+  Runtime::Current()->GetHeap()->SetIdealFootprint(1 * GB);
+
+  // Class java.lang.Object.
+  Handle<mirror::Class> c(handle_scope->NewHandle(
+      class_linker->FindSystemClass(self, "Ljava/lang/Object;")));
+  // Array helps to fill memory faster.
+  Handle<mirror::Class> ca(handle_scope->NewHandle(
+      class_linker->FindSystemClass(self, "[Ljava/lang/Object;")));
+
+  // Start allocating with ~128K
+  size_t length = 128 * KB;
+  while (length > 40) {
+    const int32_t array_length = length / 4;  // Object[] has elements of size 4.
+    MutableHandle<mirror::Object> h(handle_scope->NewHandle<mirror::Object>(
+        mirror::ObjectArray<mirror::Object>::Alloc(self, ca.Get(), array_length)));
+    if (self->IsExceptionPending() || h == nullptr) {
+      self->ClearException();
+
+      // Try a smaller length
+      length = length / 2;
+      // Use at most a quarter the reported free space.
+      size_t mem = Runtime::Current()->GetHeap()->GetFreeMemory();
+      if (length * 4 > mem) {
+        length = mem / 4;
+      }
+    }
+  }
+
+  // Allocate simple objects till it fails.
+  while (!self->IsExceptionPending()) {
+    handle_scope->NewHandle<mirror::Object>(c->AllocObject(self));
+  }
+  self->ClearException();
+}
+
+void CommonRuntimeTestImpl::SetUpRuntimeOptionsForFillHeap(RuntimeOptions *options) {
+  // Use a smaller heap
+  bool found = false;
+  for (std::pair<std::string, const void*>& pair : *options) {
+    if (pair.first.find("-Xmx") == 0) {
+      pair.first = "-Xmx4M";  // Smallest we can go.
+      found = true;
+    }
+  }
+  if (!found) {
+    options->emplace_back("-Xmx4M", nullptr);
+  }
+}
+
 CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
   vm_->SetCheckJniAbortHook(Hook, &actual_);
 }
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index daf9ac3..74bc0b2 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -44,6 +44,8 @@
 class JavaVMExt;
 class Runtime;
 typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;
+class Thread;
+class VariableSizedHandleScope;
 
 uint8_t* DecodeBase64(const char* src, size_t* dst_size);
 
@@ -105,6 +107,14 @@
   // Retuerns the filename for a test dex (i.e. XandY or ManyMethods).
   std::string GetTestDexFileName(const char* name) const;
 
+  // A helper function to fill the heap.
+  static void FillHeap(Thread* self,
+                       ClassLinker* class_linker,
+                       VariableSizedHandleScope* handle_scope)
+      REQUIRES_SHARED(Locks::mutator_lock_);
+  // A helper to set up a small heap (4M) to make FillHeap faster.
+  static void SetUpRuntimeOptionsForFillHeap(RuntimeOptions *options);
+
  protected:
   // Allow subclases such as CommonCompilerTest to add extra options.
   virtual void SetUpRuntimeOptions(RuntimeOptions* options ATTRIBUTE_UNUSED) {}
diff --git a/runtime/monitor_test.cc b/runtime/monitor_test.cc
index 27ce149..fb12841 100644
--- a/runtime/monitor_test.cc
+++ b/runtime/monitor_test.cc
@@ -36,11 +36,8 @@
  protected:
   void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
     // Use a smaller heap
-    for (std::pair<std::string, const void*>& pair : *options) {
-      if (pair.first.find("-Xmx") == 0) {
-        pair.first = "-Xmx4M";  // Smallest we can go.
-      }
-    }
+    SetUpRuntimeOptionsForFillHeap(options);
+
     options->push_back(std::make_pair("-Xint", nullptr));
   }
  public:
@@ -56,52 +53,6 @@
   bool completed_;
 };
 
-// Fill the heap.
-static const size_t kMaxHandles = 1000000;  // Use arbitrary large amount for now.
-static void FillHeap(Thread* self, ClassLinker* class_linker,
-                     std::unique_ptr<StackHandleScope<kMaxHandles>>* hsp,
-                     std::vector<MutableHandle<mirror::Object>>* handles)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  Runtime::Current()->GetHeap()->SetIdealFootprint(1 * GB);
-
-  hsp->reset(new StackHandleScope<kMaxHandles>(self));
-  // Class java.lang.Object.
-  Handle<mirror::Class> c((*hsp)->NewHandle(class_linker->FindSystemClass(self,
-                                                                       "Ljava/lang/Object;")));
-  // Array helps to fill memory faster.
-  Handle<mirror::Class> ca((*hsp)->NewHandle(class_linker->FindSystemClass(self,
-                                                                        "[Ljava/lang/Object;")));
-
-  // Start allocating with 128K
-  size_t length = 128 * KB / 4;
-  while (length > 10) {
-    MutableHandle<mirror::Object> h((*hsp)->NewHandle<mirror::Object>(
-        mirror::ObjectArray<mirror::Object>::Alloc(self, ca.Get(), length / 4)));
-    if (self->IsExceptionPending() || h == nullptr) {
-      self->ClearException();
-
-      // Try a smaller length
-      length = length / 8;
-      // Use at most half the reported free space.
-      size_t mem = Runtime::Current()->GetHeap()->GetFreeMemory();
-      if (length * 8 > mem) {
-        length = mem / 8;
-      }
-    } else {
-      handles->push_back(h);
-    }
-  }
-
-  // Allocate simple objects till it fails.
-  while (!self->IsExceptionPending()) {
-    MutableHandle<mirror::Object> h = (*hsp)->NewHandle<mirror::Object>(c->AllocObject(self));
-    if (!self->IsExceptionPending() && h != nullptr) {
-      handles->push_back(h);
-    }
-  }
-  self->ClearException();
-}
-
 // Check that an exception can be thrown correctly.
 // This test is potentially racy, but the timeout is long enough that it should work.
 
@@ -304,16 +255,12 @@
   test->complete_barrier_ = std::unique_ptr<Barrier>(new Barrier(3));
   test->completed_ = false;
 
-  // Fill the heap.
-  std::unique_ptr<StackHandleScope<kMaxHandles>> hsp;
-  std::vector<MutableHandle<mirror::Object>> handles;
-
   // Our job: Fill the heap, then try Wait.
-  FillHeap(soa.Self(), class_linker, &hsp, &handles);
+  {
+    VariableSizedHandleScope vhs(soa.Self());
+    test->FillHeap(soa.Self(), class_linker, &vhs);
 
-  // Now release everything.
-  for (MutableHandle<mirror::Object>& h : handles) {
-    h.Assign(nullptr);
+    // Now release everything.
   }
 
   // Need to drop the mutator lock to allow barriers.
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 740b7dd..883de38 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -711,6 +711,29 @@
       DCHECK(c1 != nullptr && !c1->IsPrimitive());
       DCHECK(c2 != nullptr && !c2->IsPrimitive());
       mirror::Class* join_class = ClassJoin(c1, c2);
+      if (UNLIKELY(join_class == nullptr)) {
+        // Internal error joining the classes (e.g., OOME). Report an unresolved reference type.
+        // We cannot report an unresolved merge type, as that will attempt to merge the resolved
+        // components, leaving us in an infinite loop.
+        // We do not want to report the originating exception, as that would require a fast path
+        // out all the way to VerifyClass. Instead attempt to continue on without a detailed type.
+        Thread* self = Thread::Current();
+        self->AssertPendingException();
+        self->ClearException();
+
+        // When compiling on the host, we rather want to abort to ensure determinism for preopting.
+        // (In that case, it is likely a misconfiguration of dex2oat.)
+        if (!kIsTargetBuild && Runtime::Current()->IsAotCompiler()) {
+          LOG(FATAL) << "Could not create class join of "
+                     << c1->PrettyClass()
+                     << " & "
+                     << c2->PrettyClass();
+          UNREACHABLE();
+        }
+
+        return reg_types->MakeUnresolvedReference();
+      }
+
       // Record the dependency that both `c1` and `c2` are assignable to `join_class`.
       // The `verifier` is null during unit tests.
       if (verifier != nullptr) {
@@ -753,10 +776,18 @@
       DCHECK(result->IsObjectClass());
       return result;
     }
+    Thread* self = Thread::Current();
     ObjPtr<mirror::Class> common_elem = ClassJoin(s_ct, t_ct);
+    if (UNLIKELY(common_elem == nullptr)) {
+      self->AssertPendingException();
+      return nullptr;
+    }
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    mirror::Class* array_class = class_linker->FindArrayClass(Thread::Current(), &common_elem);
-    DCHECK(array_class != nullptr);
+    mirror::Class* array_class = class_linker->FindArrayClass(self, &common_elem);
+    if (UNLIKELY(array_class == nullptr)) {
+      self->AssertPendingException();
+      return nullptr;
+    }
     return array_class;
   } else {
     size_t s_depth = s->Depth();
diff --git a/runtime/verifier/reg_type.h b/runtime/verifier/reg_type.h
index 6c01a79..c5d8ff5 100644
--- a/runtime/verifier/reg_type.h
+++ b/runtime/verifier/reg_type.h
@@ -355,6 +355,10 @@
    * the perversion of Object being assignable to an interface type (note, however, that we don't
    * allow assignment of Object or Interface to any concrete class and are therefore type safe).
    *
+   * Note: This may return null in case of internal errors, e.g., OOME when a new class would have
+   *       to be created but there is no heap space. The exception will stay pending, and it is
+   *       the job of the caller to handle it.
+   *
    * [1] Java bytecode verification: algorithms and formalizations, Xavier Leroy
    */
   static mirror::Class* ClassJoin(mirror::Class* s, mirror::Class* t)
diff --git a/runtime/verifier/reg_type_cache.cc b/runtime/verifier/reg_type_cache.cc
index 93286ea..0c00868 100644
--- a/runtime/verifier/reg_type_cache.cc
+++ b/runtime/verifier/reg_type_cache.cc
@@ -222,6 +222,11 @@
   }
 }
 
+const RegType& RegTypeCache::MakeUnresolvedReference() {
+  // The descriptor is intentionally invalid so nothing else will match this type.
+  return AddEntry(new (&arena_) UnresolvedReferenceType(AddString("a"), entries_.size()));
+}
+
 const RegType* RegTypeCache::FindClass(mirror::Class* klass, bool precise) const {
   DCHECK(klass != nullptr);
   if (klass->IsPrimitive()) {
diff --git a/runtime/verifier/reg_type_cache.h b/runtime/verifier/reg_type_cache.h
index 37f8a1f..c9bf6a9 100644
--- a/runtime/verifier/reg_type_cache.h
+++ b/runtime/verifier/reg_type_cache.h
@@ -97,6 +97,10 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
   const RegType& FromUnresolvedSuperClass(const RegType& child)
       REQUIRES_SHARED(Locks::mutator_lock_);
+
+  // Note: this should not be used outside of RegType::ClassJoin!
+  const RegType& MakeUnresolvedReference() REQUIRES_SHARED(Locks::mutator_lock_);
+
   const ConstantType& Zero() REQUIRES_SHARED(Locks::mutator_lock_) {
     return FromCat1Const(0, true);
   }
diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc
index b0ea6c8..fef13a2 100644
--- a/runtime/verifier/reg_type_test.cc
+++ b/runtime/verifier/reg_type_test.cc
@@ -22,6 +22,7 @@
 #include "base/casts.h"
 #include "base/scoped_arena_allocator.h"
 #include "common_runtime_test.h"
+#include "compiler_callbacks.h"
 #include "reg_type_cache-inl.h"
 #include "reg_type-inl.h"
 #include "scoped_thread_state_change-inl.h"
@@ -677,5 +678,56 @@
   EXPECT_FALSE(imprecise_const.Equals(precise_const));
 }
 
+class RegTypeOOMTest : public RegTypeTest {
+ protected:
+  void SetUpRuntimeOptions(RuntimeOptions *options) OVERRIDE {
+    SetUpRuntimeOptionsForFillHeap(options);
+
+    // We must not appear to be a compiler, or we'll abort on the host.
+    callbacks_.reset();
+  }
+};
+
+TEST_F(RegTypeOOMTest, ClassJoinOOM) {
+  // Tests that we don't abort with OOMs.
+
+  ArenaStack stack(Runtime::Current()->GetArenaPool());
+  ScopedArenaAllocator allocator(&stack);
+  ScopedObjectAccess soa(Thread::Current());
+
+  // We cannot allow moving GC. Otherwise we'd have to ensure the reg types are updated (reference
+  // reg types store a class pointer in a GCRoot, which is normally updated through active verifiers
+  // being registered with their thread), which is unnecessarily complex.
+  Runtime::Current()->GetHeap()->IncrementDisableMovingGC(soa.Self());
+
+  // We merge nested array of primitive wrappers. These have a join type of an array of Number of
+  // the same depth. We start with depth five, as we want at least two newly created classes to
+  // test recursion (it's just more likely that nobody uses such deep arrays in runtime bringup).
+  constexpr const char* kIntArrayFive = "[[[[[Ljava/lang/Integer;";
+  constexpr const char* kFloatArrayFive = "[[[[[Ljava/lang/Float;";
+  constexpr const char* kNumberArrayFour = "[[[[Ljava/lang/Number;";
+  constexpr const char* kNumberArrayFive = "[[[[[Ljava/lang/Number;";
+
+  RegTypeCache cache(true, allocator);
+  const RegType& int_array_array = cache.From(nullptr, kIntArrayFive, false);
+  ASSERT_TRUE(int_array_array.HasClass());
+  const RegType& float_array_array = cache.From(nullptr, kFloatArrayFive, false);
+  ASSERT_TRUE(float_array_array.HasClass());
+
+  // Check assumptions: the joined classes don't exist, yet.
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  ASSERT_TRUE(class_linker->LookupClass(soa.Self(), kNumberArrayFour, nullptr) == nullptr);
+  ASSERT_TRUE(class_linker->LookupClass(soa.Self(), kNumberArrayFive, nullptr) == nullptr);
+
+  // Fill the heap.
+  VariableSizedHandleScope hs(soa.Self());
+  FillHeap(soa.Self(), class_linker, &hs);
+
+  const RegType& join_type = int_array_array.Merge(float_array_array, &cache, nullptr);
+  ASSERT_TRUE(join_type.IsUnresolvedReference());
+
+  Runtime::Current()->GetHeap()->DecrementDisableMovingGC(soa.Self());
+}
+
 }  // namespace verifier
 }  // namespace art