import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; interface Vector {} abstract class FloatVector implements Vector {} class Float32Vector extends FloatVector { float f; } class Float128Vector extends FloatVector { long l0, l1; } class Float256Vector extends FloatVector { long l0, l1, l2, l3; } class Float512Vector extends FloatVector { long l0, l1, l2, l3, l4, l5, l6, l7; } public class Generic { static final Class THIS_CLASS = Generic.class; static float f32(Float32Vector v) { return v.f; } static float f128(Float128Vector v) { return Float.intBitsToFloat((int)v.l1) ; } static float f256(Float256Vector v) { return Float.intBitsToFloat((int)v.l3) ; } static float f512(Float512Vector v) { return Float.intBitsToFloat((int)v.l7) ; } static final MethodHandle dispatchMH; static { try { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mh32 = lookup.findStatic(THIS_CLASS, "f32", MethodType.methodType(float.class, Float32Vector.class)); MethodHandle mh128 = lookup.findStatic(THIS_CLASS, "f128", MethodType.methodType(float.class, Float128Vector.class)); MethodHandle mh256 = lookup.findStatic(THIS_CLASS, "f256", MethodType.methodType(float.class, Float256Vector.class)); MethodHandle mh512 = lookup.findStatic(THIS_CLASS, "f512", MethodType.methodType(float.class, Float512Vector.class)); MethodHandle mhThrow = MethodHandles.dropArguments( MethodHandles.insertArguments( MethodHandles.throwException(float.class, Error.class), 0, new Error()), 0, Object.class); MethodHandle isInstanceMH = lookup.findVirtual(Class.class, "isInstance", MethodType.methodType(boolean.class, Object.class)); MethodHandle t = MethodHandles.guardWithTest( MethodHandles.insertArguments(isInstanceMH, 0, Float512Vector.class), mh512.asType(MethodType.methodType(float.class, Object.class)), mhThrow); t = MethodHandles.guardWithTest( MethodHandles.insertArguments(isInstanceMH, 0, Float256Vector.class), mh256.asType(MethodType.methodType(float.class, Object.class)), t); t = MethodHandles.guardWithTest( MethodHandles.insertArguments(isInstanceMH, 0, Float128Vector.class), mh128.asType(MethodType.methodType(float.class, Object.class)), t); t = MethodHandles.guardWithTest( MethodHandles.insertArguments(isInstanceMH, 0, Float32Vector.class), mh32.asType(MethodType.methodType(float.class, Object.class)), t); dispatchMH = t; } catch (Throwable e) { throw new Error(e); } } static final MethodHandle F32MH = dispatchMH.asType(MethodType.methodType(float.class, Float32Vector.class)); static final MethodHandle F128MH = dispatchMH.asType(MethodType.methodType(float.class, Float128Vector.class)); static final MethodHandle F256MH = dispatchMH.asType(MethodType.methodType(float.class, Float256Vector.class)); static void warmup() { try { float f1 = (float) dispatchMH.invokeExact((Object) new Float32Vector()); float f2 = (float) dispatchMH.invokeExact((Object) new Float128Vector()); float f3 = (float) dispatchMH.invokeExact((Object) new Float256Vector()); float f4 = (float) dispatchMH.invokeExact((Object) new Float512Vector()); } catch (Throwable e) { throw new Error(e); } } /** * # {method} {0x000000012a650db0} 'test32' '(LFloat32Vector;)F' in 'Generic' * # parm0: rsi:rsi = 'Float32Vector' * # [sp+0x20] (sp of caller) * 0x11ab97140: mov %eax,-0x16000(%rsp) * 0x11ab97147: push %rbp * 0x11ab97148: sub $0x10,%rsp * * 0x11ab9714c: vmovss 0xc(%rsi),%xmm0 ;*getfield f {reexecute=0 rethrow=0 return_oop=0} * ; - Generic::f32@1 (line 25) * * 0x11ab97151: add $0x10,%rsp * 0x11ab97155: pop %rbp * 0x11ab97156: test %eax,-0xaf1e15c(%rip) # 0x000000010fc79000 * 0x11ab9715c: retq */ static float test32(Float32Vector v) { try { return (float)F32MH.invokeExact(v); } catch (Throwable e) { throw new Error(e); } } /** * # {method} {0x000000012a650e98} 'test32D' '(LFloat32Vector;)F' in 'Generic' * # parm0: rsi:rsi = 'Float32Vector' * # [sp+0x20] (sp of caller) * * 0x11ab9c4c0: mov %eax,-0x16000(%rsp) * 0x11ab9c4c7: push %rbp * 0x11ab9c4c8: sub $0x10,%rsp * * 0x11ab9c4cc: vmovss 0xc(%rsi),%xmm0 ;*getfield f {reexecute=0 rethrow=0 return_oop=0} * ; - Generic::f32@1 (line 25) * * 0x11ab9c4d1: add $0x10,%rsp * 0x11ab9c4d5: pop %rbp * 0x11ab9c4d6: test %eax,-0xaf234dc(%rip) # 0x000000010fc79000 * 0x11ab9c4dc: retq */ static float test32D(Float32Vector v) { try { return (float)dispatchMH.invokeExact((Object)v); } catch (Throwable e) { throw new Error(e); } } /** * # {method} {0x000000012a650f80} 'test128' '(LFloat128Vector;)F' in 'Generic' * # parm0: rsi:rsi = 'Float128Vector' * # [sp+0x20] (sp of caller) * * 0x11ab9c8c0: mov %eax,-0x16000(%rsp) * 0x11ab9c8c7: push %rbp * 0x11ab9c8c8: sub $0x10,%rsp ;*synchronization entry * * 0x11ab9c8cc: mov 0x18(%rsi),%r10 ; implicit exception: dispatches to 0x000000011ab9c8e4 * * 0x11ab9c8d0: mov %r10d,%r10d * 0x11ab9c8d3: vmovd %r10d,%xmm0 ;*invokestatic intBitsToFloat {reexecute=0 rethrow=0 return_oop=0} * ; - Generic::f128@5 (line 28) * * 0x11ab9c8d8: add $0x10,%rsp * 0x11ab9c8dc: pop %rbp * 0x11ab9c8dd: test %eax,-0xaf238e3(%rip) # 0x000000010fc79000 * 0x11ab9c8e3: retq */ static float test128(Float128Vector v) { try { return (float)F128MH.invokeExact(v); } catch (Throwable e) { throw new Error(e); } } /** * # {method} {0x000000012a6510a8} 'test128D' '(LFloat128Vector;)F' in 'Generic' * # parm0: rsi:rsi = 'Float128Vector' * # [sp+0x20] (sp of caller) * * 0x11ab9cd40: mov %eax,-0x16000(%rsp) * 0x11ab9cd47: push %rbp * 0x11ab9cd48: sub $0x10,%rsp ;*synchronization entry * * 0x11ab9cd4c: mov 0x18(%rsi),%r10 ; implicit exception: dispatches to 0x000000011ab9cd64 * * 0x11ab9cd50: mov %r10d,%r10d * 0x11ab9cd53: vmovd %r10d,%xmm0 ;*invokestatic intBitsToFloat {reexecute=0 rethrow=0 return_oop=0} * ; - Generic::f128@5 (line 28) * * 0x11ab9cd58: add $0x10,%rsp * 0x11ab9cd5c: pop %rbp * 0x11ab9cd5d: test %eax,-0xaf23d63(%rip) # 0x000000010fc79000 * 0x11ab9cd63: retq */ static float test128D(Float128Vector v) { try { return (float)dispatchMH.invokeExact((Object)v); } catch (Throwable e) { throw new Error(e); } } static float test256(Float256Vector v) { try { return (float)F256MH.invokeExact(v); } catch (Throwable e) { throw new Error(e); } } static float test256D(Float256Vector v) { try { return (float)dispatchMH.invokeExact((Object)v); } catch (Throwable e) { throw new Error(e); } } /** * # {method} {0x000000012a651360} 'testFloat' '(LFloatVector;)F' in 'Generic' * # parm0: rsi:rsi = 'FloatVector' * # [sp+0x30] (sp of caller) * * 0x000000011ab97e60: mov %eax,-0x16000(%rsp) * 0x000000011ab97e67: push %rbp * 0x000000011ab97e68: sub $0x20,%rsp ;*synchronization entry * * 0x000000011ab97e6c: mov 0x8(%rsi),%r10d ; implicit exception: dispatches to 0x000000011ab97ee9 * * 0x000000011ab97e70: cmp $0xf800c206,%r10d ; {metadata('Float32Vector')} * 0x000000011ab97e77: jne 0x000000011ab97e8a * * 0x000000011ab97e79: vmovss 0xc(%rsi),%xmm0 * * 0x000000011ab97e7e: add $0x20,%rsp * 0x000000011ab97e82: pop %rbp * 0x000000011ab97e83: test %eax,-0xaf1ee89(%rip) # 0x000000010fc79000 * 0x000000011ab97e89: retq * * 0x000000011ab97e8a: cmp $0xf800c246,%r10d ; {metadata('Float128Vector')} * 0x000000011ab97e91: jne 0x000000011ab97eaa * * 0x000000011ab97e93: cmp $0xf800c246,%r10d ; {metadata('Float128Vector')} * 0x000000011ab97e9a: jne 0x000000011ab97ec1 * * 0x000000011ab97e9c: mov 0x18(%rsi),%r10 * 0x000000011ab97ea0: mov %r10d,%r11d * 0x000000011ab97ea3: vmovd %r11d,%xmm0 ;*invokestatic intBitsToFloat {reexecute=0 rethrow=0 return_oop=0} * ; - Generic::f128@5 (line 28) * 0x000000011ab97ea8: jmp 0x000000011ab97e7e * * 0x000000011ab97eaa: cmp $0xf800c286,%r10d ; {metadata('Float256Vector')} * 0x000000011ab97eb1: jne 0x000000011ab97ed5 * * 0x000000011ab97eb3: mov 0x28(%rsi),%r10 * 0x000000011ab97eb7: mov %r10d,%r11d * 0x000000011ab97eba: vmovd %r11d,%xmm0 ;*invokestatic intBitsToFloat {reexecute=0 rethrow=0 return_oop=0} * ; - Generic::f256@5 (line 31) * 0x000000011ab97ebf: jmp 0x000000011ab97e7e * * 0x000000011ab97ec1: mov %rsi,%rbp * 0x000000011ab97ec4: mov $0xffffffce,%esi * 0x000000011ab97ec9: nop * 0x000000011ab97eca: nop * 0x000000011ab97ecb: callq 0x000000011aaa9120 ; ImmutableOopMap{rbp=Oop } * ; {runtime_call UncommonTrapBlob} * * 0x000000011ab97ed5: mov %rsi,(%rsp) * 0x000000011ab97ed9: mov $0xffffff76,%esi * 0x000000011ab97ede: nop * 0x000000011ab97edf: callq 0x000000011aaa9120 ; ImmutableOopMap{[0]=Oop } * ; {runtime_call UncommonTrapBlob} * * 0x000000011ab97ee9: mov %rsi,%rbp * 0x000000011ab97eec: mov $0xffffff6c,%esi * 0x000000011ab97ef1: nop * 0x000000011ab97ef2: nop * 0x000000011ab97ef3: callq 0x000000011aaa9120 ; ImmutableOopMap{rbp=Oop } * ; {runtime_call UncommonTrapBlob} * 0x000000011ab97efd: hlt * 0x000000011ab97efe: hlt * 0x000000011ab97eff: hlt */ static float testFloat(FloatVector v) { try { return (float)dispatchMH.invokeExact((Object)v); } catch (Throwable e) { throw new Error(e); } } public static void main(String[] args) { for (int i = 0; i < 100; i++) { warmup(); } for (int i = 0; i < 20000; i++) { test32(new Float32Vector()); test32D(new Float32Vector()); test128(new Float128Vector()); test128D(new Float128Vector()); test256(new Float256Vector()); test256D(new Float256Vector()); testFloat(new Float32Vector()); testFloat(new Float128Vector()); testFloat(new Float256Vector()); } } }