1 /*
   2  * Copyright (c) 2016 SAP SE. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8158260
  27  * @summary Test unaligned Unsafe accesses
  28  * @modules java.base/jdk.internal.misc
  29  * @run main/othervm -Diters=20000 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation JdkInternalMiscUnsafeUnalignedAccess
  30  * @author volker.simonis@gmail.com
  31  */
  32 
  33 import java.lang.reflect.Field;
  34 import java.nio.ByteOrder;
  35 import jdk.internal.misc.Unsafe;
  36 
  37 public class JdkInternalMiscUnsafeUnalignedAccess {
  38     static final int ITERS = Integer.getInteger("iters", 20_000);
  39     private static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN);
  40     private static final Unsafe UNSAFE;
  41     private static final int SIZE = 1024;
  42     private static long memory;
  43 
  44     static {
  45         try {
  46             Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
  47             unsafeField.setAccessible(true);
  48             UNSAFE = (Unsafe) unsafeField.get(null);
  49         }
  50         catch (Exception e) {
  51             throw new RuntimeException("Unable to get Unsafe instance.", e);
  52         }
  53     }
  54 
  55     static int getInt_0() {
  56         return UNSAFE.getInt(memory + 0);
  57     }
  58     static int getInt_1() {
  59         return UNSAFE.getInt(memory + 1);
  60     }
  61     static int getInt_4() {
  62         return UNSAFE.getInt(memory + 4);
  63     }
  64     static int getInt_17() {
  65         return UNSAFE.getInt(memory + 17);
  66     }
  67 
  68     static long getIntAsLong_0() {
  69         return UNSAFE.getInt(memory + 0);
  70     }
  71     static long getIntAsLong_1() {
  72         return UNSAFE.getInt(memory + 1);
  73     }
  74     static long getIntAsLong_4() {
  75         return UNSAFE.getInt(memory + 4);
  76     }
  77     static long getIntAsLong_17() {
  78         return UNSAFE.getInt(memory + 17);
  79     }
  80 
  81     static long getLong_0() {
  82         return UNSAFE.getLong(memory + 0);
  83     }
  84     static long getLong_1() {
  85         return UNSAFE.getLong(memory + 1);
  86     }
  87     static long getLong_4() {
  88         return UNSAFE.getLong(memory + 4);
  89     }
  90     static long getLong_8() {
  91         return UNSAFE.getLong(memory + 8);
  92     }
  93     static long getLong_17() {
  94         return UNSAFE.getLong(memory + 17);
  95     }
  96 
  97     static void putInt_0(int i) {
  98         UNSAFE.putInt(memory + 0, i);
  99     }
 100     static void putInt_1(int i) {
 101         UNSAFE.putInt(memory + 1, i);
 102     }
 103     static void putInt_4(int i) {
 104         UNSAFE.putInt(memory + 4, i);
 105     }
 106     static void putInt_17(int i) {
 107         UNSAFE.putInt(memory + 17, i);
 108     }
 109 
 110     static void putLong_0(long l) {
 111         UNSAFE.putLong(memory + 0, l);
 112     }
 113     static void putLong_1(long l) {
 114         UNSAFE.putLong(memory + 1, l);
 115     }
 116     static void putLong_4(long l) {
 117         UNSAFE.putLong(memory + 4, l);
 118     }
 119     static void putLong_8(long l) {
 120         UNSAFE.putLong(memory + 8, l);
 121     }
 122     static void putLong_17(long l) {
 123         UNSAFE.putLong(memory + 17, l);
 124     }
 125 
 126     public static void main(String[] args) throws Exception {
 127 
 128         if (!UNSAFE.unalignedAccess()) {
 129             System.out.println("Platform is not supporting unaligned access - nothing to test.");
 130             return;
 131         }
 132 
 133         memory = UNSAFE.allocateMemory(SIZE);
 134 
 135         UNSAFE.putInt(memory +  0, 0x00112233);
 136         UNSAFE.putInt(memory +  4, 0x44556677);
 137         UNSAFE.putInt(memory +  8, 0x8899aabb);
 138         UNSAFE.putInt(memory + 12, 0xccddeeff);
 139         UNSAFE.putInt(memory + 16, 0x01234567);
 140         UNSAFE.putInt(memory + 20, 0x89abcdef);
 141         UNSAFE.putInt(memory + 24, 0x01234567);
 142 
 143         // Unsafe.getInt()
 144         int res;
 145         for (int i = 0; i < ITERS; i++) {
 146             res = getInt_0();
 147             if (res != 0x00112233) {
 148                 throw new Exception(res + " != 0x00112233");
 149             }
 150         }
 151 
 152         for (int i = 0; i < ITERS; i++) {
 153             res = getInt_1();
 154             if (res != (BIG_ENDIAN ? 0x11223344 : 0x77001122)) {
 155                 throw new Exception(res + " != " + (BIG_ENDIAN ? 0x11223344 : 0x77001122));
 156             }
 157         }
 158 
 159         for (int i = 0; i < ITERS; i++) {
 160             res = getInt_4();
 161             if (res != 0x44556677) {
 162                 throw new Exception(res + " != 0x44556677");
 163             }
 164         }
 165 
 166         for (int i = 0; i < ITERS; i++) {
 167             res = getInt_17();
 168             if (res != (BIG_ENDIAN ? 0x23456789 : 0xef012345)) {
 169                 throw new Exception(res + " != " + (BIG_ENDIAN ? 0x23456789 : 0xef012345));
 170             }
 171         }
 172 
 173         // (long)Unsafe.getInt()
 174         long lres;
 175         for (int i = 0; i < ITERS; i++) {
 176             lres = getIntAsLong_0();
 177             if (lres != (long)0x00112233) {
 178                 throw new Exception(lres + " != 0x00112233");
 179             }
 180         }
 181 
 182         for (int i = 0; i < ITERS; i++) {
 183             lres = getIntAsLong_1();
 184             if (lres != (BIG_ENDIAN ? (long)0x11223344 : (long)0x77001122)) {
 185                 throw new Exception(lres + " != " + (BIG_ENDIAN ? (long)0x11223344 : (long)0x77001122));
 186             }
 187         }
 188 
 189         for (int i = 0; i < ITERS; i++) {
 190             lres = getIntAsLong_4();
 191             if (lres != (long)0x44556677) {
 192                 throw new Exception(lres + " != 0x44556677");
 193             }
 194         }
 195 
 196         for (int i = 0; i < ITERS; i++) {
 197             lres = getIntAsLong_17();
 198             if (lres != (BIG_ENDIAN ? (long)0x23456789 : (long)0xef012345)) {
 199                 throw new Exception(lres + " != " + (BIG_ENDIAN ? (long)0x23456789 : (long)0xef012345));
 200             }
 201         }
 202 
 203         // Unsafe.getLong()
 204         for (int i = 0; i < ITERS; i++) {
 205             lres = getLong_0();
 206             if (lres != (BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L)) {
 207                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L));
 208             }
 209         }
 210 
 211         for (int i = 0; i < ITERS; i++) {
 212             lres = getLong_1();
 213             if (lres != (BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L)) {
 214                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L));
 215             }
 216         }
 217 
 218         for (int i = 0; i < ITERS; i++) {
 219             lres = getLong_4();
 220             if (lres != (BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L)) {
 221                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L));
 222             }
 223         }
 224 
 225         for (int i = 0; i < ITERS; i++) {
 226             lres = getLong_8();
 227             if (lres != (BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL)) {
 228                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL));
 229             }
 230         }
 231 
 232         for (int i = 0; i < ITERS; i++) {
 233             lres = getLong_17();
 234             if (lres != (BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L)) {
 235                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L));
 236             }
 237         }
 238 
 239         // Unsafe.putInt()
 240         for (int i = 0; i < ITERS; i++) {
 241             putInt_0(0x00112233);
 242             res = getInt_0();
 243             if (res != 0x00112233) {
 244                 throw new Exception(res + " != 0x00112233");
 245             }
 246         }
 247 
 248         for (int i = 0; i < ITERS; i++) {
 249             putInt_1(BIG_ENDIAN ? 0x11223344 : 0x77001122);
 250             res = getInt_1();
 251             if (res != (BIG_ENDIAN ? 0x11223344 : 0x77001122)) {
 252                 throw new Exception(res + " != " + (BIG_ENDIAN ? 0x11223344 : 0x77001122));
 253             }
 254         }
 255 
 256         for (int i = 0; i < ITERS; i++) {
 257             putInt_4(0x44556677);
 258             res = getInt_4();
 259             if (res != 0x44556677) {
 260                 throw new Exception(res + " != 0x44556677");
 261             }
 262         }
 263 
 264         for (int i = 0; i < ITERS; i++) {
 265             putInt_17(BIG_ENDIAN ? 0x23456789 : 0xef012345);
 266             res = getInt_17();
 267             if (res != (BIG_ENDIAN ? 0x23456789 : 0xef012345)) {
 268                 throw new Exception(res + " != " + (BIG_ENDIAN ? 0x23456789 : 0xef012345));
 269             }
 270         }
 271 
 272 
 273         // Unsafe.putLong()
 274         for (int i = 0; i < ITERS; i++) {
 275             putLong_0(BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L);
 276             lres = getLong_0();
 277             if (lres != (BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L)) {
 278                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L));
 279             }
 280         }
 281 
 282         for (int i = 0; i < ITERS; i++) {
 283             putLong_1(BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L);
 284             lres = getLong_1();
 285             if (lres != (BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L)) {
 286                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L));
 287             }
 288         }
 289 
 290         for (int i = 0; i < ITERS; i++) {
 291             putLong_4(BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L);
 292             lres = getLong_4();
 293             if (lres != (BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L)) {
 294                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L));
 295             }
 296         }
 297 
 298         for (int i = 0; i < ITERS; i++) {
 299             putLong_8(BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL);
 300             lres = getLong_8();
 301             if (lres != (BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL)) {
 302                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL));
 303             }
 304         }
 305 
 306         for (int i = 0; i < ITERS; i++) {
 307             putLong_17(BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L);
 308             lres = getLong_17();
 309             if (lres != (BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L)) {
 310                 throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L));
 311             }
 312         }
 313     }
 314 
 315 }