Support in VMRuntime for allocating "unpadded" arrays.

Bug: 13028925.

Change-Id: I0a53645f0468aaf44d38aabe016cb610fcfefaf7
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 3da7409..754d1dd 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -46,6 +46,7 @@
       return array_class;
     }
   }
+  DCHECK(!element_class->IsPrimitiveVoid());
   std::string descriptor("[");
   descriptor += ClassHelper(element_class).GetDescriptor();
   SirtRef<mirror::ClassLoader> class_loader(self, element_class->GetClassLoader());
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 3c703ba..decbc66 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -56,13 +56,17 @@
 static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaElementClass,
                                             jint length) {
   ScopedFastNativeObjectAccess soa(env);
+  if (UNLIKELY(length < 0)) {
+    ThrowNegativeArraySizeException(length);
+    return nullptr;
+  }
   mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
   if (UNLIKELY(element_class == nullptr)) {
     ThrowNullPointerException(NULL, "element class == null");
     return nullptr;
   }
-  if (UNLIKELY(length < 0)) {
-    ThrowNegativeArraySizeException(length);
+  if (UNLIKELY(element_class->IsPrimitiveVoid())) {
+    ThrowIllegalArgumentException(NULL, "Can't allocate an array of void");
     return nullptr;
   }
   Runtime* runtime = Runtime::Current();
@@ -76,6 +80,34 @@
   return soa.AddLocalReference<jobject>(result);
 }
 
+static jobject VMRuntime_newUnpaddedArray(JNIEnv* env, jobject, jclass javaElementClass,
+                                          jint length) {
+  ScopedFastNativeObjectAccess soa(env);
+  if (UNLIKELY(length < 0)) {
+    ThrowNegativeArraySizeException(length);
+    return nullptr;
+  }
+  mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
+  if (UNLIKELY(element_class == nullptr)) {
+    ThrowNullPointerException(NULL, "element class == null");
+    return nullptr;
+  }
+  if (UNLIKELY(element_class->IsPrimitiveVoid())) {
+    ThrowIllegalArgumentException(NULL, "Can't allocate an array of void");
+    return nullptr;
+  }
+  Runtime* runtime = Runtime::Current();
+  mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
+  if (UNLIKELY(array_class == nullptr)) {
+    return nullptr;
+  }
+  gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
+  mirror::Array* result = mirror::Array::Alloc<true>(soa.Self(), array_class, length,
+                                                     array_class->GetComponentSize(), allocator,
+                                                     true);
+  return soa.AddLocalReference<jobject>(result);
+}
+
 static jlong VMRuntime_addressOf(JNIEnv* env, jobject, jobject javaArray) {
   if (javaArray == NULL) {  // Most likely allocation failed
     return 0;
@@ -497,6 +529,7 @@
   NATIVE_METHOD(VMRuntime, isDebuggerActive, "()Z"),
   NATIVE_METHOD(VMRuntime, nativeSetTargetHeapUtilization, "(F)V"),
   NATIVE_METHOD(VMRuntime, newNonMovableArray, "!(Ljava/lang/Class;I)Ljava/lang/Object;"),
+  NATIVE_METHOD(VMRuntime, newUnpaddedArray, "!(Ljava/lang/Class;I)Ljava/lang/Object;"),
   NATIVE_METHOD(VMRuntime, properties, "()[Ljava/lang/String;"),
   NATIVE_METHOD(VMRuntime, setTargetSdkVersionNative, "(I)V"),
   NATIVE_METHOD(VMRuntime, registerNativeAllocation, "(I)V"),