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 java.nio.ByteOrder; 29 30 import sun.misc.Unsafe; 31 32 final class Bits { // package-private 33 34 private static final Unsafe unsafe = Unsafe.getUnsafe(); 35 // XXX TODO proper value (e.g. copy from java.nio.Bits) 36 private static final boolean unalignedAccess = false/*unsafe.unalignedAccess()*/; 37 private static final boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; 38 39 private Bits() { } 40 41 // -- Swapping -- 42 43 private static short swap(short x) { 44 return Short.reverseBytes(x); 45 } 46 47 private static char swap(char x) { 48 return Character.reverseBytes(x); 49 } 50 51 private static int swap(int x) { 52 return Integer.reverseBytes(x); 53 } 54 55 private static long swap(long x) { 56 return Long.reverseBytes(x); 57 } 58 59 private static float swap(float x) { 60 return Float.intBitsToFloat(swap(Float.floatToIntBits(x))); 61 } 62 63 private static double swap(double x) { 64 return Double.longBitsToDouble(swap(Double.doubleToLongBits(x))); 65 } 66 67 // -- Alignment -- 68 69 private static boolean isAddressAligned(long a, int datumSize) { 70 return (a & datumSize - 1) == 0; 71 } 72 73 // -- Primitives stored per byte 74 75 private static byte char1(char x) { return (byte)(x >> 8); } 76 private static byte char0(char x) { return (byte)(x ); } 77 78 private static byte short1(short x) { return (byte)(x >> 8); } 79 private static byte short0(short x) { return (byte)(x ); } 80 81 private static byte int3(int x) { return (byte)(x >> 24); } 82 private static byte int2(int x) { return (byte)(x >> 16); } 83 private static byte int1(int x) { return (byte)(x >> 8); } 84 private static byte int0(int x) { return (byte)(x ); } 85 86 private static byte long7(long x) { return (byte)(x >> 56); } 87 private static byte long6(long x) { return (byte)(x >> 48); } 88 private static byte long5(long x) { return (byte)(x >> 40); } 89 private static byte long4(long x) { return (byte)(x >> 32); } 90 private static byte long3(long x) { return (byte)(x >> 24); } 91 private static byte long2(long x) { return (byte)(x >> 16); } 92 private static byte long1(long x) { return (byte)(x >> 8); } 93 private static byte long0(long x) { return (byte)(x ); } 94 95 private static void putCharBigEndianUnaligned(long a, char x) { 96 putByte_(a , char1(x)); 97 putByte_(a + 1, char0(x)); 98 } 99 100 private static void putShortBigEndianUnaligned(long a, short x) { 101 putByte_(a , short1(x)); 102 putByte_(a + 1, short0(x)); 103 } 104 105 private static void putIntBigEndianUnaligned(long a, int x) { 106 putByte_(a , int3(x)); 107 putByte_(a + 1, int2(x)); 108 putByte_(a + 2, int1(x)); 109 putByte_(a + 3, int0(x)); 110 } 111 112 private static void putLongBigEndianUnaligned(long a, long x) { 113 putByte_(a , long7(x)); 114 putByte_(a + 1, long6(x)); 115 putByte_(a + 2, long5(x)); 116 putByte_(a + 3, long4(x)); 117 putByte_(a + 4, long3(x)); 118 putByte_(a + 5, long2(x)); 119 putByte_(a + 6, long1(x)); 120 putByte_(a + 7, long0(x)); 121 } 122 123 private static void putFloatBigEndianUnaligned(long a, float x) { 124 putIntBigEndianUnaligned(a, Float.floatToRawIntBits(x)); 125 } 126 127 private static void putDoubleBigEndianUnaligned(long a, double x) { 128 putLongBigEndianUnaligned(a, Double.doubleToRawLongBits(x)); 129 } 130 131 private static void putByte_(long a, byte b) { 132 unsafe.putByte(a, b); 133 } 134 135 private static void putBoolean_(long a, boolean x) { 136 unsafe.putBoolean(null, a, x); 137 } 138 139 private static void putChar_(long a, char x) { 140 unsafe.putChar(a, bigEndian ? x : swap(x)); 141 } 142 143 private static void putShort_(long a, short x) { 144 unsafe.putShort(a, bigEndian ? x : swap(x)); 145 } 146 147 private static void putInt_(long a, int x) { 148 unsafe.putInt(a, bigEndian ? x : swap(x)); 149 } 150 151 private static void putLong_(long a, long x) { 152 unsafe.putLong(a, bigEndian ? x : swap(x)); 153 } 154 155 private static void putFloat_(long a, float x) { 156 unsafe.putFloat(a, bigEndian ? x : swap(x)); 157 } 158 159 private static void putDouble_(long a, double x) { 160 unsafe.putDouble(a, bigEndian ? x : swap(x)); 161 } 162 163 // external api 164 static int putByte(long a, byte x) { 165 putByte_(a, x); 166 return Byte.BYTES; 167 } 168 169 static int putBoolean(long a, boolean x) { 170 putBoolean_(a, x); 171 return Byte.BYTES; 172 } 173 174 static int putChar(long a, char x) { 175 if (unalignedAccess || isAddressAligned(a, Character.BYTES)) { 176 putChar_(a, x); 177 return Character.BYTES; 178 } 179 putCharBigEndianUnaligned(a, x); 180 return Character.BYTES; 181 } 182 183 static int putShort(long a, short x) { 184 if (unalignedAccess || isAddressAligned(a, Short.BYTES)) { 185 putShort_(a, x); 186 return Short.BYTES; 187 } 188 putShortBigEndianUnaligned(a, x); 189 return Short.BYTES; 190 } 191 192 static int putInt(long a, int x) { 193 if (unalignedAccess || isAddressAligned(a, Integer.BYTES)) { 194 putInt_(a, x); 195 return Integer.BYTES; 196 } 197 putIntBigEndianUnaligned(a, x); 198 return Integer.BYTES; 199 } 200 201 static int putLong(long a, long x) { 202 if (unalignedAccess || isAddressAligned(a, Long.BYTES)) { 203 putLong_(a, x); 204 return Long.BYTES; 205 } 206 putLongBigEndianUnaligned(a, x); 207 return Long.BYTES; 208 } 209 210 static int putFloat(long a, float x) { 211 if (unalignedAccess || isAddressAligned(a, Float.BYTES)) { 212 putFloat_(a, x); 213 return Float.BYTES; 214 } 215 putFloatBigEndianUnaligned(a, x); 216 return Float.BYTES; 217 } 218 219 static int putDouble(long a, double x) { 220 if (unalignedAccess || isAddressAligned(a, Double.BYTES)) { 221 putDouble_(a, x); 222 return Double.BYTES; 223 } 224 putDoubleBigEndianUnaligned(a, x); 225 return Double.BYTES; 226 } 227 }