1 /*
   2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.jfr.internal;
  27 
  28 import jdk.internal.misc.Unsafe;
  29 
  30 final class Bits {                            // package-private
  31 
  32     private static final Unsafe unsafe = Unsafe.getUnsafe();
  33     private static final boolean unalignedAccess = unsafe.unalignedAccess();
  34     private static final boolean bigEndian = unsafe.isBigEndian();
  35 
  36     private Bits() { }
  37 
  38     // -- Swapping --
  39 
  40     private static short swap(short x) {
  41         return Short.reverseBytes(x);
  42     }
  43 
  44     private static char swap(char x) {
  45         return Character.reverseBytes(x);
  46     }
  47 
  48     private static int swap(int x) {
  49         return Integer.reverseBytes(x);
  50     }
  51 
  52     private static long swap(long x) {
  53         return Long.reverseBytes(x);
  54     }
  55 
  56     private static float swap(float x) {
  57         return Float.intBitsToFloat(swap(Float.floatToIntBits(x)));
  58     }
  59 
  60     private static double swap(double x) {
  61         return Double.longBitsToDouble(swap(Double.doubleToLongBits(x)));
  62     }
  63 
  64     // -- Alignment --
  65 
  66     private static boolean isAddressAligned(long a, int datumSize) {
  67         return (a & datumSize - 1) == 0;
  68     }
  69 
  70     // -- Primitives stored per byte
  71 
  72     private static byte char1(char x) { return (byte)(x >> 8); }
  73     private static byte char0(char x) { return (byte)(x     ); }
  74 
  75     private static byte short1(short x) { return (byte)(x >> 8); }
  76     private static byte short0(short x) { return (byte)(x     ); }
  77 
  78     private static byte int3(int x) { return (byte)(x >> 24); }
  79     private static byte int2(int x) { return (byte)(x >> 16); }
  80     private static byte int1(int x) { return (byte)(x >>  8); }
  81     private static byte int0(int x) { return (byte)(x      ); }
  82 
  83     private static byte long7(long x) { return (byte)(x >> 56); }
  84     private static byte long6(long x) { return (byte)(x >> 48); }
  85     private static byte long5(long x) { return (byte)(x >> 40); }
  86     private static byte long4(long x) { return (byte)(x >> 32); }
  87     private static byte long3(long x) { return (byte)(x >> 24); }
  88     private static byte long2(long x) { return (byte)(x >> 16); }
  89     private static byte long1(long x) { return (byte)(x >>  8); }
  90     private static byte long0(long x) { return (byte)(x      ); }
  91 
  92     private static void putCharBigEndianUnaligned(long a, char x) {
  93         putByte_(a    , char1(x));
  94         putByte_(a + 1, char0(x));
  95     }
  96 
  97     private static void putShortBigEndianUnaligned(long a, short x) {
  98         putByte_(a    , short1(x));
  99         putByte_(a + 1, short0(x));
 100     }
 101 
 102     private static void putIntBigEndianUnaligned(long a, int x) {
 103         putByte_(a    , int3(x));
 104         putByte_(a + 1, int2(x));
 105         putByte_(a + 2, int1(x));
 106         putByte_(a + 3, int0(x));
 107     }
 108 
 109     private static void putLongBigEndianUnaligned(long a, long x) {
 110         putByte_(a    , long7(x));
 111         putByte_(a + 1, long6(x));
 112         putByte_(a + 2, long5(x));
 113         putByte_(a + 3, long4(x));
 114         putByte_(a + 4, long3(x));
 115         putByte_(a + 5, long2(x));
 116         putByte_(a + 6, long1(x));
 117         putByte_(a + 7, long0(x));
 118     }
 119 
 120     private static void putFloatBigEndianUnaligned(long a, float x) {
 121         putIntBigEndianUnaligned(a, Float.floatToRawIntBits(x));
 122     }
 123 
 124     private static void putDoubleBigEndianUnaligned(long a, double x) {
 125         putLongBigEndianUnaligned(a, Double.doubleToRawLongBits(x));
 126     }
 127 
 128     private static void putByte_(long a, byte b) {
 129         unsafe.putByte(a, b);
 130     }
 131 
 132     private static void putBoolean_(long a, boolean x) {
 133         unsafe.putBoolean(null, a, x);
 134     }
 135 
 136     private static void putChar_(long a, char x) {
 137         unsafe.putChar(a, bigEndian ? x : swap(x));
 138     }
 139 
 140     private static void putShort_(long a, short x) {
 141         unsafe.putShort(a, bigEndian ? x : swap(x));
 142     }
 143 
 144     private static void putInt_(long a, int x) {
 145         unsafe.putInt(a, bigEndian ? x : swap(x));
 146     }
 147 
 148     private static void putLong_(long a, long x) {
 149         unsafe.putLong(a, bigEndian ? x : swap(x));
 150     }
 151 
 152     private static void putFloat_(long a, float x) {
 153         unsafe.putFloat(a, bigEndian ? x : swap(x));
 154     }
 155 
 156     private static void putDouble_(long a, double x) {
 157         unsafe.putDouble(a, bigEndian ? x : swap(x));
 158     }
 159 
 160     // external api
 161     static int putByte(long a, byte x) {
 162         putByte_(a, x);
 163         return Byte.BYTES;
 164     }
 165 
 166     static int putBoolean(long a, boolean x) {
 167         putBoolean_(a, x);
 168         return Byte.BYTES;
 169     }
 170 
 171     static int putChar(long a, char x) {
 172         if (unalignedAccess || isAddressAligned(a, Character.BYTES)) {
 173             putChar_(a, x);
 174             return Character.BYTES;
 175         }
 176         putCharBigEndianUnaligned(a, x);
 177         return Character.BYTES;
 178     }
 179 
 180     static int putShort(long a, short x) {
 181         if (unalignedAccess || isAddressAligned(a, Short.BYTES)) {
 182             putShort_(a, x);
 183             return Short.BYTES;
 184         }
 185         putShortBigEndianUnaligned(a, x);
 186         return Short.BYTES;
 187     }
 188 
 189     static int putInt(long a, int x) {
 190         if (unalignedAccess || isAddressAligned(a, Integer.BYTES)) {
 191             putInt_(a, x);
 192             return Integer.BYTES;
 193         }
 194         putIntBigEndianUnaligned(a, x);
 195         return Integer.BYTES;
 196     }
 197 
 198     static int putLong(long a, long x) {
 199          if (unalignedAccess || isAddressAligned(a, Long.BYTES)) {
 200             putLong_(a, x);
 201             return Long.BYTES;
 202         }
 203         putLongBigEndianUnaligned(a, x);
 204         return Long.BYTES;
 205     }
 206 
 207     static int putFloat(long a, float x) {
 208         if (unalignedAccess || isAddressAligned(a, Float.BYTES)) {
 209             putFloat_(a, x);
 210             return Float.BYTES;
 211         }
 212         putFloatBigEndianUnaligned(a, x);
 213         return Float.BYTES;
 214     }
 215 
 216     static int putDouble(long a, double x) {
 217         if (unalignedAccess || isAddressAligned(a, Double.BYTES)) {
 218             putDouble_(a, x);
 219             return Double.BYTES;
 220         }
 221         putDoubleBigEndianUnaligned(a, x);
 222         return Double.BYTES;
 223     }
 224 }