diff options
author | Andy McFadden <fadden@android.com> | 2011-02-02 16:55:41 -0800 |
---|---|---|
committer | Andy McFadden <fadden@android.com> | 2011-02-04 15:54:59 -0800 |
commit | d6e32b8147f26a32059ae86abc5f8e5c0ef92ac1 (patch) | |
tree | 053397a2a4a4a8061f28de78a4d1817da91c399b /tests | |
parent | 13a0e7b2e9b4cd0eb09a3cfa156b82e11671e116 (diff) | |
download | android_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.txt | 11 | ||||
-rw-r--r-- | tests/011-array-copy/src/Main.java | 105 |
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); + } } |