1 /* 2 * Copyright (c) 2015, 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. 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 package org.graalvm.compiler.core.common.util; 26 27 import static org.graalvm.compiler.core.common.util.UnsafeAccess.UNSAFE; 28 import sun.misc.Unsafe; 29 30 /** 31 * Provides low-level read access from a byte[] array for signed and unsigned values of size 1, 2, 32 * 4, and 8 bytes. 33 * 34 * The class can either be instantiated for sequential access to the byte[] array; or static methods 35 * can be used to read values without the overhead of creating an instance. 36 * 37 * The flag {@code supportsUnalignedMemoryAccess} must be set according to the capabilities of the 38 * hardware architecture: the value {@code true} allows more efficient memory access on 39 * architectures that support unaligned memory accesses; the value {@code false} is the safe 40 * fallback that works on every hardware. 41 */ 42 public abstract class UnsafeArrayTypeReader implements TypeReader { 43 44 public static int getS1(byte[] data, long byteIndex) { 45 return UNSAFE.getByte(data, readOffset(data, byteIndex, Byte.BYTES)); 46 } 47 48 public static int getU1(byte[] data, long byteIndex) { 49 return UNSAFE.getByte(data, readOffset(data, byteIndex, Byte.BYTES)) & 0xFF; 50 } 51 52 public static int getS2(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) { 53 if (supportsUnalignedMemoryAccess) { 54 return UnalignedUnsafeArrayTypeReader.getS2(data, byteIndex); 55 } else { 56 return AlignedUnsafeArrayTypeReader.getS2(data, byteIndex); 57 } 58 } 59 60 public static int getU2(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) { 61 return getS2(data, byteIndex, supportsUnalignedMemoryAccess) & 0xFFFF; 62 } 63 64 public static int getS4(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) { 65 if (supportsUnalignedMemoryAccess) { 66 return UnalignedUnsafeArrayTypeReader.getS4(data, byteIndex); 67 } else { 68 return AlignedUnsafeArrayTypeReader.getS4(data, byteIndex); 69 } 70 } 71 72 public static long getU4(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) { 73 return getS4(data, byteIndex, supportsUnalignedMemoryAccess) & 0xFFFFFFFFL; 74 } 75 76 public static long getS8(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) { 77 if (supportsUnalignedMemoryAccess) { 78 return UnalignedUnsafeArrayTypeReader.getS8(data, byteIndex); 79 } else { 80 return AlignedUnsafeArrayTypeReader.getS8(data, byteIndex); 81 } 82 } 83 84 protected static long readOffset(byte[] data, long byteIndex, int numBytes) { 85 assert byteIndex >= 0; 86 assert numBytes > 0; 87 assert byteIndex + numBytes <= data.length; 88 assert Unsafe.ARRAY_BYTE_INDEX_SCALE == 1; 89 90 return byteIndex + Unsafe.ARRAY_BYTE_BASE_OFFSET; 91 } 92 93 public static UnsafeArrayTypeReader create(byte[] data, long byteIndex, boolean supportsUnalignedMemoryAccess) { 94 if (supportsUnalignedMemoryAccess) { 95 return new UnalignedUnsafeArrayTypeReader(data, byteIndex); 96 } else { 97 return new AlignedUnsafeArrayTypeReader(data, byteIndex); 98 } 99 } 100 101 protected final byte[] data; 102 protected long byteIndex; 103 104 protected UnsafeArrayTypeReader(byte[] data, long byteIndex) { 105 this.data = data; 106 this.byteIndex = byteIndex; 107 } 108 109 @Override 110 public long getByteIndex() { 111 return byteIndex; 112 } 113 114 @Override 115 public void setByteIndex(long byteIndex) { 116 this.byteIndex = byteIndex; 117 } 118 119 @Override 120 public final int getS1() { 121 int result = getS1(data, byteIndex); 122 byteIndex += Byte.BYTES; 123 return result; 124 } 125 126 @Override 127 public final int getU1() { 128 int result = getU1(data, byteIndex); 129 byteIndex += Byte.BYTES; 130 return result; 131 } 132 133 @Override 134 public final int getU2() { 135 return getS2() & 0xFFFF; 136 } 137 138 @Override 139 public final long getU4() { 140 return getS4() & 0xFFFFFFFFL; 141 } 142 } 143 144 final class UnalignedUnsafeArrayTypeReader extends UnsafeArrayTypeReader { 145 protected static int getS2(byte[] data, long byteIndex) { 146 return UNSAFE.getShort(data, readOffset(data, byteIndex, Short.BYTES)); 147 } 148 149 protected static int getS4(byte[] data, long byteIndex) { 150 return UNSAFE.getInt(data, readOffset(data, byteIndex, Integer.BYTES)); 151 } 152 153 protected static long getS8(byte[] data, long byteIndex) { 154 return UNSAFE.getLong(data, readOffset(data, byteIndex, Long.BYTES)); 155 } 156 157 protected UnalignedUnsafeArrayTypeReader(byte[] data, long byteIndex) { 158 super(data, byteIndex); 159 } 160 161 @Override 162 public int getS2() { 163 int result = getS2(data, byteIndex); 164 byteIndex += Short.BYTES; 165 return result; 166 } 167 168 @Override 169 public int getS4() { 170 int result = getS4(data, byteIndex); 171 byteIndex += Integer.BYTES; 172 return result; 173 } 174 175 @Override 176 public long getS8() { 177 long result = getS8(data, byteIndex); 178 byteIndex += Long.BYTES; 179 return result; 180 } 181 } 182 183 class AlignedUnsafeArrayTypeReader extends UnsafeArrayTypeReader { 184 protected static int getS2(byte[] data, long byteIndex) { 185 long offset = readOffset(data, byteIndex, Short.BYTES); 186 return ((UNSAFE.getByte(data, offset + 0) & 0xFF) << 0) | // 187 (UNSAFE.getByte(data, offset + 1) << 8); 188 } 189 190 protected static int getS4(byte[] data, long byteIndex) { 191 long offset = readOffset(data, byteIndex, Integer.BYTES); 192 return ((UNSAFE.getByte(data, offset + 0) & 0xFF) << 0) | // 193 ((UNSAFE.getByte(data, offset + 1) & 0xFF) << 8) | // 194 ((UNSAFE.getByte(data, offset + 2) & 0xFF) << 16) | // 195 (UNSAFE.getByte(data, offset + 3) << 24); 196 } 197 198 protected static long getS8(byte[] data, long byteIndex) { 199 long offset = readOffset(data, byteIndex, Long.BYTES); 200 return ((long) ((UNSAFE.getByte(data, offset + 0) & 0xFF)) << 0) | // 201 ((long) ((UNSAFE.getByte(data, offset + 1) & 0xFF)) << 8) | // 202 ((long) ((UNSAFE.getByte(data, offset + 2) & 0xFF)) << 16) | // 203 ((long) ((UNSAFE.getByte(data, offset + 3) & 0xFF)) << 24) | // 204 ((long) ((UNSAFE.getByte(data, offset + 4) & 0xFF)) << 32) | // 205 ((long) ((UNSAFE.getByte(data, offset + 5) & 0xFF)) << 40) | // 206 ((long) ((UNSAFE.getByte(data, offset + 6) & 0xFF)) << 48) | // 207 ((long) (UNSAFE.getByte(data, offset + 7)) << 56); 208 } 209 210 protected AlignedUnsafeArrayTypeReader(byte[] data, long byteIndex) { 211 super(data, byteIndex); 212 } 213 214 @Override 215 public int getS2() { 216 int result = getS2(data, byteIndex); 217 byteIndex += Short.BYTES; 218 return result; 219 } 220 221 @Override 222 public int getS4() { 223 int result = getS4(data, byteIndex); 224 byteIndex += Integer.BYTES; 225 return result; 226 } 227 228 @Override 229 public long getS8() { 230 long result = getS8(data, byteIndex); 231 byteIndex += Long.BYTES; 232 return result; 233 } 234 }