1034 */ |
1034 */ |
1035 private static void throwIllegalAccessError() { |
1035 private static void throwIllegalAccessError() { |
1036 throw new IllegalAccessError(); |
1036 throw new IllegalAccessError(); |
1037 } |
1037 } |
1038 |
1038 |
1039 /** |
|
1040 * @return Returns true if the native byte ordering of this |
|
1041 * platform is big-endian, false if it is little-endian. |
|
1042 */ |
|
1043 public final boolean isBigEndian() { return BE; } |
|
1044 |
|
1045 /** |
|
1046 * @return Returns true if this platform is capable of performing |
|
1047 * accesses at addresses which are not aligned for the type of the |
|
1048 * primitive type being accessed, false otherwise. |
|
1049 */ |
|
1050 public final boolean unalignedAccess() { return unalignedAccess; } |
|
1051 |
|
1052 /** |
|
1053 * Fetches a value at some byte offset into a given Java object. |
|
1054 * More specifically, fetches a value within the given object |
|
1055 * <code>o</code> at the given offset, or (if <code>o</code> is |
|
1056 * null) from the memory address whose numerical value is the |
|
1057 * given offset. <p> |
|
1058 * |
|
1059 * The specification of this method is the same as {@link |
|
1060 * #getLong(Object, long)} except that the offset does not need to |
|
1061 * have been obtained from {@link #objectFieldOffset} on the |
|
1062 * {@link java.lang.reflect.Field} of some Java field. The value |
|
1063 * in memory is raw data, and need not correspond to any Java |
|
1064 * variable. Unless <code>o</code> is null, the value accessed |
|
1065 * must be entirely within the allocated object. The endianness |
|
1066 * of the value in memory is the endianness of the native platform. |
|
1067 * |
|
1068 * <p> The read will be atomic with respect to the largest power |
|
1069 * of two that divides the GCD of the offset and the storage size. |
|
1070 * For example, getLongUnaligned will make atomic reads of 2-, 4-, |
|
1071 * or 8-byte storage units if the offset is zero mod 2, 4, or 8, |
|
1072 * respectively. There are no other guarantees of atomicity. |
|
1073 * <p> |
|
1074 * 8-byte atomicity is only guaranteed on platforms on which |
|
1075 * support atomic accesses to longs. |
|
1076 * |
|
1077 * @param o Java heap object in which the value resides, if any, else |
|
1078 * null |
|
1079 * @param offset The offset in bytes from the start of the object |
|
1080 * @return the value fetched from the indicated object |
|
1081 * @throws RuntimeException No defined exceptions are thrown, not even |
|
1082 * {@link NullPointerException} |
|
1083 * @since 1.9 |
|
1084 */ |
|
1085 @HotSpotIntrinsicCandidate |
|
1086 public final long getLongUnaligned(Object o, long offset) { |
|
1087 if ((offset & 7) == 0) { |
|
1088 return getLong(o, offset); |
|
1089 } else if ((offset & 3) == 0) { |
|
1090 return makeLong(getInt(o, offset), |
|
1091 getInt(o, offset + 4)); |
|
1092 } else if ((offset & 1) == 0) { |
|
1093 return makeLong(getShort(o, offset), |
|
1094 getShort(o, offset + 2), |
|
1095 getShort(o, offset + 4), |
|
1096 getShort(o, offset + 6)); |
|
1097 } else { |
|
1098 return makeLong(getByte(o, offset), |
|
1099 getByte(o, offset + 1), |
|
1100 getByte(o, offset + 2), |
|
1101 getByte(o, offset + 3), |
|
1102 getByte(o, offset + 4), |
|
1103 getByte(o, offset + 5), |
|
1104 getByte(o, offset + 6), |
|
1105 getByte(o, offset + 7)); |
|
1106 } |
|
1107 } |
|
1108 /** |
|
1109 * As {@link #getLongUnaligned(Object, long)} but with an |
|
1110 * additional argument which specifies the endianness of the value |
|
1111 * as stored in memory. |
|
1112 * |
|
1113 * @param o Java heap object in which the variable resides |
|
1114 * @param offset The offset in bytes from the start of the object |
|
1115 * @param bigEndian The endianness of the value |
|
1116 * @return the value fetched from the indicated object |
|
1117 * @since 1.9 |
|
1118 */ |
|
1119 public final long getLongUnaligned(Object o, long offset, boolean bigEndian) { |
|
1120 return convEndian(bigEndian, getLongUnaligned(o, offset)); |
|
1121 } |
|
1122 |
|
1123 /** @see #getLongUnaligned(Object, long) */ |
|
1124 @HotSpotIntrinsicCandidate |
|
1125 public final int getIntUnaligned(Object o, long offset) { |
|
1126 if ((offset & 3) == 0) { |
|
1127 return getInt(o, offset); |
|
1128 } else if ((offset & 1) == 0) { |
|
1129 return makeInt(getShort(o, offset), |
|
1130 getShort(o, offset + 2)); |
|
1131 } else { |
|
1132 return makeInt(getByte(o, offset), |
|
1133 getByte(o, offset + 1), |
|
1134 getByte(o, offset + 2), |
|
1135 getByte(o, offset + 3)); |
|
1136 } |
|
1137 } |
|
1138 /** @see #getLongUnaligned(Object, long, boolean) */ |
|
1139 public final int getIntUnaligned(Object o, long offset, boolean bigEndian) { |
|
1140 return convEndian(bigEndian, getIntUnaligned(o, offset)); |
|
1141 } |
|
1142 |
|
1143 /** @see #getLongUnaligned(Object, long) */ |
|
1144 @HotSpotIntrinsicCandidate |
|
1145 public final short getShortUnaligned(Object o, long offset) { |
|
1146 if ((offset & 1) == 0) { |
|
1147 return getShort(o, offset); |
|
1148 } else { |
|
1149 return makeShort(getByte(o, offset), |
|
1150 getByte(o, offset + 1)); |
|
1151 } |
|
1152 } |
|
1153 /** @see #getLongUnaligned(Object, long, boolean) */ |
|
1154 public final short getShortUnaligned(Object o, long offset, boolean bigEndian) { |
|
1155 return convEndian(bigEndian, getShortUnaligned(o, offset)); |
|
1156 } |
|
1157 |
|
1158 /** @see #getLongUnaligned(Object, long) */ |
|
1159 @HotSpotIntrinsicCandidate |
|
1160 public final char getCharUnaligned(Object o, long offset) { |
|
1161 return (char)getShortUnaligned(o, offset); |
|
1162 } |
|
1163 |
|
1164 /** @see #getLongUnaligned(Object, long, boolean) */ |
|
1165 public final char getCharUnaligned(Object o, long offset, boolean bigEndian) { |
|
1166 return convEndian(bigEndian, getCharUnaligned(o, offset)); |
|
1167 } |
|
1168 |
|
1169 /** |
|
1170 * Stores a value at some byte offset into a given Java object. |
|
1171 * <p> |
|
1172 * The specification of this method is the same as {@link |
|
1173 * #getLong(Object, long)} except that the offset does not need to |
|
1174 * have been obtained from {@link #objectFieldOffset} on the |
|
1175 * {@link java.lang.reflect.Field} of some Java field. The value |
|
1176 * in memory is raw data, and need not correspond to any Java |
|
1177 * variable. The endianness of the value in memory is the |
|
1178 * endianness of the native platform. |
|
1179 * <p> |
|
1180 * The write will be atomic with respect to the largest power of |
|
1181 * two that divides the GCD of the offset and the storage size. |
|
1182 * For example, putLongUnaligned will make atomic writes of 2-, 4-, |
|
1183 * or 8-byte storage units if the offset is zero mod 2, 4, or 8, |
|
1184 * respectively. There are no other guarantees of atomicity. |
|
1185 * <p> |
|
1186 * 8-byte atomicity is only guaranteed on platforms on which |
|
1187 * support atomic accesses to longs. |
|
1188 * |
|
1189 * @param o Java heap object in which the value resides, if any, else |
|
1190 * null |
|
1191 * @param offset The offset in bytes from the start of the object |
|
1192 * @param x the value to store |
|
1193 * @throws RuntimeException No defined exceptions are thrown, not even |
|
1194 * {@link NullPointerException} |
|
1195 * @since 1.9 |
|
1196 */ |
|
1197 @HotSpotIntrinsicCandidate |
|
1198 public final void putLongUnaligned(Object o, long offset, long x) { |
|
1199 if ((offset & 7) == 0) { |
|
1200 putLong(o, offset, x); |
|
1201 } else if ((offset & 3) == 0) { |
|
1202 putLongParts(o, offset, |
|
1203 (int)(x >> 0), |
|
1204 (int)(x >>> 32)); |
|
1205 } else if ((offset & 1) == 0) { |
|
1206 putLongParts(o, offset, |
|
1207 (short)(x >>> 0), |
|
1208 (short)(x >>> 16), |
|
1209 (short)(x >>> 32), |
|
1210 (short)(x >>> 48)); |
|
1211 } else { |
|
1212 putLongParts(o, offset, |
|
1213 (byte)(x >>> 0), |
|
1214 (byte)(x >>> 8), |
|
1215 (byte)(x >>> 16), |
|
1216 (byte)(x >>> 24), |
|
1217 (byte)(x >>> 32), |
|
1218 (byte)(x >>> 40), |
|
1219 (byte)(x >>> 48), |
|
1220 (byte)(x >>> 56)); |
|
1221 } |
|
1222 } |
|
1223 |
|
1224 /** |
|
1225 * As {@link #putLongUnaligned(Object, long, long)} but with an additional |
|
1226 * argument which specifies the endianness of the value as stored in memory. |
|
1227 * @param o Java heap object in which the value resides |
|
1228 * @param offset The offset in bytes from the start of the object |
|
1229 * @param x the value to store |
|
1230 * @param bigEndian The endianness of the value |
|
1231 * @throws RuntimeException No defined exceptions are thrown, not even |
|
1232 * {@link NullPointerException} |
|
1233 * @since 1.9 |
|
1234 */ |
|
1235 public final void putLongUnaligned(Object o, long offset, long x, boolean bigEndian) { |
|
1236 putLongUnaligned(o, offset, convEndian(bigEndian, x)); |
|
1237 } |
|
1238 |
|
1239 /** @see #putLongUnaligned(Object, long, long) */ |
|
1240 @HotSpotIntrinsicCandidate |
|
1241 public final void putIntUnaligned(Object o, long offset, int x) { |
|
1242 if ((offset & 3) == 0) { |
|
1243 putInt(o, offset, x); |
|
1244 } else if ((offset & 1) == 0) { |
|
1245 putIntParts(o, offset, |
|
1246 (short)(x >> 0), |
|
1247 (short)(x >>> 16)); |
|
1248 } else { |
|
1249 putIntParts(o, offset, |
|
1250 (byte)(x >>> 0), |
|
1251 (byte)(x >>> 8), |
|
1252 (byte)(x >>> 16), |
|
1253 (byte)(x >>> 24)); |
|
1254 } |
|
1255 } |
|
1256 /** @see #putLongUnaligned(Object, long, long, boolean) */ |
|
1257 public final void putIntUnaligned(Object o, long offset, int x, boolean bigEndian) { |
|
1258 putIntUnaligned(o, offset, convEndian(bigEndian, x)); |
|
1259 } |
|
1260 |
|
1261 /** @see #putLongUnaligned(Object, long, long) */ |
|
1262 @HotSpotIntrinsicCandidate |
|
1263 public final void putShortUnaligned(Object o, long offset, short x) { |
|
1264 if ((offset & 1) == 0) { |
|
1265 putShort(o, offset, x); |
|
1266 } else { |
|
1267 putShortParts(o, offset, |
|
1268 (byte)(x >>> 0), |
|
1269 (byte)(x >>> 8)); |
|
1270 } |
|
1271 } |
|
1272 /** @see #putLongUnaligned(Object, long, long, boolean) */ |
|
1273 public final void putShortUnaligned(Object o, long offset, short x, boolean bigEndian) { |
|
1274 putShortUnaligned(o, offset, convEndian(bigEndian, x)); |
|
1275 } |
|
1276 |
|
1277 /** @see #putLongUnaligned(Object, long, long) */ |
|
1278 @HotSpotIntrinsicCandidate |
|
1279 public final void putCharUnaligned(Object o, long offset, char x) { |
|
1280 putShortUnaligned(o, offset, (short)x); |
|
1281 } |
|
1282 /** @see #putLongUnaligned(Object, long, long, boolean) */ |
|
1283 public final void putCharUnaligned(Object o, long offset, char x, boolean bigEndian) { |
|
1284 putCharUnaligned(o, offset, convEndian(bigEndian, x)); |
|
1285 } |
|
1286 |
|
1287 // JVM interface methods |
1039 // JVM interface methods |
1288 private native boolean unalignedAccess0(); |
1040 private native boolean unalignedAccess0(); |
1289 private native boolean isBigEndian0(); |
1041 private native boolean isBigEndian0(); |
1290 |
1042 |
1291 // BE is true iff the native endianness of this platform is big. |
|
1292 private static final boolean BE = theUnsafe.isBigEndian0(); |
|
1293 |
|
1294 // unalignedAccess is true iff this platform can perform unaligned accesses. |
|
1295 private static final boolean unalignedAccess = theUnsafe.unalignedAccess0(); |
|
1296 |
|
1297 private static int pickPos(int top, int pos) { return BE ? top - pos : pos; } |
|
1298 |
|
1299 // These methods construct integers from bytes. The byte ordering |
|
1300 // is the native endianness of this platform. |
|
1301 private static long makeLong(byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) { |
|
1302 return ((toUnsignedLong(i0) << pickPos(56, 0)) |
|
1303 | (toUnsignedLong(i1) << pickPos(56, 8)) |
|
1304 | (toUnsignedLong(i2) << pickPos(56, 16)) |
|
1305 | (toUnsignedLong(i3) << pickPos(56, 24)) |
|
1306 | (toUnsignedLong(i4) << pickPos(56, 32)) |
|
1307 | (toUnsignedLong(i5) << pickPos(56, 40)) |
|
1308 | (toUnsignedLong(i6) << pickPos(56, 48)) |
|
1309 | (toUnsignedLong(i7) << pickPos(56, 56))); |
|
1310 } |
|
1311 private static long makeLong(short i0, short i1, short i2, short i3) { |
|
1312 return ((toUnsignedLong(i0) << pickPos(48, 0)) |
|
1313 | (toUnsignedLong(i1) << pickPos(48, 16)) |
|
1314 | (toUnsignedLong(i2) << pickPos(48, 32)) |
|
1315 | (toUnsignedLong(i3) << pickPos(48, 48))); |
|
1316 } |
|
1317 private static long makeLong(int i0, int i1) { |
|
1318 return (toUnsignedLong(i0) << pickPos(32, 0)) |
|
1319 | (toUnsignedLong(i1) << pickPos(32, 32)); |
|
1320 } |
|
1321 private static int makeInt(short i0, short i1) { |
|
1322 return (toUnsignedInt(i0) << pickPos(16, 0)) |
|
1323 | (toUnsignedInt(i1) << pickPos(16, 16)); |
|
1324 } |
|
1325 private static int makeInt(byte i0, byte i1, byte i2, byte i3) { |
|
1326 return ((toUnsignedInt(i0) << pickPos(24, 0)) |
|
1327 | (toUnsignedInt(i1) << pickPos(24, 8)) |
|
1328 | (toUnsignedInt(i2) << pickPos(24, 16)) |
|
1329 | (toUnsignedInt(i3) << pickPos(24, 24))); |
|
1330 } |
|
1331 private static short makeShort(byte i0, byte i1) { |
|
1332 return (short)((toUnsignedInt(i0) << pickPos(8, 0)) |
|
1333 | (toUnsignedInt(i1) << pickPos(8, 8))); |
|
1334 } |
|
1335 |
|
1336 private static byte pick(byte le, byte be) { return BE ? be : le; } |
|
1337 private static short pick(short le, short be) { return BE ? be : le; } |
|
1338 private static int pick(int le, int be) { return BE ? be : le; } |
|
1339 |
|
1340 // These methods write integers to memory from smaller parts |
|
1341 // provided by their caller. The ordering in which these parts |
|
1342 // are written is the native endianness of this platform. |
|
1343 private void putLongParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3, byte i4, byte i5, byte i6, byte i7) { |
|
1344 putByte(o, offset + 0, pick(i0, i7)); |
|
1345 putByte(o, offset + 1, pick(i1, i6)); |
|
1346 putByte(o, offset + 2, pick(i2, i5)); |
|
1347 putByte(o, offset + 3, pick(i3, i4)); |
|
1348 putByte(o, offset + 4, pick(i4, i3)); |
|
1349 putByte(o, offset + 5, pick(i5, i2)); |
|
1350 putByte(o, offset + 6, pick(i6, i1)); |
|
1351 putByte(o, offset + 7, pick(i7, i0)); |
|
1352 } |
|
1353 private void putLongParts(Object o, long offset, short i0, short i1, short i2, short i3) { |
|
1354 putShort(o, offset + 0, pick(i0, i3)); |
|
1355 putShort(o, offset + 2, pick(i1, i2)); |
|
1356 putShort(o, offset + 4, pick(i2, i1)); |
|
1357 putShort(o, offset + 6, pick(i3, i0)); |
|
1358 } |
|
1359 private void putLongParts(Object o, long offset, int i0, int i1) { |
|
1360 putInt(o, offset + 0, pick(i0, i1)); |
|
1361 putInt(o, offset + 4, pick(i1, i0)); |
|
1362 } |
|
1363 private void putIntParts(Object o, long offset, short i0, short i1) { |
|
1364 putShort(o, offset + 0, pick(i0, i1)); |
|
1365 putShort(o, offset + 2, pick(i1, i0)); |
|
1366 } |
|
1367 private void putIntParts(Object o, long offset, byte i0, byte i1, byte i2, byte i3) { |
|
1368 putByte(o, offset + 0, pick(i0, i3)); |
|
1369 putByte(o, offset + 1, pick(i1, i2)); |
|
1370 putByte(o, offset + 2, pick(i2, i1)); |
|
1371 putByte(o, offset + 3, pick(i3, i0)); |
|
1372 } |
|
1373 private void putShortParts(Object o, long offset, byte i0, byte i1) { |
|
1374 putByte(o, offset + 0, pick(i0, i1)); |
|
1375 putByte(o, offset + 1, pick(i1, i0)); |
|
1376 } |
|
1377 |
|
1378 // Zero-extend an integer |
|
1379 private static int toUnsignedInt(byte n) { return n & 0xff; } |
|
1380 private static int toUnsignedInt(short n) { return n & 0xffff; } |
|
1381 private static long toUnsignedLong(byte n) { return n & 0xffl; } |
|
1382 private static long toUnsignedLong(short n) { return n & 0xffffl; } |
|
1383 private static long toUnsignedLong(int n) { return n & 0xffffffffl; } |
|
1384 |
|
1385 // Maybe byte-reverse an integer |
|
1386 private static char convEndian(boolean big, char n) { return big == BE ? n : Character.reverseBytes(n); } |
|
1387 private static short convEndian(boolean big, short n) { return big == BE ? n : Short.reverseBytes(n) ; } |
|
1388 private static int convEndian(boolean big, int n) { return big == BE ? n : Integer.reverseBytes(n) ; } |
|
1389 private static long convEndian(boolean big, long n) { return big == BE ? n : Long.reverseBytes(n) ; } |
|
1390 } |
1043 } |