summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorAndy McFadden <fadden@android.com>2011-02-02 16:55:41 -0800
committerAndy McFadden <fadden@android.com>2011-02-04 15:54:59 -0800
commitd6e32b8147f26a32059ae86abc5f8e5c0ef92ac1 (patch)
tree053397a2a4a4a8061f28de78a4d1817da91c399b /tests
parent13a0e7b2e9b4cd0eb09a3cfa156b82e11671e116 (diff)
downloadandroid_dalvik-d6e32b8147f26a32059ae86abc5f8e5c0ef92ac1.tar.gz
android_dalvik-d6e32b8147f26a32059ae86abc5f8e5c0ef92ac1.tar.bz2
android_dalvik-d6e32b8147f26a32059ae86abc5f8e5c0ef92ac1.zip
Ensure word atomicity in System.arraycopy
The VM needs to ensure that updates to 16-bit and 32-bit fields and array elements happen atomically. System.arraycopy was calling memmmove(), which in bionic happens to copy a byte at a time. The new plan is to have bionic provide a platform-optimized memmove variant that makes guarantees about word sizes. If it is not present (either because it hasn't been written for the current platform, or we're not linking against bionic), we will use a trivial copy loop. We assume that the memmove-by-word implementation does whatever it needs to for best performance. For example, if the function determines that memcpy() is word-safe and will be faster, it can call that. The VM no longer makes assumptions about the internal workings of libc functions. I also rearranged the code to avoid making indirect calls, reading function addresses from memory, and using integer multiplication instructions when a simple shift will do. (gcc now generates the whole thing as one function.) Also, added some primitive array copy tests to 011-array-copy. Bug 3398352 Change-Id: I4677ee1c87998697a93e61f39a48b3f391e8e11b
Diffstat (limited to 'tests')
-rw-r--r--tests/011-array-copy/expected.txt11
-rw-r--r--tests/011-array-copy/src/Main.java105
2 files changed, 116 insertions, 0 deletions
diff --git a/tests/011-array-copy/expected.txt b/tests/011-array-copy/expected.txt
index 0ef202995..724786ee3 100644
--- a/tests/011-array-copy/expected.txt
+++ b/tests/011-array-copy/expected.txt
@@ -2,3 +2,14 @@ string -> object
object -> string
object -> string (modified)
caught ArrayStoreException (expected)
+copy: 0,0,0: [0, 1, 2, 3, 4, 5, 6, 7]
+copy: 0,0,8: [0, 1, 2, 3, 4, 5, 6, 7]
+copy: 0,2,4: [0, 1, 0, 1, 2, 3, 6, 7]
+copy: 2,0,4: [2, 3, 4, 5, 4, 5, 6, 7]
+copy: 1,3,4: [0, 1, 2, 1, 2, 3, 4, 7]
+copy: 3,1,4: [0, 3, 4, 5, 6, 5, 6, 7]
+copy: 3,1,5: [0, 3, 4, 5, 6, 7, 6, 7]
+copy: 1,3,5: [0, 1, 2, 1, 2, 3, 4, 5]
+copy: 0,3,5: [0, 1, 2, 0, 1, 2, 3, 4]
+copy: 3,0,5: [3, 4, 5, 6, 7, 5, 6, 7]
+copy: 0,5,1: [0, 1, 2, 3, 4, 0, 6, 7]
diff --git a/tests/011-array-copy/src/Main.java b/tests/011-array-copy/src/Main.java
index 9cb8238fe..505d8b09c 100644
--- a/tests/011-array-copy/src/Main.java
+++ b/tests/011-array-copy/src/Main.java
@@ -14,11 +14,18 @@
* limitations under the License.
*/
+import java.util.Arrays;
+
/**
* System.arraycopy cases
*/
public class Main {
public static void main(String args[]) {
+ testObjectCopy();
+ testOverlappingMoves();
+ }
+
+ public static void testObjectCopy() {
String[] stringArray = new String[8];
Object[] objectArray = new Object[8];
@@ -38,4 +45,102 @@ public class Main {
System.out.println("caught ArrayStoreException (expected)");
}
}
+
+ static final int ARRAY_SIZE = 8;
+
+ static void initByteArray(byte[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (byte) i;
+ }
+ }
+ static void initShortArray(short[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (short) i;
+ }
+ }
+ static void initIntArray(int[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (int) i;
+ }
+ }
+ static void initLongArray(long[] array) {
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ array[i] = (long) i;
+ }
+ }
+
+ /*
+ * Perform an array copy operation on primitive arrays with different
+ * element widths.
+ */
+ static void makeCopies(int srcPos, int dstPos, int length) {
+ byte[] byteArray = new byte[ARRAY_SIZE];
+ short[] shortArray = new short[ARRAY_SIZE];
+ int[] intArray = new int[ARRAY_SIZE];
+ long[] longArray = new long[ARRAY_SIZE];
+
+ initByteArray(byteArray);
+ initShortArray(shortArray);
+ initIntArray(intArray);
+ initLongArray(longArray);
+
+ System.arraycopy(byteArray, srcPos, byteArray, dstPos, length);
+ System.arraycopy(shortArray, srcPos, shortArray, dstPos, length);
+ System.arraycopy(intArray, srcPos, intArray, dstPos, length);
+ System.arraycopy(longArray, srcPos, longArray, dstPos, length);
+
+ for (int i = 0; i < ARRAY_SIZE; i++) {
+ if (intArray[i] != byteArray[i]) {
+ System.out.println("mismatch int vs byte at " + i + " : " +
+ Arrays.toString(byteArray));
+ break;
+ } else if (intArray[i] != shortArray[i]) {
+ System.out.println("mismatch int vs short at " + i + " : " +
+ Arrays.toString(shortArray));
+ break;
+ } else if (intArray[i] != longArray[i]) {
+ System.out.println("mismatch int vs long at " + i + " : " +
+ Arrays.toString(longArray));
+ break;
+ }
+ }
+
+ System.out.println("copy: " + srcPos + "," + dstPos + "," + length +
+ ": " + Arrays.toString(intArray));
+ }
+
+ public static void testOverlappingMoves() {
+ /* do nothing */
+ makeCopies(0, 0, 0);
+
+ /* do more nothing */
+ makeCopies(0, 0, ARRAY_SIZE);
+
+ /* copy forward, even alignment */
+ makeCopies(0, 2, 4);
+
+ /* copy backward, even alignment */
+ makeCopies(2, 0, 4);
+
+ /* copy forward, odd alignment */
+ makeCopies(1, 3, 4);
+
+ /* copy backward, odd alignment */
+ makeCopies(3, 1, 4);
+
+ /* copy backward, odd length */
+ makeCopies(3, 1, 5);
+
+ /* copy forward, odd length */
+ makeCopies(1, 3, 5);
+
+ /* copy forward, mixed alignment */
+ makeCopies(0, 3, 5);
+
+ /* copy backward, mixed alignment */
+ makeCopies(3, 0, 5);
+
+ /* copy forward, mixed alignment, trivial length */
+ makeCopies(0, 5, 1);
+ }
}