hotspot/test/compiler/intrinsics/unsafe/HeapByteBufferTest.java
changeset 30209 8ea30dc99369
child 30218 53a798b8b063
equal deleted inserted replaced
30208:ed11124f18e1 30209:8ea30dc99369
       
     1 //
       
     2 // Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
       
     3 // Copyright (c) 2015, Red Hat Inc. All rights reserved.
       
     4 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     5 //
       
     6 // This code is free software; you can redistribute it and/or modify it
       
     7 // under the terms of the GNU General Public License version 2 only, as
       
     8 // published by the Free Software Foundation.
       
     9 //
       
    10 // This code is distributed in the hope that it will be useful, but WITHOUT
       
    11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    12 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    13 // version 2 for more details (a copy is included in the LICENSE file that
       
    14 // accompanied this code).
       
    15 //
       
    16 // You should have received a copy of the GNU General Public License version
       
    17 // 2 along with this work; if not, write to the Free Software Foundation,
       
    18 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    19 //
       
    20 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    21 // or visit www.oracle.com if you need additional information or have any
       
    22 // questions.
       
    23 //
       
    24 //
       
    25 
       
    26 
       
    27 import static java.lang.Math.abs;
       
    28 import java.nio.ByteBuffer;
       
    29 import java.nio.ByteOrder;
       
    30 import static java.nio.ByteOrder.BIG_ENDIAN;
       
    31 import static java.nio.ByteOrder.LITTLE_ENDIAN;
       
    32 import java.util.SplittableRandom;
       
    33 import java.util.Arrays;
       
    34 
       
    35 /**
       
    36  * @test
       
    37  * @bug 8026049
       
    38  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses HeapByteBufferTest
       
    39  * @run main/othervm HeapByteBufferTest
       
    40  * @summary Verify that byte buffers are correctly accessed.
       
    41  */
       
    42 
       
    43 // A wrapper for a ByteBuffer which maintains a backing array and a
       
    44 // position.  Whenever this wrapper is written the backing array and
       
    45 // the wrapped byte buffer are updated together, and whenever it is
       
    46 // read we check that the ByteBuffer and the backing array are identical.
       
    47 
       
    48 class MyByteBuffer {
       
    49     final ByteBuffer buf;
       
    50     final byte[] bytes;
       
    51     int pos;
       
    52     ByteOrder byteOrder = BIG_ENDIAN;
       
    53 
       
    54     MyByteBuffer(ByteBuffer buf, byte[] bytes) {
       
    55         this.buf = buf;
       
    56         this.bytes = Arrays.copyOf(bytes, bytes.length);
       
    57         pos = 0;
       
    58     }
       
    59 
       
    60     public final MyByteBuffer order(ByteOrder bo) {
       
    61         byteOrder = bo;
       
    62         buf.order(bo);
       
    63         return this;
       
    64     }
       
    65 
       
    66     static MyByteBuffer wrap(byte[] bytes) {
       
    67         return new MyByteBuffer(ByteBuffer.wrap(bytes), bytes);
       
    68     }
       
    69 
       
    70     int capacity() { return bytes.length; }
       
    71     int position() {
       
    72         if (buf.position() != pos)
       
    73             throw new RuntimeException();
       
    74         return buf.position();
       
    75     }
       
    76 
       
    77     byte[] array() { return buf.array(); }
       
    78     byte[] backingArray() { return bytes; }
       
    79 
       
    80     private static byte long7(long x) { return (byte)(x >> 56); }
       
    81     private static byte long6(long x) { return (byte)(x >> 48); }
       
    82     private static byte long5(long x) { return (byte)(x >> 40); }
       
    83     private static byte long4(long x) { return (byte)(x >> 32); }
       
    84     private static byte long3(long x) { return (byte)(x >> 24); }
       
    85     private static byte long2(long x) { return (byte)(x >> 16); }
       
    86     private static byte long1(long x) { return (byte)(x >>  8); }
       
    87     private static byte long0(long x) { return (byte)(x      ); }
       
    88 
       
    89     private static byte int3(int x) { return (byte)(x >> 24); }
       
    90     private static byte int2(int x) { return (byte)(x >> 16); }
       
    91     private static byte int1(int x) { return (byte)(x >>  8); }
       
    92     private static byte int0(int x) { return (byte)(x      ); }
       
    93 
       
    94     private static byte short1(short x) { return (byte)(x >> 8); }
       
    95     private static byte short0(short x) { return (byte)(x     ); }
       
    96 
       
    97     byte _get(long i) { return bytes[(int)i]; }
       
    98     void _put(long i, byte x) { bytes[(int)i] = x; }
       
    99 
       
   100     private void putLongX(long a, long x) {
       
   101         if (byteOrder == BIG_ENDIAN) {
       
   102             x = Long.reverseBytes(x);
       
   103         }
       
   104         _put(a + 7, long7(x));
       
   105         _put(a + 6, long6(x));
       
   106         _put(a + 5, long5(x));
       
   107         _put(a + 4, long4(x));
       
   108         _put(a + 3, long3(x));
       
   109         _put(a + 2, long2(x));
       
   110         _put(a + 1, long1(x));
       
   111         _put(a    , long0(x));
       
   112     }
       
   113 
       
   114     private void putIntX(long a, int x) {
       
   115         if (byteOrder == BIG_ENDIAN) {
       
   116             x = Integer.reverseBytes(x);
       
   117         }
       
   118         _put(a + 3, int3(x));
       
   119         _put(a + 2, int2(x));
       
   120         _put(a + 1, int1(x));
       
   121         _put(a    , int0(x));
       
   122     }
       
   123 
       
   124     private void putShortX(int bi, short x) {
       
   125         if (byteOrder == BIG_ENDIAN) {
       
   126             x = Short.reverseBytes(x);
       
   127         }
       
   128         _put(bi    , short0(x));
       
   129         _put(bi + 1, short1(x));
       
   130     }
       
   131 
       
   132     static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
       
   133         return (((b3       ) << 24) |
       
   134                 ((b2 & 0xff) << 16) |
       
   135                 ((b1 & 0xff) <<  8) |
       
   136                 ((b0 & 0xff)      ));
       
   137     }
       
   138     int getIntX(long a) {
       
   139         int x = makeInt(_get(a + 3),
       
   140                 _get(a + 2),
       
   141                 _get(a + 1),
       
   142                 _get(a));
       
   143         if (byteOrder == BIG_ENDIAN) {
       
   144             x = Integer.reverseBytes(x);
       
   145         }
       
   146         return x;
       
   147     }
       
   148 
       
   149     static private long makeLong(byte b7, byte b6, byte b5, byte b4,
       
   150                                  byte b3, byte b2, byte b1, byte b0)
       
   151     {
       
   152         return ((((long)b7       ) << 56) |
       
   153                 (((long)b6 & 0xff) << 48) |
       
   154                 (((long)b5 & 0xff) << 40) |
       
   155                 (((long)b4 & 0xff) << 32) |
       
   156                 (((long)b3 & 0xff) << 24) |
       
   157                 (((long)b2 & 0xff) << 16) |
       
   158                 (((long)b1 & 0xff) <<  8) |
       
   159                 (((long)b0 & 0xff)      ));
       
   160     }
       
   161 
       
   162     long getLongX(long a) {
       
   163         long x = makeLong(_get(a + 7),
       
   164                 _get(a + 6),
       
   165                 _get(a + 5),
       
   166                 _get(a + 4),
       
   167                 _get(a + 3),
       
   168                 _get(a + 2),
       
   169                 _get(a + 1),
       
   170                 _get(a));
       
   171         if (byteOrder == BIG_ENDIAN) {
       
   172             x = Long.reverseBytes(x);
       
   173         }
       
   174         return x;
       
   175     }
       
   176 
       
   177     static private short makeShort(byte b1, byte b0) {
       
   178         return (short)((b1 << 8) | (b0 & 0xff));
       
   179     }
       
   180 
       
   181     short getShortX(long a) {
       
   182         short x = makeShort(_get(a + 1),
       
   183                             _get(a    ));
       
   184         if (byteOrder == BIG_ENDIAN) {
       
   185             x = Short.reverseBytes(x);
       
   186         }
       
   187         return x;
       
   188     }
       
   189 
       
   190     double getDoubleX(long a) {
       
   191         long x = getLongX(a);
       
   192         return Double.longBitsToDouble(x);
       
   193     }
       
   194 
       
   195     double getFloatX(long a) {
       
   196         int x = getIntX(a);
       
   197         return Float.intBitsToFloat(x);
       
   198     }
       
   199 
       
   200     void ck(long x, long y) {
       
   201         if (x != y) {
       
   202             throw new RuntimeException(" x = " + Long.toHexString(x) + ", y = " + Long.toHexString(y));
       
   203         }
       
   204     }
       
   205 
       
   206     void ck(double x, double y) {
       
   207         if (x == x && y == y && x != y) {
       
   208             ck(x, y);
       
   209         }
       
   210     }
       
   211 
       
   212     long getLong(int i) { ck(buf.getLong(i), getLongX(i)); return buf.getLong(i); }
       
   213     int getInt(int i) { ck(buf.getInt(i), getIntX(i)); return buf.getInt(i); }
       
   214     short getShort(int i) { ck(buf.getShort(i), getShortX(i)); return buf.getShort(i); }
       
   215     char getChar(int i) { ck(buf.getChar(i), (char)getShortX(i)); return buf.getChar(i); }
       
   216     double getDouble(int i) { ck(buf.getDouble(i), getDoubleX(i)); return buf.getDouble(i); }
       
   217     float getFloat(int i) { ck(buf.getFloat(i), getFloatX(i)); return buf.getFloat(i); }
       
   218 
       
   219     void putLong(int i, long x) { buf.putLong(i, x); putLongX(i, x); }
       
   220     void putInt(int i, int x) { buf.putInt(i, x); putIntX(i, x); }
       
   221     void putShort(int i, short x) { buf.putShort(i, x); putShortX(i, x); }
       
   222     void putChar(int i, char x) { buf.putChar(i, x); putShortX(i, (short)x); }
       
   223     void putDouble(int i, double x) { buf.putDouble(i, x); putLongX(i, Double.doubleToRawLongBits(x)); }
       
   224     void putFloat(int i, float x) { buf.putFloat(i, x); putIntX(i, Float.floatToRawIntBits(x)); }
       
   225 
       
   226     long getLong() { ck(buf.getLong(buf.position()), getLongX(pos)); long x = buf.getLong(); pos += 8; return x; }
       
   227     int getInt() { ck(buf.getInt(buf.position()), getIntX(pos)); int x = buf.getInt(); pos += 4; return x; }
       
   228     short getShort() { ck(buf.getShort(buf.position()), getShortX(pos)); short x = buf.getShort(); pos += 2; return x; }
       
   229     char getChar() {  ck(buf.getChar(buf.position()), (char)getShortX(pos)); char x = buf.getChar(); pos += 2; return x; }
       
   230     double getDouble() { ck(buf.getDouble(buf.position()), getDoubleX(pos)); double x = buf.getDouble(); pos += 8; return x; }
       
   231     float getFloat() { ck(buf.getFloat(buf.position()), getFloatX(pos)); float x = buf.getFloat(); pos += 4; return x; }
       
   232 
       
   233     void putLong(long x) { putLongX(pos, x); pos += 8; buf.putLong(x); }
       
   234     void putInt(int x) { putIntX(pos, x); pos += 4; buf.putInt(x); }
       
   235     void putShort(short x) { putShortX(pos, x); pos += 2; buf.putShort(x); }
       
   236     void putChar(char x) { putShortX(pos, (short)x); pos += 2; buf.putChar(x); }
       
   237     void putDouble(double x) { putLongX(pos, Double.doubleToRawLongBits(x)); pos += 8; buf.putDouble(x); }
       
   238     void putFloat(float x) { putIntX(pos, Float.floatToRawIntBits(x)); pos += 4; buf.putFloat(x); }
       
   239 
       
   240     void rewind() { pos = 0; buf.rewind(); }
       
   241 }
       
   242 
       
   243 public class HeapByteBufferTest implements Runnable {
       
   244 
       
   245     SplittableRandom random = new SplittableRandom();
       
   246     MyByteBuffer data = MyByteBuffer.wrap(new byte[1024]);
       
   247 
       
   248     int randomOffset(SplittableRandom r, MyByteBuffer buf, int size) {
       
   249         return abs(r.nextInt()) % (buf.capacity() - size);
       
   250     }
       
   251 
       
   252     long iterations;
       
   253 
       
   254     HeapByteBufferTest(long iterations) {
       
   255         this.iterations = iterations;
       
   256     }
       
   257 
       
   258     // The core of the test.  Walk over the buffer reading and writing
       
   259     // random data, XORing it as we go.  We can detect writes in the
       
   260     // wrong place, writes which are too long or too short, and reads
       
   261     // or writes of the wrong data,
       
   262     void step(SplittableRandom r) {
       
   263         data.order((r.nextInt() & 1) != 0 ? BIG_ENDIAN : LITTLE_ENDIAN);
       
   264 
       
   265         data.rewind();
       
   266         while (data.position() < data.capacity())
       
   267             data.putLong(data.getLong() ^ random.nextLong());
       
   268 
       
   269         data.rewind();
       
   270         while (data.position() < data.capacity())
       
   271             data.putInt(data.getInt() ^ random.nextInt());
       
   272 
       
   273         data.rewind();
       
   274         while (data.position() < data.capacity())
       
   275             data.putShort((short)(data.getShort() ^ random.nextInt()));
       
   276 
       
   277         data.rewind();
       
   278         while (data.position() < data.capacity())
       
   279             data.putChar((char)(data.getChar() ^ random.nextInt()));
       
   280 
       
   281         data.rewind();
       
   282         while (data.position() < data.capacity()) {
       
   283             data.putDouble(combine(data.getDouble(), random.nextLong()));
       
   284         }
       
   285 
       
   286         data.rewind();
       
   287         while (data.position() < data.capacity())
       
   288             data.putFloat(combine(data.getFloat(), random.nextInt()));
       
   289 
       
   290         for (int i = 0; i < 100; i++) {
       
   291             int offset = randomOffset(r, data, 8);
       
   292             data.putLong(offset, data.getLong(offset) ^ random.nextLong());
       
   293         }
       
   294         for (int i = 0; i < 100; i++) {
       
   295             int offset = randomOffset(r, data, 4);
       
   296             data.putInt(offset, data.getInt(offset) ^ random.nextInt());
       
   297         }
       
   298         for (int i = 0; i < 100; i++) {
       
   299             int offset = randomOffset(r, data, 4);
       
   300             data.putShort(offset, (short)(data.getShort(offset) ^ random.nextInt()));
       
   301         }
       
   302         for (int i = 0; i < 100; i++) {
       
   303             int offset = randomOffset(r, data, 4);
       
   304             data.putChar(offset, (char)(data.getChar(offset) ^ random.nextInt()));
       
   305         }
       
   306         for (int i = 0; i < 100; i++) {
       
   307             int offset = randomOffset(r, data, 8);
       
   308             data.putDouble(offset, combine(data.getDouble(offset), random.nextLong()));
       
   309         }
       
   310         for (int i = 0; i < 100; i++) {
       
   311             int offset = randomOffset(r, data, 4);
       
   312             data.putFloat(offset, combine(data.getFloat(offset), random.nextInt()));
       
   313         }
       
   314     }
       
   315 
       
   316     // XOR the bit pattern of a double and a long, returning the
       
   317     // result as a double.
       
   318     //
       
   319     // We convert signalling NaNs to quiet NaNs.  We need to do this
       
   320     // because some platforms (in particular legacy 80x87) do not
       
   321     // provide transparent conversions between integer and
       
   322     // floating-point types even when using raw conversions but
       
   323     // quietly convert sNaN to qNaN.  This causes spurious test
       
   324     // failures when the template interpreter uses 80x87 and the JITs
       
   325     // use XMM registers.
       
   326     //
       
   327     public double combine(double prev, long bits) {
       
   328         bits ^= Double.doubleToRawLongBits(prev);
       
   329         double result = Double.longBitsToDouble(bits);
       
   330         if (Double.isNaN(result)) {
       
   331             result = Double.longBitsToDouble(bits | 0x8000000000000l);
       
   332         }
       
   333         return result;
       
   334     }
       
   335 
       
   336     // XOR the bit pattern of a float and an int, returning the result
       
   337     // as a float.  Convert sNaNs to qNaNs.
       
   338     public Float combine(float prev, int bits) {
       
   339         bits ^= Float.floatToRawIntBits(prev);
       
   340         Float result = Float.intBitsToFloat(bits);
       
   341         if (Float.isNaN(result)) {
       
   342             result = Float.intBitsToFloat(bits | 0x400000);
       
   343         }
       
   344         return result;
       
   345     }
       
   346 
       
   347     public void run() {
       
   348         SplittableRandom r = new SplittableRandom();
       
   349 
       
   350         for (int i = 0; i < data.capacity(); i += 8) {
       
   351             data.putLong(i, random.nextLong());
       
   352         }
       
   353 
       
   354         for (int i = 0; i < iterations; i++) {
       
   355             step(r);
       
   356         }
       
   357 
       
   358         if (!Arrays.equals(data.array(), data.backingArray())) {
       
   359             throw new RuntimeException();
       
   360         }
       
   361     }
       
   362 
       
   363     public static void main(String[] args) {
       
   364         // The number of iterations is high to ensure that tiered
       
   365         // compilation kicks in all the way up to C2.
       
   366         long iterations = 100000;
       
   367         if (args.length > 0)
       
   368             iterations = Long.parseLong(args[0]);
       
   369 
       
   370         new HeapByteBufferTest(iterations).run();
       
   371     }
       
   372 }