404 * @see MethodHandles |
403 * @see MethodHandles |
405 * @see MethodType |
404 * @see MethodType |
406 * @since 9 |
405 * @since 9 |
407 */ |
406 */ |
408 public abstract class VarHandle { |
407 public abstract class VarHandle { |
409 // Use explicit final fields rather than an @Stable array as |
|
410 // this can reduce the memory per handle |
|
411 // e.g. by 24 bytes on 64 bit architectures |
|
412 final MethodType typeGet; |
|
413 final MethodType typeSet; |
|
414 final MethodType typeCompareSwap; |
|
415 final MethodType typeCompareExchange; |
|
416 final MethodType typeGetAndUpdate; |
|
417 |
|
418 final VarForm vform; |
408 final VarForm vform; |
419 |
409 |
420 VarHandle(VarForm vform, Class<?> receiver, Class<?> value, Class<?>... intermediate) { |
410 VarHandle(VarForm vform) { |
421 this.vform = vform; |
411 this.vform = vform; |
422 |
|
423 // (Receiver, <Intermediates>) |
|
424 List<Class<?>> l = new ArrayList<>(); |
|
425 if (receiver != null) |
|
426 l.add(receiver); |
|
427 l.addAll(Arrays.asList(intermediate)); |
|
428 |
|
429 // (Receiver, <Intermediates>)Value |
|
430 this.typeGet = MethodType.methodType(value, l); |
|
431 |
|
432 // (Receiver, <Intermediates>, Value)void |
|
433 l.add(value); |
|
434 this.typeSet = MethodType.methodType(void.class, l); |
|
435 |
|
436 // (Receiver, <Intermediates>, Value)Value |
|
437 this.typeGetAndUpdate = MethodType.methodType(value, l); |
|
438 |
|
439 // (Receiver, <Intermediates>, Value, Value)boolean |
|
440 l.add(value); |
|
441 this.typeCompareSwap = MethodType.methodType(boolean.class, l); |
|
442 |
|
443 // (Receiver, <Intermediates>, Value, Value)Value |
|
444 this.typeCompareExchange = MethodType.methodType(value, l); |
|
445 } |
412 } |
446 |
413 |
447 RuntimeException unsupported() { |
414 RuntimeException unsupported() { |
448 return new UnsupportedOperationException(); |
415 return new UnsupportedOperationException(); |
449 } |
416 } |
1088 @MethodHandle.PolymorphicSignature |
1055 @MethodHandle.PolymorphicSignature |
1089 @HotSpotIntrinsicCandidate |
1056 @HotSpotIntrinsicCandidate |
1090 Object addAndGet(Object... args); |
1057 Object addAndGet(Object... args); |
1091 |
1058 |
1092 enum AccessType { |
1059 enum AccessType { |
1093 GET, // 0 |
1060 GET(Object.class) { |
1094 SET, // 1 |
1061 @Override |
1095 COMPARE_AND_SWAP, // 2 |
1062 MethodType accessModeType(Class<?> receiver, Class<?> value, |
1096 COMPARE_AND_EXCHANGE, // 3 |
1063 Class<?>... intermediate) { |
1097 GET_AND_UPDATE; // 4 |
1064 Class<?>[] ps = allocateParameters(0, receiver, intermediate); |
1098 |
1065 fillParameters(ps, receiver, intermediate); |
1099 MethodType getMethodType(VarHandle vh) { |
1066 return MethodType.methodType(value, ps); |
1100 return getMethodType(this.ordinal(), vh); |
|
1101 } |
|
1102 |
|
1103 @ForceInline |
|
1104 static MethodType getMethodType(int ordinal, VarHandle vh) { |
|
1105 if (ordinal == 0) { |
|
1106 return vh.typeGet; |
|
1107 } |
1067 } |
1108 else if (ordinal == 1) { |
1068 }, |
1109 return vh.typeSet; |
1069 SET(void.class) { |
|
1070 @Override |
|
1071 MethodType accessModeType(Class<?> receiver, Class<?> value, |
|
1072 Class<?>... intermediate) { |
|
1073 Class<?>[] ps = allocateParameters(1, receiver, intermediate); |
|
1074 int i = fillParameters(ps, receiver, intermediate); |
|
1075 ps[i] = value; |
|
1076 return MethodType.methodType(void.class, ps); |
1110 } |
1077 } |
1111 else if (ordinal == 2) { |
1078 }, |
1112 return vh.typeCompareSwap; |
1079 COMPARE_AND_SWAP(boolean.class) { |
|
1080 @Override |
|
1081 MethodType accessModeType(Class<?> receiver, Class<?> value, |
|
1082 Class<?>... intermediate) { |
|
1083 Class<?>[] ps = allocateParameters(2, receiver, intermediate); |
|
1084 int i = fillParameters(ps, receiver, intermediate); |
|
1085 ps[i++] = value; |
|
1086 ps[i] = value; |
|
1087 return MethodType.methodType(boolean.class, ps); |
1113 } |
1088 } |
1114 else if (ordinal == 3) { |
1089 }, |
1115 return vh.typeCompareExchange; |
1090 COMPARE_AND_EXCHANGE(Object.class) { |
|
1091 @Override |
|
1092 MethodType accessModeType(Class<?> receiver, Class<?> value, |
|
1093 Class<?>... intermediate) { |
|
1094 Class<?>[] ps = allocateParameters(2, receiver, intermediate); |
|
1095 int i = fillParameters(ps, receiver, intermediate); |
|
1096 ps[i++] = value; |
|
1097 ps[i] = value; |
|
1098 return MethodType.methodType(value, ps); |
1116 } |
1099 } |
1117 else if (ordinal == 4) { |
1100 }, |
1118 return vh.typeGetAndUpdate; |
1101 GET_AND_UPDATE(Object.class) { |
|
1102 @Override |
|
1103 MethodType accessModeType(Class<?> receiver, Class<?> value, |
|
1104 Class<?>... intermediate) { |
|
1105 Class<?>[] ps = allocateParameters(1, receiver, intermediate); |
|
1106 int i = fillParameters(ps, receiver, intermediate); |
|
1107 ps[i] = value; |
|
1108 return MethodType.methodType(value, ps); |
1119 } |
1109 } |
1120 else { |
1110 }; |
1121 throw new IllegalStateException("Illegal access type: " + ordinal); |
1111 |
1122 } |
1112 final Class<?> returnType; |
|
1113 final boolean isMonomorphicInReturnType; |
|
1114 |
|
1115 AccessType(Class<?> returnType) { |
|
1116 this.returnType = returnType; |
|
1117 isMonomorphicInReturnType = returnType != Object.class; |
|
1118 } |
|
1119 |
|
1120 abstract MethodType accessModeType(Class<?> receiver, Class<?> value, |
|
1121 Class<?>... intermediate); |
|
1122 |
|
1123 private static Class<?>[] allocateParameters(int values, |
|
1124 Class<?> receiver, Class<?>... intermediate) { |
|
1125 int size = ((receiver != null) ? 1 : 0) + intermediate.length + values; |
|
1126 return new Class<?>[size]; |
|
1127 } |
|
1128 |
|
1129 private static int fillParameters(Class<?>[] ps, |
|
1130 Class<?> receiver, Class<?>... intermediate) { |
|
1131 int i = 0; |
|
1132 if (receiver != null) |
|
1133 ps[i++] = receiver; |
|
1134 for (int j = 0; j < intermediate.length; j++) |
|
1135 ps[i++] = intermediate[j]; |
|
1136 return i; |
1123 } |
1137 } |
1124 } |
1138 } |
1125 |
1139 |
1126 /** |
1140 /** |
1127 * The set of access modes that specify how a variable, referenced by a |
1141 * The set of access modes that specify how a variable, referenced by a |
1131 /** |
1145 /** |
1132 * The access mode whose access is specified by the corresponding |
1146 * The access mode whose access is specified by the corresponding |
1133 * method |
1147 * method |
1134 * {@link VarHandle#get VarHandle.get} |
1148 * {@link VarHandle#get VarHandle.get} |
1135 */ |
1149 */ |
1136 GET("get", AccessType.GET, Object.class), |
1150 GET("get", AccessType.GET), |
1137 /** |
1151 /** |
1138 * The access mode whose access is specified by the corresponding |
1152 * The access mode whose access is specified by the corresponding |
1139 * method |
1153 * method |
1140 * {@link VarHandle#set VarHandle.set} |
1154 * {@link VarHandle#set VarHandle.set} |
1141 */ |
1155 */ |
1142 SET("set", AccessType.SET, void.class), |
1156 SET("set", AccessType.SET), |
1143 /** |
1157 /** |
1144 * The access mode whose access is specified by the corresponding |
1158 * The access mode whose access is specified by the corresponding |
1145 * method |
1159 * method |
1146 * {@link VarHandle#getVolatile VarHandle.getVolatile} |
1160 * {@link VarHandle#getVolatile VarHandle.getVolatile} |
1147 */ |
1161 */ |
1148 GET_VOLATILE("getVolatile", AccessType.GET, Object.class), |
1162 GET_VOLATILE("getVolatile", AccessType.GET), |
1149 /** |
1163 /** |
1150 * The access mode whose access is specified by the corresponding |
1164 * The access mode whose access is specified by the corresponding |
1151 * method |
1165 * method |
1152 * {@link VarHandle#setVolatile VarHandle.setVolatile} |
1166 * {@link VarHandle#setVolatile VarHandle.setVolatile} |
1153 */ |
1167 */ |
1154 SET_VOLATILE("setVolatile", AccessType.SET, void.class), |
1168 SET_VOLATILE("setVolatile", AccessType.SET), |
1155 /** |
1169 /** |
1156 * The access mode whose access is specified by the corresponding |
1170 * The access mode whose access is specified by the corresponding |
1157 * method |
1171 * method |
1158 * {@link VarHandle#getAcquire VarHandle.getAcquire} |
1172 * {@link VarHandle#getAcquire VarHandle.getAcquire} |
1159 */ |
1173 */ |
1160 GET_ACQUIRE("getAcquire", AccessType.GET, Object.class), |
1174 GET_ACQUIRE("getAcquire", AccessType.GET), |
1161 /** |
1175 /** |
1162 * The access mode whose access is specified by the corresponding |
1176 * The access mode whose access is specified by the corresponding |
1163 * method |
1177 * method |
1164 * {@link VarHandle#setRelease VarHandle.setRelease} |
1178 * {@link VarHandle#setRelease VarHandle.setRelease} |
1165 */ |
1179 */ |
1166 SET_RELEASE("setRelease", AccessType.SET, void.class), |
1180 SET_RELEASE("setRelease", AccessType.SET), |
1167 /** |
1181 /** |
1168 * The access mode whose access is specified by the corresponding |
1182 * The access mode whose access is specified by the corresponding |
1169 * method |
1183 * method |
1170 * {@link VarHandle#getOpaque VarHandle.getOpaque} |
1184 * {@link VarHandle#getOpaque VarHandle.getOpaque} |
1171 */ |
1185 */ |
1172 GET_OPAQUE("getOpaque", AccessType.GET, Object.class), |
1186 GET_OPAQUE("getOpaque", AccessType.GET), |
1173 /** |
1187 /** |
1174 * The access mode whose access is specified by the corresponding |
1188 * The access mode whose access is specified by the corresponding |
1175 * method |
1189 * method |
1176 * {@link VarHandle#setOpaque VarHandle.setOpaque} |
1190 * {@link VarHandle#setOpaque VarHandle.setOpaque} |
1177 */ |
1191 */ |
1178 SET_OPAQUE("setOpaque", AccessType.SET, void.class), |
1192 SET_OPAQUE("setOpaque", AccessType.SET), |
1179 /** |
1193 /** |
1180 * The access mode whose access is specified by the corresponding |
1194 * The access mode whose access is specified by the corresponding |
1181 * method |
1195 * method |
1182 * {@link VarHandle#compareAndSet VarHandle.compareAndSet} |
1196 * {@link VarHandle#compareAndSet VarHandle.compareAndSet} |
1183 */ |
1197 */ |
1184 COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class), |
1198 COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP), |
1185 /** |
1199 /** |
1186 * The access mode whose access is specified by the corresponding |
1200 * The access mode whose access is specified by the corresponding |
1187 * method |
1201 * method |
1188 * {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile} |
1202 * {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile} |
1189 */ |
1203 */ |
1190 COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class), |
1204 COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE), |
1191 /** |
1205 /** |
1192 * The access mode whose access is specified by the corresponding |
1206 * The access mode whose access is specified by the corresponding |
1193 * method |
1207 * method |
1194 * {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire} |
1208 * {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire} |
1195 */ |
1209 */ |
1196 COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class), |
1210 COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE), |
1197 /** |
1211 /** |
1198 * The access mode whose access is specified by the corresponding |
1212 * The access mode whose access is specified by the corresponding |
1199 * method |
1213 * method |
1200 * {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease} |
1214 * {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease} |
1201 */ |
1215 */ |
1202 COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class), |
1216 COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE), |
1203 /** |
1217 /** |
1204 * The access mode whose access is specified by the corresponding |
1218 * The access mode whose access is specified by the corresponding |
1205 * method |
1219 * method |
1206 * {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet} |
1220 * {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet} |
1207 */ |
1221 */ |
1208 WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class), |
1222 WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP), |
1209 /** |
1223 /** |
1210 * The access mode whose access is specified by the corresponding |
1224 * The access mode whose access is specified by the corresponding |
1211 * method |
1225 * method |
1212 * {@link VarHandle#weakCompareAndSetVolatile VarHandle.weakCompareAndSetVolatile} |
1226 * {@link VarHandle#weakCompareAndSetVolatile VarHandle.weakCompareAndSetVolatile} |
1213 */ |
1227 */ |
1214 WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP, boolean.class), |
1228 WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP), |
1215 /** |
1229 /** |
1216 * The access mode whose access is specified by the corresponding |
1230 * The access mode whose access is specified by the corresponding |
1217 * method |
1231 * method |
1218 * {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire} |
1232 * {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire} |
1219 */ |
1233 */ |
1220 WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class), |
1234 WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP), |
1221 /** |
1235 /** |
1222 * The access mode whose access is specified by the corresponding |
1236 * The access mode whose access is specified by the corresponding |
1223 * method |
1237 * method |
1224 * {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease} |
1238 * {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease} |
1225 */ |
1239 */ |
1226 WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class), |
1240 WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP), |
1227 /** |
1241 /** |
1228 * The access mode whose access is specified by the corresponding |
1242 * The access mode whose access is specified by the corresponding |
1229 * method |
1243 * method |
1230 * {@link VarHandle#getAndSet VarHandle.getAndSet} |
1244 * {@link VarHandle#getAndSet VarHandle.getAndSet} |
1231 */ |
1245 */ |
1232 GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class), |
1246 GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE), |
1233 /** |
1247 /** |
1234 * The access mode whose access is specified by the corresponding |
1248 * The access mode whose access is specified by the corresponding |
1235 * method |
1249 * method |
1236 * {@link VarHandle#getAndAdd VarHandle.getAndAdd} |
1250 * {@link VarHandle#getAndAdd VarHandle.getAndAdd} |
1237 */ |
1251 */ |
1238 GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class), |
1252 GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE), |
1239 /** |
1253 /** |
1240 * The access mode whose access is specified by the corresponding |
1254 * The access mode whose access is specified by the corresponding |
1241 * method |
1255 * method |
1242 * {@link VarHandle#addAndGet VarHandle.addAndGet} |
1256 * {@link VarHandle#addAndGet VarHandle.addAndGet} |
1243 */ |
1257 */ |
1244 ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class), |
1258 ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE), |
1245 ; |
1259 ; |
1246 |
1260 |
1247 static final Map<String, AccessMode> methodNameToAccessMode; |
1261 static final Map<String, AccessMode> methodNameToAccessMode; |
1248 static { |
1262 static { |
1249 // Initial capacity of # values is sufficient to avoid resizes |
1263 // Initial capacity of # values is sufficient to avoid resizes |
1415 * @return a method handle bound to this VarHandle and the given access mode |
1436 * @return a method handle bound to this VarHandle and the given access mode |
1416 */ |
1437 */ |
1417 public final MethodHandle toMethodHandle(AccessMode accessMode) { |
1438 public final MethodHandle toMethodHandle(AccessMode accessMode) { |
1418 MemberName mn = AccessMode.getMemberName(accessMode.ordinal(), vform); |
1439 MemberName mn = AccessMode.getMemberName(accessMode.ordinal(), vform); |
1419 if (mn != null) { |
1440 if (mn != null) { |
1420 return DirectMethodHandle.make(mn). |
1441 MethodHandle mh = getMethodHandle(accessMode.ordinal()); |
1421 bindTo(this). |
1442 return mh.bindTo(this); |
1422 asType(accessMode.at.getMethodType(this)); |
|
1423 } |
1443 } |
1424 else { |
1444 else { |
1425 // Ensure an UnsupportedOperationException is thrown |
1445 // Ensure an UnsupportedOperationException is thrown |
1426 return MethodHandles.varHandleInvoker(accessMode, accessModeType(accessMode)). |
1446 return MethodHandles.varHandleInvoker(accessMode, accessModeType(accessMode)). |
1427 bindTo(this); |
1447 bindTo(this); |
1428 } |
1448 } |
1429 } |
1449 } |
|
1450 |
|
1451 @Stable |
|
1452 TypesAndInvokers typesAndInvokers; |
|
1453 |
|
1454 static class TypesAndInvokers { |
|
1455 final @Stable |
|
1456 MethodType[] methodType_table = |
|
1457 new MethodType[VarHandle.AccessType.values().length]; |
|
1458 |
|
1459 final @Stable |
|
1460 MethodHandle[] methodHandle_table = |
|
1461 new MethodHandle[AccessMode.values().length]; |
|
1462 } |
|
1463 |
|
1464 @ForceInline |
|
1465 private final TypesAndInvokers getTypesAndInvokers() { |
|
1466 TypesAndInvokers tis = typesAndInvokers; |
|
1467 if (tis == null) { |
|
1468 tis = typesAndInvokers = new TypesAndInvokers(); |
|
1469 } |
|
1470 return tis; |
|
1471 } |
|
1472 |
|
1473 @ForceInline |
|
1474 final MethodHandle getMethodHandle(int mode) { |
|
1475 TypesAndInvokers tis = getTypesAndInvokers(); |
|
1476 MethodHandle mh = tis.methodHandle_table[mode]; |
|
1477 if (mh == null) { |
|
1478 mh = tis.methodHandle_table[mode] = getMethodHandleUncached(tis, mode); |
|
1479 } |
|
1480 return mh; |
|
1481 } |
|
1482 private final MethodHandle getMethodHandleUncached(TypesAndInvokers tis, int mode) { |
|
1483 MethodType mt = accessModeType(AccessMode.values()[mode]). |
|
1484 insertParameterTypes(0, VarHandle.class); |
|
1485 MemberName mn = vform.getMemberName(mode); |
|
1486 DirectMethodHandle dmh = DirectMethodHandle.make(mn); |
|
1487 // Such a method handle must not be publically exposed directly |
|
1488 // otherwise it can be cracked, it must be transformed or rebound |
|
1489 // before exposure |
|
1490 MethodHandle mh = dmh.copyWith(mt, dmh.form); |
|
1491 assert mh.type().erase() == mn.getMethodType().erase(); |
|
1492 return mh; |
|
1493 } |
|
1494 |
1430 |
1495 |
1431 /*non-public*/ |
1496 /*non-public*/ |
1432 final void updateVarForm(VarForm newVForm) { |
1497 final void updateVarForm(VarForm newVForm) { |
1433 if (vform == newVForm) return; |
1498 if (vform == newVForm) return; |
1434 UNSAFE.putObject(this, VFORM_OFFSET, newVForm); |
1499 UNSAFE.putObject(this, VFORM_OFFSET, newVForm); |