Implement the "unreasonable array allocation" OutOfMemoryError.

This doesn't fix test 061 because we still need AllocWithGrowth, but at least
it gets us far enough to need that.

Change-Id: Ia7b4a1f91a31e25d439f36b17280ce21c9ed8933
diff --git a/src/object.cc b/src/object.cc
index 8fc4108..49d689c 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -1220,12 +1220,30 @@
   DCHECK(array_class != NULL);
   DCHECK_GE(component_count, 0);
   DCHECK(array_class->IsArrayClass());
-  size_t size = SizeOf(component_count, component_size);
+
+  size_t header_size = sizeof(Array);
+  size_t data_size = component_count * component_size;
+  size_t size = header_size + data_size;
+
+  // Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
+  size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size);
+  if (data_size >> component_shift != size_t(component_count) || size < data_size) {
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/OutOfMemoryError;",
+        "%s of length %zd exceeds the VM limit",
+        PrettyDescriptor(array_class->GetDescriptor()).c_str(), component_count);
+    return NULL;
+  }
+
   Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size));
   if (array != NULL) {
     DCHECK(array->IsArrayInstance());
     array->SetLength(component_count);
   }
+
+  // TODO: throw OutOfMemoryError. (here or in Heap::AllocObject?)
+  CHECK(array != NULL) << PrettyClass(array_class)
+                       << " component_count=" << component_count
+                       << " component_size=" << component_size;
   return array;
 }