1 package jdk.internal.vm.vector; 2 3 import jdk.internal.HotSpotIntrinsicCandidate; 4 import jdk.internal.misc.Unsafe; 5 import jdk.internal.vm.annotation.ForceInline; 6 7 import java.nio.Buffer; 8 import java.nio.ByteBuffer; 9 import java.util.Objects; 10 import java.util.function.*; 11 12 public class VectorSupport { 13 static { 14 registerNatives(); 15 } 16 17 private static final Unsafe U = Unsafe.getUnsafe(); 18 19 // Unary 20 public static final int VECTOR_OP_ABS = 0; 21 public static final int VECTOR_OP_NEG = 1; 22 public static final int VECTOR_OP_SQRT = 2; 23 public static final int VECTOR_OP_NOT = 3; 24 25 // Binary 26 public static final int VECTOR_OP_ADD = 4; 27 public static final int VECTOR_OP_SUB = 5; 28 public static final int VECTOR_OP_MUL = 6; 29 public static final int VECTOR_OP_DIV = 7; 30 public static final int VECTOR_OP_MIN = 8; 31 public static final int VECTOR_OP_MAX = 9; 32 33 public static final int VECTOR_OP_AND = 10; 34 public static final int VECTOR_OP_OR = 11; 35 public static final int VECTOR_OP_XOR = 12; 36 37 // Ternary 38 public static final int VECTOR_OP_FMA = 13; 39 40 // Broadcast int 41 public static final int VECTOR_OP_LSHIFT = 14; 42 public static final int VECTOR_OP_RSHIFT = 15; 43 public static final int VECTOR_OP_URSHIFT = 16; 44 45 public static final int VECTOR_OP_CAST = 17; 46 public static final int VECTOR_OP_REINTERPRET = 18; 47 48 // enum BoolTest 49 public static final int BT_eq = 0; 50 public static final int BT_ne = 4; 51 public static final int BT_le = 5; 52 public static final int BT_ge = 7; 53 public static final int BT_lt = 3; 54 public static final int BT_gt = 1; 55 public static final int BT_overflow = 2; 56 public static final int BT_no_overflow = 6; 57 58 // BasicType codes, for primitives only: 59 public static final int 60 T_FLOAT = 6, 61 T_DOUBLE = 7, 62 T_BYTE = 8, 63 T_SHORT = 9, 64 T_INT = 10, 65 T_LONG = 11; 66 67 /* ============================================================================ */ 68 69 public static class VectorSpecies<E> {} 70 71 public static class VectorPayload { 72 private final Object payload; // array of primitives 73 74 public VectorPayload(Object payload) { 75 this.payload = payload; 76 } 77 78 protected final Object getPayload() { 79 return VectorSupport.maybeRebox(this).payload; 80 } 81 } 82 83 public static class Vector<E> extends VectorPayload { 84 public Vector(Object payload) { 85 super(payload); 86 } 87 } 88 89 public static class VectorShuffle<E> extends VectorPayload { 90 public VectorShuffle(Object payload) { 91 super(payload); 92 } 93 } 94 public static class VectorMask<E> extends VectorPayload { 95 public VectorMask(Object payload) { 96 super(payload); 97 } 98 } 99 100 /* ============================================================================ */ 101 public interface BroadcastOperation<VM, E, S extends VectorSpecies<E>> { 102 VM broadcast(long l, S s); 103 } 104 105 @HotSpotIntrinsicCandidate 106 public static 107 <VM, E, S extends VectorSpecies<E>> 108 VM broadcastCoerced(Class<? extends VM> vmClass, Class<E> E, int length, 109 long bits, S s, 110 BroadcastOperation<VM, E, S> defaultImpl) { 111 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 112 return defaultImpl.broadcast(bits, s); 113 } 114 115 /* ============================================================================ */ 116 public interface ShuffleIotaOperation<E> { 117 VectorShuffle<E> apply(int length, int start, int step); 118 } 119 120 @HotSpotIntrinsicCandidate 121 public static 122 <E> 123 VectorShuffle<E> shuffleIota(Class<?> E, Class<?> ShuffleClass, VectorSpecies<E> s, int length, 124 int start, int step, int wrap, ShuffleIotaOperation<E> defaultImpl) { 125 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 126 return defaultImpl.apply(length, start, step); 127 } 128 129 public interface ShuffleToVectorOperation<VM, Sh, E> { 130 VM apply(Sh s); 131 } 132 133 @HotSpotIntrinsicCandidate 134 public static 135 <VM ,Sh extends VectorShuffle<E>, E> 136 VM shuffleToVector(Class<?> VM, Class<?>E , Class<?> ShuffleClass, Sh s, int length, 137 ShuffleToVectorOperation<VM,Sh,E> defaultImpl) { 138 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 139 return defaultImpl.apply(s); 140 } 141 142 /* ============================================================================ */ 143 public interface IndexOperation<V extends Vector<E>, E, S extends VectorSpecies<E>> { 144 V index(V v, int step, S s); 145 } 146 147 //FIXME @HotSpotIntrinsicCandidate 148 public static 149 <V extends Vector<E>, E, S extends VectorSpecies<E>> 150 V indexVector(Class<? extends V> vClass, Class<E> E, int length, 151 V v, int step, S s, 152 IndexOperation<V, E, S> defaultImpl) { 153 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 154 return defaultImpl.index(v, step, s); 155 } 156 157 /* ============================================================================ */ 158 159 @HotSpotIntrinsicCandidate 160 public static 161 <V extends Vector<?>> 162 long reductionCoerced(int oprId, Class<?> vectorClass, Class<?> elementType, int length, 163 V v, 164 Function<V,Long> defaultImpl) { 165 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 166 return defaultImpl.apply(v); 167 } 168 169 /* ============================================================================ */ 170 171 public interface VecExtractOp<V> { 172 long apply(V v1, int idx); 173 } 174 175 @HotSpotIntrinsicCandidate 176 public static 177 <V extends Vector<?>> 178 long extract(Class<?> vectorClass, Class<?> elementType, int vlen, 179 V vec, int ix, 180 VecExtractOp<V> defaultImpl) { 181 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 182 return defaultImpl.apply(vec, ix); 183 } 184 185 /* ============================================================================ */ 186 187 public interface VecInsertOp<V> { 188 V apply(V v1, int idx, long val); 189 } 190 191 @HotSpotIntrinsicCandidate 192 public static 193 <V extends Vector<?>> 194 V insert(Class<? extends V> vectorClass, Class<?> elementType, int vlen, 195 V vec, int ix, long val, 196 VecInsertOp<V> defaultImpl) { 197 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 198 return defaultImpl.apply(vec, ix, val); 199 } 200 201 /* ============================================================================ */ 202 203 @HotSpotIntrinsicCandidate 204 public static 205 <VM> 206 VM unaryOp(int oprId, Class<? extends VM> vmClass, Class<?> elementType, int length, 207 VM vm, 208 Function<VM, VM> defaultImpl) { 209 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 210 return defaultImpl.apply(vm); 211 } 212 213 /* ============================================================================ */ 214 215 @HotSpotIntrinsicCandidate 216 public static 217 <VM> 218 VM binaryOp(int oprId, Class<? extends VM> vmClass, Class<?> elementType, int length, 219 VM vm1, VM vm2, 220 BiFunction<VM, VM, VM> defaultImpl) { 221 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 222 return defaultImpl.apply(vm1, vm2); 223 } 224 225 /* ============================================================================ */ 226 227 public interface TernaryOperation<V> { 228 V apply(V v1, V v2, V v3); 229 } 230 231 @HotSpotIntrinsicCandidate 232 public static 233 <VM> 234 VM ternaryOp(int oprId, Class<? extends VM> vmClass, Class<?> elementType, int length, 235 VM vm1, VM vm2, VM vm3, 236 TernaryOperation<VM> defaultImpl) { 237 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 238 return defaultImpl.apply(vm1, vm2, vm3); 239 } 240 241 /* ============================================================================ */ 242 243 // Memory operations 244 245 public interface LoadOperation<C, V, E, S extends VectorSpecies<E>> { 246 V load(C container, int index, S s); 247 } 248 249 @HotSpotIntrinsicCandidate 250 public static 251 <C, VM, E, S extends VectorSpecies<E>> 252 VM load(Class<? extends VM> vmClass, Class<E> E, int length, 253 Object base, long offset, // Unsafe addressing 254 C container, int index, S s, // Arguments for default implementation 255 LoadOperation<C, VM, E, S> defaultImpl) { 256 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 257 return defaultImpl.load(container, index, s); 258 } 259 260 /* ============================================================================ */ 261 262 public interface LoadVectorOperationWithMap<C, V extends Vector<?>, E, S extends VectorSpecies<E>> { 263 V loadWithMap(C container, int index, int[] indexMap, int indexM, S s); 264 } 265 266 @HotSpotIntrinsicCandidate 267 public static 268 <C, V extends Vector<?>, W extends Vector<Integer>, E, S extends VectorSpecies<E>> 269 V loadWithMap(Class<?> vectorClass, Class<E> E, int length, Class<?> vectorIndexClass, 270 Object base, long offset, // Unsafe addressing 271 W index_vector, 272 C container, int index, int[] indexMap, int indexM, S s, // Arguments for default implementation 273 LoadVectorOperationWithMap<C, V, E, S> defaultImpl) { 274 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 275 return defaultImpl.loadWithMap(container, index, indexMap, indexM, s); 276 } 277 278 /* ============================================================================ */ 279 280 public interface StoreVectorOperation<C, V extends Vector<?>> { 281 void store(C container, int index, V v); 282 } 283 284 @HotSpotIntrinsicCandidate 285 public static 286 <C, V extends Vector<?>> 287 void store(Class<?> vectorClass, Class<?> elementType, int length, 288 Object base, long offset, // Unsafe addressing 289 V v, 290 C container, int index, // Arguments for default implementation 291 StoreVectorOperation<C, V> defaultImpl) { 292 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 293 defaultImpl.store(container, index, v); 294 } 295 296 /* ============================================================================ */ 297 298 public interface StoreVectorOperationWithMap<C, V extends Vector<?>> { 299 void storeWithMap(C container, int index, V v, int[] indexMap, int indexM); 300 } 301 302 @HotSpotIntrinsicCandidate 303 public static 304 <C, V extends Vector<?>, W extends Vector<Integer>> 305 void storeWithMap(Class<?> vectorClass, Class<?> elementType, int length, Class<?> vectorIndexClass, 306 Object base, long offset, // Unsafe addressing 307 W index_vector, V v, 308 C container, int index, int[] indexMap, int indexM, // Arguments for default implementation 309 StoreVectorOperationWithMap<C, V> defaultImpl) { 310 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 311 defaultImpl.storeWithMap(container, index, v, indexMap, indexM); 312 } 313 314 /* ============================================================================ */ 315 316 @HotSpotIntrinsicCandidate 317 public static 318 <VM> 319 boolean test(int cond, Class<?> vmClass, Class<?> elementType, int length, 320 VM vm1, VM vm2, 321 BiFunction<VM, VM, Boolean> defaultImpl) { 322 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 323 return defaultImpl.apply(vm1, vm2); 324 } 325 326 /* ============================================================================ */ 327 328 public interface VectorCompareOp<V,M> { 329 M apply(int cond, V v1, V v2); 330 } 331 332 @HotSpotIntrinsicCandidate 333 public static <V extends Vector<E>, 334 M extends VectorMask<E>, 335 E> 336 M compare(int cond, Class<? extends V> vectorClass, Class<M> maskClass, Class<?> elementType, int length, 337 V v1, V v2, 338 VectorCompareOp<V,M> defaultImpl) { 339 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 340 return defaultImpl.apply(cond, v1, v2); 341 } 342 343 /* ============================================================================ */ 344 345 public interface VectorRearrangeOp<V extends Vector<E>, 346 Sh extends VectorShuffle<E>, 347 E> { 348 V apply(V v1, Sh shuffle); 349 } 350 351 @HotSpotIntrinsicCandidate 352 public static 353 <V extends Vector<E>, 354 Sh extends VectorShuffle<E>, 355 E> 356 V rearrangeOp(Class<? extends V> vectorClass, Class<Sh> shuffleClass, Class<?> elementType, int vlen, 357 V v1, Sh sh, 358 VectorRearrangeOp<V,Sh, E> defaultImpl) { 359 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 360 return defaultImpl.apply(v1, sh); 361 } 362 363 /* ============================================================================ */ 364 365 public interface VectorBlendOp<V extends Vector<E>, 366 M extends VectorMask<E>, 367 E> { 368 V apply(V v1, V v2, M mask); 369 } 370 371 @HotSpotIntrinsicCandidate 372 public static 373 <V extends Vector<E>, 374 M extends VectorMask<E>, 375 E> 376 V blend(Class<? extends V> vectorClass, Class<M> maskClass, Class<?> elementType, int length, 377 V v1, V v2, M m, 378 VectorBlendOp<V,M, E> defaultImpl) { 379 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 380 return defaultImpl.apply(v1, v2, m); 381 } 382 383 /* ============================================================================ */ 384 385 public interface VectorBroadcastIntOp<V extends Vector<?>> { 386 V apply(V v, int n); 387 } 388 389 @HotSpotIntrinsicCandidate 390 public static 391 <V extends Vector<?>> 392 V broadcastInt(int opr, Class<? extends V> vectorClass, Class<?> elementType, int length, 393 V v, int n, 394 VectorBroadcastIntOp<V> defaultImpl) { 395 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 396 return defaultImpl.apply(v, n); 397 } 398 399 /* ============================================================================ */ 400 401 public interface VectorConvertOp<VOUT, VIN, S> { 402 VOUT apply(VIN v, S species); 403 } 404 405 // Users of this intrinsic assume that it respects 406 // REGISTER_ENDIAN, which is currently ByteOrder.LITTLE_ENDIAN. 407 // See javadoc for REGISTER_ENDIAN. 408 409 @HotSpotIntrinsicCandidate 410 public static <VOUT extends VectorPayload, 411 VIN extends VectorPayload, 412 S extends VectorSpecies<?>> 413 VOUT convert(int oprId, 414 Class<?> fromVectorClass, Class<?> fromElementType, int fromVLen, 415 Class<?> toVectorClass, Class<?> toElementType, int toVLen, 416 VIN v, S s, 417 VectorConvertOp<VOUT, VIN, S> defaultImpl) { 418 assert isNonCapturingLambda(defaultImpl) : defaultImpl; 419 return defaultImpl.apply(v, s); 420 } 421 422 /* ============================================================================ */ 423 424 @HotSpotIntrinsicCandidate 425 public static <V> V maybeRebox(V v) { 426 // The fence is added here to avoid memory aliasing problems in C2 between scalar & vector accesses. 427 // TODO: move the fence generation into C2. Generate only when reboxing is taking place. 428 U.loadFence(); 429 return v; 430 } 431 432 /* ============================================================================ */ 433 434 // query the JVM's supported vector sizes and types 435 public static native int getMaxLaneCount(Class<?> etype); 436 437 /* ============================================================================ */ 438 439 public static boolean isNonCapturingLambda(Object o) { 440 return o.getClass().getDeclaredFields().length == 0; 441 } 442 443 /* ============================================================================ */ 444 445 private static native int registerNatives(); 446 }