/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.runtime; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_BYTE; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_INT; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_LONG; import static org.jikesrvm.runtime.JavaSizeConstants.BYTES_IN_SHORT; import static org.junit.Assert.fail; import org.jikesrvm.VM; import org.jikesrvm.junit.runners.RequiresBuiltJikesRVM; import org.jikesrvm.junit.runners.VMRequirements; import org.junit.BeforeClass; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; import org.vmmagic.unboxed.Address; @RunWith(VMRequirements.class) @Category(RequiresBuiltJikesRVM.class) public class MemoryTest { private static int nativeThreshold; private static int arrayLength; @BeforeClass public static void setup() { if (!VM.runningVM) return; nativeThreshold = Memory.getNativeThreshold(); arrayLength = nativeThreshold * 2; } @Test public void testOverlappingCopyOfByteArrayFromGreaterToLesserPosition() { byte[] largeByteArray = initializeByteArray(); int copyLength = (arrayLength * 7) / 9; int copyStart = arrayLength - copyLength; int copyDest = (arrayLength) / 9; byte srcPosValue = largeByteArray[copyStart]; doAligned8CopyForBytes(largeByteArray, copyStart, copyLength, copyDest); verifyThatCopyingToByteArrayWasCorrect(largeByteArray, copyLength, copyDest, srcPosValue); } private void verifyThatCopyingToByteArrayWasCorrect(byte[] largeByteArray, int copyLength, int copyDest, byte srcPosValue) { for (int i = copyDest; i < copyLength; i++) { if (largeByteArray[i] != srcPosValue) { fail("Expected " + srcPosValue + " but was " + largeByteArray[i] + " at pos " + i + ". This means that parts of the byte array were overwritten"); break; } srcPosValue++; } } private void doAligned8CopyForBytes(byte[] largeByteArray, int copyStart, int copyLength, int copyDest) { VM.disableGC(); Address arrayStart = Magic.objectAsAddress(largeByteArray); Address copyStartAddress = arrayStart.plus(copyStart * BYTES_IN_BYTE); Address copyDestAddress = arrayStart.plus(copyDest * BYTES_IN_BYTE); int copyBytes = copyLength * BYTES_IN_BYTE; Memory.aligned8Copy(copyDestAddress, copyStartAddress, copyBytes); VM.enableGC(); } private byte[] initializeByteArray() { byte[] largeByteArray = new byte[arrayLength]; byte startValue = Byte.MIN_VALUE; byte value = startValue; for (int i = 0; i < largeByteArray.length; i++) { largeByteArray[i] = value; value++; } return largeByteArray; } @Test public void testOverlappingCopyOfShortArrayFromGreaterToLesserPosition() { short[] largeShortArray = initializeShortArray(); int copyLength = (arrayLength * 7) / 9; int copyStart = arrayLength - copyLength; int copyDest = (arrayLength) / 9; short srcPosValue = largeShortArray[copyStart]; doAligned16BitCopyForShorts(largeShortArray, copyStart, copyLength, copyDest); verifyThatCopyingToShortArrayWasCorrect( largeShortArray, copyLength, copyDest, srcPosValue); } private short verifyThatCopyingToShortArrayWasCorrect( short[] largeShortArray, int copyLength, int copyDest, short srcPosValue) { for (int i = copyDest; i < copyLength; i++) { if (largeShortArray[i] != srcPosValue) { fail("Expected + " + srcPosValue + " but was " + largeShortArray[i] + " at pos " + i + ". This means that parts of the short array were overwritten"); break; } srcPosValue++; } return srcPosValue; } private void doAligned16BitCopyForShorts(short[] largeShortArray, int copyStart, int copyLength, int copyDest) { VM.disableGC(); Address arrayStart = Magic.objectAsAddress(largeShortArray); Address copyStartAddress = arrayStart.plus(copyStart * BYTES_IN_SHORT); Address copyDestAddress = arrayStart.plus(copyDest * BYTES_IN_SHORT); int copyBytes = copyLength * BYTES_IN_SHORT; Memory.aligned16Copy(copyDestAddress, copyStartAddress, copyBytes); VM.enableGC(); } private short[] initializeShortArray() { short[] largeShortArray = new short[arrayLength]; short startValue = Short.MIN_VALUE; short value = startValue; for (int i = 0; i < largeShortArray.length; i++) { largeShortArray[i] = value; value++; } return largeShortArray; } @Test public void testOverlappingCopyOfIntArrayFromGreaterToLesserPosition() { int[] largeIntArray = initializeIntArray(); int copyLength = (arrayLength * 7) / 9; int copyStart = arrayLength - copyLength; int copyDest = (arrayLength) / 9; int srcPosValue = largeIntArray[copyStart]; doAligned32CopyForInts(largeIntArray, copyStart, copyLength, copyDest); verifyThatCopyingToIntArrayWasCorrect(largeIntArray, copyLength, copyDest, srcPosValue); } private int verifyThatCopyingToIntArrayWasCorrect(int[] largeIntArray, int copyLength, int copyDest, int srcPosValue) { for (int i = copyDest; i < copyLength; i++) { if (largeIntArray[i] != srcPosValue) { fail("Expected + " + srcPosValue + " but was " + largeIntArray[i] + " at pos " + i + ". This means that parts of the int array were overwritten"); break; } srcPosValue++; } return srcPosValue; } private void doAligned32CopyForInts(int[] largeIntArray, int copyStart, int copyLength, int copyDest) { VM.disableGC(); Address arrayStart = Magic.objectAsAddress(largeIntArray); Address copyStartAddress = arrayStart.plus(copyStart * BYTES_IN_INT); Address copyDestAddress = arrayStart.plus(copyDest * BYTES_IN_INT); int copyBytes = copyLength * BYTES_IN_INT; Memory.aligned32Copy(copyDestAddress, copyStartAddress, copyBytes); VM.enableGC(); } private int[] initializeIntArray() { int[] largeIntArray = new int[arrayLength]; int startValue = Integer.MIN_VALUE; int value = startValue; for (int i = 0; i < largeIntArray.length; i++) { largeIntArray[i] = value; value++; } return largeIntArray; } @Test public void testOverlappingCopyOfLongArrayFromGreaterToLesserPosition() { long[] largeLongArray = initializeLongArray(); int copyLength = (arrayLength * 7) / 9; int copyStart = arrayLength - copyLength; int copyDest = (arrayLength) / 9; long srcPosValue = largeLongArray[copyStart]; doAligned64CopyForLongs(largeLongArray, copyStart, copyLength, copyDest); verifiyThatCopyingToLongArrayWasCorrect(largeLongArray, copyLength, copyDest, srcPosValue); } private long verifiyThatCopyingToLongArrayWasCorrect( long[] largeLongArray, int copyLength, int copyDest, long srcPosValue) { for (int i = copyDest; i < copyLength; i++) { if (largeLongArray[i] != srcPosValue) { fail("Expected + " + srcPosValue + " but was " + largeLongArray[i] + " at pos " + i + ". This means that parts of the long array were overwritten"); break; } srcPosValue++; } return srcPosValue; } private void doAligned64CopyForLongs(long[] largeLongArray, int copyStart, int copyLength, int copyDest) { VM.disableGC(); Address arrayStart = Magic.objectAsAddress(largeLongArray); Address copyStartAddress = arrayStart.plus(copyStart * BYTES_IN_LONG); Address copyDestAddress = arrayStart.plus(copyDest * BYTES_IN_LONG); int copyBytes = copyLength * BYTES_IN_LONG; Memory.aligned64Copy(copyDestAddress, copyStartAddress, copyBytes); VM.enableGC(); } private long[] initializeLongArray() { long[] largeLongArray = new long[arrayLength]; long startValue = Long.MIN_VALUE; long value = startValue; for (int i = 0; i < largeLongArray.length; i++) { largeLongArray[i] = value; value++; } return largeLongArray; } @Test public void testMemcopyFromGreaterToLesserOverlapping() throws Exception { byte[] largeByteArray = initializeByteArray(); int copyLength = (arrayLength * 7) / 9; int copyStart = arrayLength - copyLength; int copyDest = (arrayLength) / 9; byte srcPosValue = largeByteArray[copyStart]; doMemcopy(largeByteArray, copyLength, copyStart, copyDest); verifyThatCopyingToByteArrayWasCorrect(largeByteArray, copyLength, copyDest, srcPosValue); } @Test public void testMemcopyFromLesserToGreaterOverlapping() throws Exception { byte[] largeByteArray = initializeByteArray(); int copyLength = (arrayLength * 7) / 9; int copyStart = (3 * arrayLength) / 9; int copyDest = arrayLength - copyLength; byte srcPosValue = largeByteArray[copyStart]; doMemcopy(largeByteArray, copyLength, copyStart, copyDest); verifyThatCopyingToByteArrayWasCorrect(largeByteArray, copyLength, copyDest, srcPosValue); } @Test public void testMemcopyWholeArray() throws Exception { byte[] largeByteArray = initializeByteArray(); int copyLength = arrayLength; int copyStart = 0; int copyDest = 0; byte srcPosValue = largeByteArray[copyStart]; doMemcopy(largeByteArray, copyLength, copyStart, copyDest); verifyThatCopyingToByteArrayWasCorrect(largeByteArray, copyLength, copyDest, srcPosValue); } private void doMemcopy(byte[] largeByteArray, int copyLength, int copyStart, int copyDest) { VM.disableGC(); Address arrayStart = Magic.objectAsAddress(largeByteArray); Address copyStartAddress = arrayStart.plus(copyStart * BYTES_IN_BYTE); Address copyDestAddress = arrayStart.plus(copyDest * BYTES_IN_BYTE); int copyBytes = copyLength * BYTES_IN_BYTE; Memory.memcopy(copyDestAddress, copyStartAddress, copyBytes); VM.enableGC(); } }