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 }