summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libart/src/main/java/dalvik/system/VMRuntime.java7
-rw-r--r--libdvm/src/main/java/dalvik/system/VMRuntime.java51
-rw-r--r--luni/src/main/java/java/lang/reflect/Array.java12
-rw-r--r--luni/src/test/java/dalvik/system/VMRuntimeTest.java135
4 files changed, 199 insertions, 6 deletions
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 39cd326..7bbb93e 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -223,6 +223,13 @@ public final class VMRuntime {
public native Object newNonMovableArray(Class<?> componentType, int length);
/**
+ * Returns an array of at least minLength, but potentially larger. The increased size comes from
+ * avoiding any padding after the array. The amount of padding varies depending on the
+ * componentType and the memory allocator implementation.
+ */
+ public native Object newUnpaddedArray(Class<?> componentType, int minLength);
+
+ /**
* Returns the address of array[0]. This differs from using JNI in that JNI might lie and
* give you the address of a copy of the array when in forcecopy mode.
*/
diff --git a/libdvm/src/main/java/dalvik/system/VMRuntime.java b/libdvm/src/main/java/dalvik/system/VMRuntime.java
index f4acf47..47823f0 100644
--- a/libdvm/src/main/java/dalvik/system/VMRuntime.java
+++ b/libdvm/src/main/java/dalvik/system/VMRuntime.java
@@ -223,6 +223,57 @@ public final class VMRuntime {
public native Object newNonMovableArray(Class<?> componentType, int length);
/**
+ * Returns an array of at least minLength, but potentially larger. The increased size comes from
+ * avoiding any padding after the array. The amount of padding varies depending on the
+ * componentType and the memory allocator implementation.
+ */
+ public Object newUnpaddedArray(Class<?> componentType, int minLength) {
+ // Dalvik has 32bit pointers, the array header is 16bytes plus 4bytes for dlmalloc,
+ // allocations are 8byte aligned so having 4bytes of array data avoids padding.
+ if (!componentType.isPrimitive()) {
+ int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
+ return java.lang.reflect.Array.newInstance(componentType, size);
+ } else if (componentType == char.class) {
+ int bytes = 20 + (2 * minLength);
+ int alignedUpBytes = (bytes + 7) & -8;
+ int dataBytes = alignedUpBytes - 20;
+ int size = dataBytes / 2;
+ return new char[size];
+ } else if (componentType == int.class) {
+ int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
+ return new int[size];
+ } else if (componentType == byte.class) {
+ int bytes = 20 + minLength;
+ int alignedUpBytes = (bytes + 7) & -8;
+ int dataBytes = alignedUpBytes - 20;
+ int size = dataBytes;
+ return new byte[size];
+ } else if (componentType == boolean.class) {
+ int bytes = 20 + minLength;
+ int alignedUpBytes = (bytes + 7) & -8;
+ int dataBytes = alignedUpBytes - 20;
+ int size = dataBytes;
+ return new boolean[size];
+ } else if (componentType == short.class) {
+ int bytes = 20 + (2 * minLength);
+ int alignedUpBytes = (bytes + 7) & -8;
+ int dataBytes = alignedUpBytes - 20;
+ int size = dataBytes / 2;
+ return new short[size];
+ } else if (componentType == float.class) {
+ int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
+ return new float[size];
+ } else if (componentType == long.class) {
+ return new long[minLength];
+ } else if (componentType == double.class) {
+ return new double[minLength];
+ } else {
+ assert componentType == void.class;
+ throw new IllegalArgumentException("Can't allocate an array of void");
+ }
+ }
+
+ /**
* Returns the address of array[0]. This differs from using JNI in that JNI might lie and
* give you the address of a copy of the array when in forcecopy mode.
*/
diff --git a/luni/src/main/java/java/lang/reflect/Array.java b/luni/src/main/java/java/lang/reflect/Array.java
index 088a434..a7dacfe 100644
--- a/luni/src/main/java/java/lang/reflect/Array.java
+++ b/luni/src/main/java/java/lang/reflect/Array.java
@@ -352,16 +352,16 @@ public final class Array {
public static Object newInstance(Class<?> componentType, int size) throws NegativeArraySizeException {
if (!componentType.isPrimitive()) {
return createObjectArray(componentType, size);
- } else if (componentType == boolean.class) {
- return new boolean[size];
- } else if (componentType == byte.class) {
- return new byte[size];
} else if (componentType == char.class) {
return new char[size];
- } else if (componentType == short.class) {
- return new short[size];
} else if (componentType == int.class) {
return new int[size];
+ } else if (componentType == byte.class) {
+ return new byte[size];
+ } else if (componentType == boolean.class) {
+ return new boolean[size];
+ } else if (componentType == short.class) {
+ return new short[size];
} else if (componentType == long.class) {
return new long[size];
} else if (componentType == float.class) {
diff --git a/luni/src/test/java/dalvik/system/VMRuntimeTest.java b/luni/src/test/java/dalvik/system/VMRuntimeTest.java
new file mode 100644
index 0000000..44af461
--- /dev/null
+++ b/luni/src/test/java/dalvik/system/VMRuntimeTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dalvik.system;
+
+import java.lang.reflect.Array;
+import junit.framework.TestCase;
+
+/**
+ * Test VMRuntime behavior.
+ */
+public final class VMRuntimeTest extends TestCase {
+
+ private void doTestNewNonMovableArray(Class<?> componentType, int step, int maxLength) {
+ // Can't create negative sized arrays.
+ try {
+ Object array = VMRuntime.getRuntime().newNonMovableArray(componentType, -1);
+ assertTrue(false);
+ } catch (NegativeArraySizeException expected) {
+ }
+
+ try {
+ Object array = VMRuntime.getRuntime().newNonMovableArray(componentType, Integer.MIN_VALUE);
+ assertTrue(false);
+ } catch (NegativeArraySizeException expected) {
+ }
+
+ // Allocate arrays in a loop and check their properties.
+ for (int i = 0; i <= maxLength; i += step) {
+ Object array = VMRuntime.getRuntime().newNonMovableArray(componentType, i);
+ assertTrue(array.getClass().isArray());
+ assertEquals(array.getClass().getComponentType(), componentType);
+ assertEquals(Array.getLength(array), i);
+ }
+ }
+
+ public void testNewNonMovableArray() {
+ // Can't create arrays with no component type.
+ try {
+ Object array = VMRuntime.getRuntime().newNonMovableArray(null, 0);
+ assertTrue(false);
+ } catch (NullPointerException expected) {
+ }
+
+ // Can't create arrays of void.
+ try {
+ Object array = VMRuntime.getRuntime().newNonMovableArray(void.class, 0);
+ assertTrue(false);
+ } catch (IllegalArgumentException expected) {
+ }
+
+ int maxLengthForLoop = 16 * 1024;
+ int step = 67;
+ doTestNewNonMovableArray(boolean.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(byte.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(char.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(short.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(int.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(long.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(float.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(double.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(Object.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(Number.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(String.class, step, maxLengthForLoop);
+ doTestNewNonMovableArray(Runnable.class, step, maxLengthForLoop);
+ }
+
+ private void doTestNewUnpaddedArray(Class<?> componentType, int step, int maxLength) {
+ // Can't create negative sized arrays.
+ try {
+ Object array = VMRuntime.getRuntime().newUnpaddedArray(componentType, -1);
+ assertTrue(false);
+ } catch (NegativeArraySizeException expected) {
+ }
+
+ try {
+ Object array = VMRuntime.getRuntime().newUnpaddedArray(componentType, Integer.MIN_VALUE);
+ assertTrue(false);
+ } catch (NegativeArraySizeException expected) {
+ }
+
+ // Allocate arrays in a loop and check their properties.
+ for (int i = 0; i <= maxLength; i += step) {
+ Object array = VMRuntime.getRuntime().newUnpaddedArray(componentType, i);
+ assertTrue(array.getClass().isArray());
+ assertEquals(array.getClass().getComponentType(), componentType);
+ assertTrue(Array.getLength(array) >= i);
+ }
+ }
+
+ public void testNewUnpaddedArray() {
+ // Can't create arrays with no component type.
+ try {
+ Object array = VMRuntime.getRuntime().newUnpaddedArray(null, 0);
+ assertTrue(false);
+ } catch (NullPointerException expected) {
+ }
+
+ // Can't create arrays of void.
+ try {
+ Object array = VMRuntime.getRuntime().newUnpaddedArray(void.class, 0);
+ assertTrue(false);
+ } catch (IllegalArgumentException expected) {
+ }
+
+ int maxLengthForLoop = 16 * 1024;
+ int step = 67;
+ doTestNewUnpaddedArray(boolean.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(byte.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(char.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(short.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(int.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(long.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(float.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(double.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(Object.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(Number.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(String.class, step, maxLengthForLoop);
+ doTestNewUnpaddedArray(Runnable.class, step, maxLengthForLoop);
+ }
+}
+