1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*795d594fSAndroid Build Coastguard Worker * 10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*795d594fSAndroid Build Coastguard Worker * limitations under the License. 15*795d594fSAndroid Build Coastguard Worker */ 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker import static java.lang.invoke.MethodHandles.lookup; 18*795d594fSAndroid Build Coastguard Worker import static java.lang.invoke.MethodType.methodType; 19*795d594fSAndroid Build Coastguard Worker 20*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandle; 21*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandles; 22*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.VarHandle; 23*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.WrongMethodTypeException; 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker public final class Main { 26*795d594fSAndroid Build Coastguard Worker static class TestSetupError extends Error { TestSetupError(String message, Throwable cause)27*795d594fSAndroid Build Coastguard Worker TestSetupError(String message, Throwable cause) { 28*795d594fSAndroid Build Coastguard Worker super(message, cause); 29*795d594fSAndroid Build Coastguard Worker } 30*795d594fSAndroid Build Coastguard Worker } 31*795d594fSAndroid Build Coastguard Worker failAssertion(String message)32*795d594fSAndroid Build Coastguard Worker private static void failAssertion(String message) { 33*795d594fSAndroid Build Coastguard Worker StringBuilder sb = new StringBuilder(); 34*795d594fSAndroid Build Coastguard Worker sb.append("Test failure: "); 35*795d594fSAndroid Build Coastguard Worker sb.append(message); 36*795d594fSAndroid Build Coastguard Worker throw new AssertionError(sb.toString()); 37*795d594fSAndroid Build Coastguard Worker } 38*795d594fSAndroid Build Coastguard Worker assertUnreachable()39*795d594fSAndroid Build Coastguard Worker private static void assertUnreachable() throws Throwable { 40*795d594fSAndroid Build Coastguard Worker failAssertion("Unreachable"); 41*795d594fSAndroid Build Coastguard Worker } 42*795d594fSAndroid Build Coastguard Worker failAssertEquals(Object expected, Object actual)43*795d594fSAndroid Build Coastguard Worker private static void failAssertEquals(Object expected, Object actual) { 44*795d594fSAndroid Build Coastguard Worker StringBuilder sb = new StringBuilder(); 45*795d594fSAndroid Build Coastguard Worker sb.append(expected); 46*795d594fSAndroid Build Coastguard Worker sb.append(" != "); 47*795d594fSAndroid Build Coastguard Worker sb.append(actual); 48*795d594fSAndroid Build Coastguard Worker failAssertion(sb.toString()); 49*795d594fSAndroid Build Coastguard Worker } 50*795d594fSAndroid Build Coastguard Worker assertEquals(boolean expected, boolean actual)51*795d594fSAndroid Build Coastguard Worker private static void assertEquals(boolean expected, boolean actual) { 52*795d594fSAndroid Build Coastguard Worker if (expected != actual) { 53*795d594fSAndroid Build Coastguard Worker failAssertEquals(expected, actual); 54*795d594fSAndroid Build Coastguard Worker } 55*795d594fSAndroid Build Coastguard Worker } 56*795d594fSAndroid Build Coastguard Worker assertEquals(int expected, int actual)57*795d594fSAndroid Build Coastguard Worker private static void assertEquals(int expected, int actual) { 58*795d594fSAndroid Build Coastguard Worker if (expected != actual) { 59*795d594fSAndroid Build Coastguard Worker failAssertEquals(expected, actual); 60*795d594fSAndroid Build Coastguard Worker } 61*795d594fSAndroid Build Coastguard Worker } 62*795d594fSAndroid Build Coastguard Worker assertEquals(long expected, long actual)63*795d594fSAndroid Build Coastguard Worker private static void assertEquals(long expected, long actual) { 64*795d594fSAndroid Build Coastguard Worker if (expected != actual) { 65*795d594fSAndroid Build Coastguard Worker failAssertEquals(expected, actual); 66*795d594fSAndroid Build Coastguard Worker } 67*795d594fSAndroid Build Coastguard Worker } 68*795d594fSAndroid Build Coastguard Worker assertEquals(float expected, float actual)69*795d594fSAndroid Build Coastguard Worker private static void assertEquals(float expected, float actual) { 70*795d594fSAndroid Build Coastguard Worker if (expected != actual) { 71*795d594fSAndroid Build Coastguard Worker failAssertEquals(expected, actual); 72*795d594fSAndroid Build Coastguard Worker } 73*795d594fSAndroid Build Coastguard Worker } 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker static class FieldVarHandleExactInvokerTest { 76*795d594fSAndroid Build Coastguard Worker private static final Class<?> THIS_CLASS = FieldVarHandleExactInvokerTest.class; 77*795d594fSAndroid Build Coastguard Worker private static final VarHandle fieldVarHandle; 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker int field; 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker static { 82*795d594fSAndroid Build Coastguard Worker try { 83*795d594fSAndroid Build Coastguard Worker fieldVarHandle = lookup().findVarHandle(THIS_CLASS, "field", int.class); 84*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 85*795d594fSAndroid Build Coastguard Worker throw new TestSetupError("Failed to lookup of field", e); 86*795d594fSAndroid Build Coastguard Worker } 87*795d594fSAndroid Build Coastguard Worker } 88*795d594fSAndroid Build Coastguard Worker run()89*795d594fSAndroid Build Coastguard Worker void run() throws Throwable { 90*795d594fSAndroid Build Coastguard Worker System.out.println(THIS_CLASS.getName()); 91*795d594fSAndroid Build Coastguard Worker 92*795d594fSAndroid Build Coastguard Worker MethodHandle invokerMethodHandle = 93*795d594fSAndroid Build Coastguard Worker MethodHandles.varHandleExactInvoker( 94*795d594fSAndroid Build Coastguard Worker VarHandle.AccessMode.GET_AND_SET, 95*795d594fSAndroid Build Coastguard Worker methodType(int.class, THIS_CLASS, int.class)); 96*795d594fSAndroid Build Coastguard Worker 97*795d594fSAndroid Build Coastguard Worker field = 3; 98*795d594fSAndroid Build Coastguard Worker assertEquals(3, (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, 4)); 99*795d594fSAndroid Build Coastguard Worker assertEquals(4, field); 100*795d594fSAndroid Build Coastguard Worker 101*795d594fSAndroid Build Coastguard Worker // 102*795d594fSAndroid Build Coastguard Worker // Check invocations with MethodHandle.invokeExact() 103*795d594fSAndroid Build Coastguard Worker // 104*795d594fSAndroid Build Coastguard Worker try { 105*795d594fSAndroid Build Coastguard Worker // Check for unboxing 106*795d594fSAndroid Build Coastguard Worker int i = 107*795d594fSAndroid Build Coastguard Worker (int) 108*795d594fSAndroid Build Coastguard Worker invokerMethodHandle.invokeExact( 109*795d594fSAndroid Build Coastguard Worker fieldVarHandle, this, Integer.valueOf(3)); 110*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 111*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 112*795d594fSAndroid Build Coastguard Worker assertEquals(4, field); 113*795d594fSAndroid Build Coastguard Worker } 114*795d594fSAndroid Build Coastguard Worker try { 115*795d594fSAndroid Build Coastguard Worker // Check for widening conversion 116*795d594fSAndroid Build Coastguard Worker int i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, (short) 3); 117*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 118*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 119*795d594fSAndroid Build Coastguard Worker assertEquals(4, field); 120*795d594fSAndroid Build Coastguard Worker } 121*795d594fSAndroid Build Coastguard Worker try { 122*795d594fSAndroid Build Coastguard Worker // Check for acceptance of void return type 123*795d594fSAndroid Build Coastguard Worker invokerMethodHandle.invokeExact(fieldVarHandle, this, 77); 124*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 125*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 126*795d594fSAndroid Build Coastguard Worker assertEquals(4, field); 127*795d594fSAndroid Build Coastguard Worker } 128*795d594fSAndroid Build Coastguard Worker try { 129*795d594fSAndroid Build Coastguard Worker // Check for wider return type 130*795d594fSAndroid Build Coastguard Worker long l = (long) invokerMethodHandle.invokeExact(fieldVarHandle, this, 77); 131*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 132*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 133*795d594fSAndroid Build Coastguard Worker assertEquals(4, field); 134*795d594fSAndroid Build Coastguard Worker } 135*795d594fSAndroid Build Coastguard Worker try { 136*795d594fSAndroid Build Coastguard Worker // Check null VarHandle instance fails 137*795d594fSAndroid Build Coastguard Worker VarHandle vhNull = null; 138*795d594fSAndroid Build Coastguard Worker int i = (int) invokerMethodHandle.invokeExact(vhNull, this, 777); 139*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 140*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException expected) { 141*795d594fSAndroid Build Coastguard Worker assertEquals(4, field); 142*795d594fSAndroid Build Coastguard Worker } 143*795d594fSAndroid Build Coastguard Worker 144*795d594fSAndroid Build Coastguard Worker // 145*795d594fSAndroid Build Coastguard Worker // Check invocations with MethodHandle.invoke() 146*795d594fSAndroid Build Coastguard Worker // 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker // Check for unboxing 149*795d594fSAndroid Build Coastguard Worker int i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, Integer.valueOf(3)); 150*795d594fSAndroid Build Coastguard Worker assertEquals(3, field); 151*795d594fSAndroid Build Coastguard Worker 152*795d594fSAndroid Build Coastguard Worker // Check for unboxing 153*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, Short.valueOf((short) 4)); 154*795d594fSAndroid Build Coastguard Worker assertEquals(4, field); 155*795d594fSAndroid Build Coastguard Worker 156*795d594fSAndroid Build Coastguard Worker // Check for widening conversion 157*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, (short) 23); 158*795d594fSAndroid Build Coastguard Worker assertEquals(23, field); 159*795d594fSAndroid Build Coastguard Worker 160*795d594fSAndroid Build Coastguard Worker // Check for acceptance of void return type 161*795d594fSAndroid Build Coastguard Worker invokerMethodHandle.invoke(fieldVarHandle, this, 77); 162*795d594fSAndroid Build Coastguard Worker assertEquals(77, field); 163*795d594fSAndroid Build Coastguard Worker 164*795d594fSAndroid Build Coastguard Worker // Check for wider return type 165*795d594fSAndroid Build Coastguard Worker long l = (long) invokerMethodHandle.invoke(fieldVarHandle, this, 88); 166*795d594fSAndroid Build Coastguard Worker assertEquals(88, field); 167*795d594fSAndroid Build Coastguard Worker 168*795d594fSAndroid Build Coastguard Worker try { 169*795d594fSAndroid Build Coastguard Worker // Check null VarHandle instance fails 170*795d594fSAndroid Build Coastguard Worker VarHandle vhNull = null; 171*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invoke(vhNull, this, 888); 172*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 173*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException expected) { 174*795d594fSAndroid Build Coastguard Worker assertEquals(88, field); 175*795d594fSAndroid Build Coastguard Worker } 176*795d594fSAndroid Build Coastguard Worker } 177*795d594fSAndroid Build Coastguard Worker } 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker static class LongFieldVarHandleExactInvokerTest { 180*795d594fSAndroid Build Coastguard Worker private static final Class<?> THIS_CLASS = LongFieldVarHandleExactInvokerTest.class; 181*795d594fSAndroid Build Coastguard Worker 182*795d594fSAndroid Build Coastguard Worker private static final VarHandle fieldVarHandle; 183*795d594fSAndroid Build Coastguard Worker 184*795d594fSAndroid Build Coastguard Worker private static final long CANARY = 0x0123456789abcdefL; 185*795d594fSAndroid Build Coastguard Worker 186*795d594fSAndroid Build Coastguard Worker long field = 0L; 187*795d594fSAndroid Build Coastguard Worker 188*795d594fSAndroid Build Coastguard Worker static { 189*795d594fSAndroid Build Coastguard Worker try { 190*795d594fSAndroid Build Coastguard Worker fieldVarHandle = lookup().findVarHandle(THIS_CLASS, "field", long.class); 191*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 192*795d594fSAndroid Build Coastguard Worker throw new TestSetupError("Failed to lookup of field", e); 193*795d594fSAndroid Build Coastguard Worker } 194*795d594fSAndroid Build Coastguard Worker } 195*795d594fSAndroid Build Coastguard Worker run()196*795d594fSAndroid Build Coastguard Worker void run() throws Throwable { 197*795d594fSAndroid Build Coastguard Worker System.out.println(THIS_CLASS.getName()); 198*795d594fSAndroid Build Coastguard Worker 199*795d594fSAndroid Build Coastguard Worker MethodHandle invokerMethodHandle = 200*795d594fSAndroid Build Coastguard Worker MethodHandles.varHandleExactInvoker( 201*795d594fSAndroid Build Coastguard Worker VarHandle.AccessMode.COMPARE_AND_SET, 202*795d594fSAndroid Build Coastguard Worker methodType(boolean.class, THIS_CLASS, long.class, long.class)); 203*795d594fSAndroid Build Coastguard Worker checkCompareAndSet(invokerMethodHandle, 0L, CANARY); 204*795d594fSAndroid Build Coastguard Worker checkCompareAndSet(invokerMethodHandle, 1L, 1L); 205*795d594fSAndroid Build Coastguard Worker checkCompareAndSet(invokerMethodHandle, CANARY, ~CANARY); 206*795d594fSAndroid Build Coastguard Worker checkCompareAndSet(invokerMethodHandle, ~CANARY, 0L); 207*795d594fSAndroid Build Coastguard Worker } 208*795d594fSAndroid Build Coastguard Worker checkCompareAndSet(MethodHandle compareAndSet, long oldValue, long newValue)209*795d594fSAndroid Build Coastguard Worker private void checkCompareAndSet(MethodHandle compareAndSet, long oldValue, long newValue) 210*795d594fSAndroid Build Coastguard Worker throws Throwable { 211*795d594fSAndroid Build Coastguard Worker final boolean expectSuccess = (oldValue == field); 212*795d594fSAndroid Build Coastguard Worker final long oldFieldValue = field; 213*795d594fSAndroid Build Coastguard Worker assertEquals( 214*795d594fSAndroid Build Coastguard Worker expectSuccess, 215*795d594fSAndroid Build Coastguard Worker (boolean) compareAndSet.invoke(fieldVarHandle, this, oldValue, newValue)); 216*795d594fSAndroid Build Coastguard Worker assertEquals(expectSuccess ? newValue : oldFieldValue, field); 217*795d594fSAndroid Build Coastguard Worker } 218*795d594fSAndroid Build Coastguard Worker } 219*795d594fSAndroid Build Coastguard Worker 220*795d594fSAndroid Build Coastguard Worker static class FieldVarHandleInvokerTest { 221*795d594fSAndroid Build Coastguard Worker private static final Class<?> THIS_CLASS = FieldVarHandleInvokerTest.class; 222*795d594fSAndroid Build Coastguard Worker private static final VarHandle fieldVarHandle; 223*795d594fSAndroid Build Coastguard Worker int field; 224*795d594fSAndroid Build Coastguard Worker 225*795d594fSAndroid Build Coastguard Worker static { 226*795d594fSAndroid Build Coastguard Worker try { 227*795d594fSAndroid Build Coastguard Worker fieldVarHandle = lookup().findVarHandle(THIS_CLASS, "field", int.class); 228*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 229*795d594fSAndroid Build Coastguard Worker throw new TestSetupError("Failed to lookup of field", e); 230*795d594fSAndroid Build Coastguard Worker } 231*795d594fSAndroid Build Coastguard Worker } 232*795d594fSAndroid Build Coastguard Worker run()233*795d594fSAndroid Build Coastguard Worker void run() throws Throwable { 234*795d594fSAndroid Build Coastguard Worker System.out.println("fieldVarHandleInvokerTest"); 235*795d594fSAndroid Build Coastguard Worker MethodHandle invokerMethodHandle = 236*795d594fSAndroid Build Coastguard Worker MethodHandles.varHandleInvoker( 237*795d594fSAndroid Build Coastguard Worker VarHandle.AccessMode.GET_AND_SET, 238*795d594fSAndroid Build Coastguard Worker methodType(int.class, THIS_CLASS, int.class)); 239*795d594fSAndroid Build Coastguard Worker 240*795d594fSAndroid Build Coastguard Worker field = 3; 241*795d594fSAndroid Build Coastguard Worker int oldField = (int) invokerMethodHandle.invoke(fieldVarHandle, this, 4); 242*795d594fSAndroid Build Coastguard Worker assertEquals(3, oldField); 243*795d594fSAndroid Build Coastguard Worker assertEquals(4, field); 244*795d594fSAndroid Build Coastguard Worker 245*795d594fSAndroid Build Coastguard Worker // 246*795d594fSAndroid Build Coastguard Worker // Check invocations with MethodHandle.invoke() 247*795d594fSAndroid Build Coastguard Worker // 248*795d594fSAndroid Build Coastguard Worker 249*795d594fSAndroid Build Coastguard Worker // Check for unboxing 250*795d594fSAndroid Build Coastguard Worker int i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, Integer.valueOf(3)); 251*795d594fSAndroid Build Coastguard Worker assertEquals(3, field); 252*795d594fSAndroid Build Coastguard Worker 253*795d594fSAndroid Build Coastguard Worker // Check for widening conversion 254*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, (short) 33); 255*795d594fSAndroid Build Coastguard Worker assertEquals(33, field); 256*795d594fSAndroid Build Coastguard Worker 257*795d594fSAndroid Build Coastguard Worker // Check for widening conversion 258*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, Byte.valueOf((byte) 34)); 259*795d594fSAndroid Build Coastguard Worker assertEquals(34, field); 260*795d594fSAndroid Build Coastguard Worker 261*795d594fSAndroid Build Coastguard Worker // Check for acceptance of void return type 262*795d594fSAndroid Build Coastguard Worker invokerMethodHandle.invoke(fieldVarHandle, this, 77); 263*795d594fSAndroid Build Coastguard Worker assertEquals(77, field); 264*795d594fSAndroid Build Coastguard Worker 265*795d594fSAndroid Build Coastguard Worker // Check for wider return type 266*795d594fSAndroid Build Coastguard Worker long l = (long) invokerMethodHandle.invoke(fieldVarHandle, this, 88); 267*795d594fSAndroid Build Coastguard Worker assertEquals(88, field); 268*795d594fSAndroid Build Coastguard Worker try { 269*795d594fSAndroid Build Coastguard Worker // Check narrowing conversion fails 270*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, 3.0); 271*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 272*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 273*795d594fSAndroid Build Coastguard Worker } 274*795d594fSAndroid Build Coastguard Worker try { 275*795d594fSAndroid Build Coastguard Worker // Check reference type fails 276*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, "Bad"); 277*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 278*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 279*795d594fSAndroid Build Coastguard Worker } 280*795d594fSAndroid Build Coastguard Worker try { 281*795d594fSAndroid Build Coastguard Worker // Check null VarHandle instance fails 282*795d594fSAndroid Build Coastguard Worker VarHandle vhNull = null; 283*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invoke(vhNull, this, 888); 284*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 285*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException expected) { 286*795d594fSAndroid Build Coastguard Worker assertEquals(88, field); 287*795d594fSAndroid Build Coastguard Worker } 288*795d594fSAndroid Build Coastguard Worker 289*795d594fSAndroid Build Coastguard Worker // 290*795d594fSAndroid Build Coastguard Worker // Check invocations with MethodHandle.invokeExact() 291*795d594fSAndroid Build Coastguard Worker // 292*795d594fSAndroid Build Coastguard Worker field = -1; 293*795d594fSAndroid Build Coastguard Worker try { 294*795d594fSAndroid Build Coastguard Worker // Check for unboxing 295*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, Integer.valueOf(3)); 296*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 297*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 298*795d594fSAndroid Build Coastguard Worker assertEquals(-1, field); 299*795d594fSAndroid Build Coastguard Worker } 300*795d594fSAndroid Build Coastguard Worker try { 301*795d594fSAndroid Build Coastguard Worker // Check for widening conversion 302*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, (short) 33); 303*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 304*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 305*795d594fSAndroid Build Coastguard Worker assertEquals(-1, field); 306*795d594fSAndroid Build Coastguard Worker } 307*795d594fSAndroid Build Coastguard Worker try { 308*795d594fSAndroid Build Coastguard Worker // Check for acceptance of void return type 309*795d594fSAndroid Build Coastguard Worker invokerMethodHandle.invokeExact(fieldVarHandle, this, 77); 310*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 311*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 312*795d594fSAndroid Build Coastguard Worker assertEquals(-1, field); 313*795d594fSAndroid Build Coastguard Worker } 314*795d594fSAndroid Build Coastguard Worker try { 315*795d594fSAndroid Build Coastguard Worker // Check for wider return type 316*795d594fSAndroid Build Coastguard Worker l = (long) invokerMethodHandle.invokeExact(fieldVarHandle, this, 78); 317*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 318*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 319*795d594fSAndroid Build Coastguard Worker assertEquals(-1, field); 320*795d594fSAndroid Build Coastguard Worker } 321*795d594fSAndroid Build Coastguard Worker try { 322*795d594fSAndroid Build Coastguard Worker // Check narrowing conversion fails 323*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, 3.0); 324*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 325*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 326*795d594fSAndroid Build Coastguard Worker } 327*795d594fSAndroid Build Coastguard Worker try { 328*795d594fSAndroid Build Coastguard Worker // Check reference type fails 329*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, "Bad"); 330*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 331*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 332*795d594fSAndroid Build Coastguard Worker } 333*795d594fSAndroid Build Coastguard Worker try { 334*795d594fSAndroid Build Coastguard Worker // Check null VarHandle instance fails 335*795d594fSAndroid Build Coastguard Worker VarHandle vhNull = null; 336*795d594fSAndroid Build Coastguard Worker i = (int) invokerMethodHandle.invokeExact(vhNull, this, 888); 337*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 338*795d594fSAndroid Build Coastguard Worker } catch (NullPointerException expected) { 339*795d594fSAndroid Build Coastguard Worker assertEquals(-1, field); 340*795d594fSAndroid Build Coastguard Worker } 341*795d594fSAndroid Build Coastguard Worker } 342*795d594fSAndroid Build Coastguard Worker } 343*795d594fSAndroid Build Coastguard Worker 344*795d594fSAndroid Build Coastguard Worker static class DivergenceExactInvokerTest { 345*795d594fSAndroid Build Coastguard Worker private static final VarHandle floatsArrayVarHandle; 346*795d594fSAndroid Build Coastguard Worker 347*795d594fSAndroid Build Coastguard Worker static { 348*795d594fSAndroid Build Coastguard Worker try { 349*795d594fSAndroid Build Coastguard Worker floatsArrayVarHandle = MethodHandles.arrayElementVarHandle(float[].class); 350*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 351*795d594fSAndroid Build Coastguard Worker throw new TestSetupError("Failed to create VarHandle", e); 352*795d594fSAndroid Build Coastguard Worker } 353*795d594fSAndroid Build Coastguard Worker } 354*795d594fSAndroid Build Coastguard Worker run()355*795d594fSAndroid Build Coastguard Worker void run() throws Throwable { 356*795d594fSAndroid Build Coastguard Worker System.out.println("DivergenceExactInvokerTest"); 357*795d594fSAndroid Build Coastguard Worker float[] floatsArray = new float[4]; 358*795d594fSAndroid Build Coastguard Worker // Exact invoker of an accessor having the form: 359*795d594fSAndroid Build Coastguard Worker // float accessor(float[] values, int index, Float current, float replacement) 360*795d594fSAndroid Build Coastguard Worker MethodHandle exactInvoker = 361*795d594fSAndroid Build Coastguard Worker MethodHandles.varHandleExactInvoker( 362*795d594fSAndroid Build Coastguard Worker VarHandle.AccessMode.COMPARE_AND_EXCHANGE, 363*795d594fSAndroid Build Coastguard Worker methodType( 364*795d594fSAndroid Build Coastguard Worker float.class, 365*795d594fSAndroid Build Coastguard Worker float[].class, 366*795d594fSAndroid Build Coastguard Worker int.class, 367*795d594fSAndroid Build Coastguard Worker Float.class, 368*795d594fSAndroid Build Coastguard Worker float.class)); 369*795d594fSAndroid Build Coastguard Worker floatsArray[2] = Float.valueOf(4.0f); 370*795d594fSAndroid Build Coastguard Worker // Callsite that is an exact match with exactInvoker.type(). 371*795d594fSAndroid Build Coastguard Worker try { 372*795d594fSAndroid Build Coastguard Worker // exactInvoker.type() is not compatible with floatsArrayVarHandle accessor. 373*795d594fSAndroid Build Coastguard Worker float old = 374*795d594fSAndroid Build Coastguard Worker (float) 375*795d594fSAndroid Build Coastguard Worker exactInvoker.invoke( 376*795d594fSAndroid Build Coastguard Worker floatsArrayVarHandle, 377*795d594fSAndroid Build Coastguard Worker floatsArray, 378*795d594fSAndroid Build Coastguard Worker 2, 379*795d594fSAndroid Build Coastguard Worker Float.valueOf(4.0f), 380*795d594fSAndroid Build Coastguard Worker 8.0f); 381*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 382*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 383*795d594fSAndroid Build Coastguard Worker assertEquals(4.0f, floatsArray[2]); 384*795d594fSAndroid Build Coastguard Worker } 385*795d594fSAndroid Build Coastguard Worker 386*795d594fSAndroid Build Coastguard Worker // Callsites that are exact matches with exactInvoker.type() 387*795d594fSAndroid Build Coastguard Worker try { 388*795d594fSAndroid Build Coastguard Worker // Mismatch between exactInvoker.type() and VarHandle type (Float != float) 389*795d594fSAndroid Build Coastguard Worker float old = 390*795d594fSAndroid Build Coastguard Worker (float) 391*795d594fSAndroid Build Coastguard Worker exactInvoker.invoke( 392*795d594fSAndroid Build Coastguard Worker floatsArrayVarHandle, floatsArray, 2, 8.0f, 16.0f); 393*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 394*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 395*795d594fSAndroid Build Coastguard Worker assertEquals(4.0f, floatsArray[2]); 396*795d594fSAndroid Build Coastguard Worker } 397*795d594fSAndroid Build Coastguard Worker try { 398*795d594fSAndroid Build Coastguard Worker // short not convertible to Float 399*795d594fSAndroid Build Coastguard Worker float old = 400*795d594fSAndroid Build Coastguard Worker (float) 401*795d594fSAndroid Build Coastguard Worker exactInvoker.invoke( 402*795d594fSAndroid Build Coastguard Worker floatsArrayVarHandle, floatsArray, 2, (short) 4, 13.0f); 403*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 404*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 405*795d594fSAndroid Build Coastguard Worker assertEquals(4.0f, floatsArray[2]); 406*795d594fSAndroid Build Coastguard Worker } 407*795d594fSAndroid Build Coastguard Worker try { 408*795d594fSAndroid Build Coastguard Worker // int not convertible to Float 409*795d594fSAndroid Build Coastguard Worker float old = 410*795d594fSAndroid Build Coastguard Worker (float) exactInvoker.invoke(floatsArrayVarHandle, floatsArray, 2, 8, -8.0f); 411*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 412*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 413*795d594fSAndroid Build Coastguard Worker assertEquals(4.0f, floatsArray[2]); 414*795d594fSAndroid Build Coastguard Worker } 415*795d594fSAndroid Build Coastguard Worker } 416*795d594fSAndroid Build Coastguard Worker } 417*795d594fSAndroid Build Coastguard Worker 418*795d594fSAndroid Build Coastguard Worker static class DivergenceInvokerTest { 419*795d594fSAndroid Build Coastguard Worker private static final VarHandle floatsArrayVarHandle; 420*795d594fSAndroid Build Coastguard Worker 421*795d594fSAndroid Build Coastguard Worker static { 422*795d594fSAndroid Build Coastguard Worker try { 423*795d594fSAndroid Build Coastguard Worker floatsArrayVarHandle = MethodHandles.arrayElementVarHandle(float[].class); 424*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 425*795d594fSAndroid Build Coastguard Worker throw new TestSetupError("Failed to create VarHandle", e); 426*795d594fSAndroid Build Coastguard Worker } 427*795d594fSAndroid Build Coastguard Worker } 428*795d594fSAndroid Build Coastguard Worker run()429*795d594fSAndroid Build Coastguard Worker void run() throws Throwable { 430*795d594fSAndroid Build Coastguard Worker System.out.println("DivergenceInvokerTest"); 431*795d594fSAndroid Build Coastguard Worker float[] floatsArray = new float[4]; 432*795d594fSAndroid Build Coastguard Worker // Invoker of an accessor having the form: 433*795d594fSAndroid Build Coastguard Worker // float accessor(float[] values, int index, Float current, float replacement) 434*795d594fSAndroid Build Coastguard Worker MethodHandle invoker = 435*795d594fSAndroid Build Coastguard Worker MethodHandles.varHandleInvoker( 436*795d594fSAndroid Build Coastguard Worker VarHandle.AccessMode.COMPARE_AND_EXCHANGE, 437*795d594fSAndroid Build Coastguard Worker methodType( 438*795d594fSAndroid Build Coastguard Worker float.class, 439*795d594fSAndroid Build Coastguard Worker float[].class, 440*795d594fSAndroid Build Coastguard Worker int.class, 441*795d594fSAndroid Build Coastguard Worker Float.class, 442*795d594fSAndroid Build Coastguard Worker float.class)); 443*795d594fSAndroid Build Coastguard Worker floatsArray[2] = Float.valueOf(4.0f); 444*795d594fSAndroid Build Coastguard Worker // Callsite that is an exact match with invoker.type() 445*795d594fSAndroid Build Coastguard Worker float old = 446*795d594fSAndroid Build Coastguard Worker (float) 447*795d594fSAndroid Build Coastguard Worker invoker.invoke( 448*795d594fSAndroid Build Coastguard Worker floatsArrayVarHandle, 449*795d594fSAndroid Build Coastguard Worker floatsArray, 450*795d594fSAndroid Build Coastguard Worker 2, 451*795d594fSAndroid Build Coastguard Worker Float.valueOf(4.0f), 452*795d594fSAndroid Build Coastguard Worker 8.0f); 453*795d594fSAndroid Build Coastguard Worker assertEquals(4.0f, old); 454*795d594fSAndroid Build Coastguard Worker assertEquals(8.0f, floatsArray[2]); 455*795d594fSAndroid Build Coastguard Worker 456*795d594fSAndroid Build Coastguard Worker // Callsite that is convertible match to invoker.type() 457*795d594fSAndroid Build Coastguard Worker old = (float) invoker.invoke(floatsArrayVarHandle, floatsArray, 2, 8.0f, 16.0f); 458*795d594fSAndroid Build Coastguard Worker assertEquals(8.0f, old); 459*795d594fSAndroid Build Coastguard Worker assertEquals(16.0f, floatsArray[2]); 460*795d594fSAndroid Build Coastguard Worker 461*795d594fSAndroid Build Coastguard Worker // Callsites that are not convertible to invoker.type(). 462*795d594fSAndroid Build Coastguard Worker try { 463*795d594fSAndroid Build Coastguard Worker // short is not convertible to Float 464*795d594fSAndroid Build Coastguard Worker old = (float) invoker.invoke(floatsArrayVarHandle, floatsArray, 2, (short) 4, 8.0f); 465*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 466*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 467*795d594fSAndroid Build Coastguard Worker assertEquals(16.0f, floatsArray[2]); 468*795d594fSAndroid Build Coastguard Worker } 469*795d594fSAndroid Build Coastguard Worker try { 470*795d594fSAndroid Build Coastguard Worker // int is not convertible to Float 471*795d594fSAndroid Build Coastguard Worker old = (float) invoker.invoke(floatsArrayVarHandle, floatsArray, 2, 8, -8.0f); 472*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 473*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 474*795d594fSAndroid Build Coastguard Worker assertEquals(16.0f, floatsArray[2]); 475*795d594fSAndroid Build Coastguard Worker } 476*795d594fSAndroid Build Coastguard Worker 477*795d594fSAndroid Build Coastguard Worker try { 478*795d594fSAndroid Build Coastguard Worker MethodHandle unsupportedInvoker = 479*795d594fSAndroid Build Coastguard Worker MethodHandles.varHandleInvoker( 480*795d594fSAndroid Build Coastguard Worker VarHandle.AccessMode.GET_AND_BITWISE_OR, 481*795d594fSAndroid Build Coastguard Worker methodType(float.class, float[].class, int.class, float.class)); 482*795d594fSAndroid Build Coastguard Worker old = 483*795d594fSAndroid Build Coastguard Worker (float) 484*795d594fSAndroid Build Coastguard Worker unsupportedInvoker.invoke( 485*795d594fSAndroid Build Coastguard Worker floatsArrayVarHandle, floatsArray, 0, 2.71f); 486*795d594fSAndroid Build Coastguard Worker assertUnreachable(); 487*795d594fSAndroid Build Coastguard Worker } catch (UnsupportedOperationException expected) { 488*795d594fSAndroid Build Coastguard Worker } 489*795d594fSAndroid Build Coastguard Worker } 490*795d594fSAndroid Build Coastguard Worker } 491*795d594fSAndroid Build Coastguard Worker main(String[] args)492*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Throwable { 493*795d594fSAndroid Build Coastguard Worker new FieldVarHandleExactInvokerTest().run(); 494*795d594fSAndroid Build Coastguard Worker new LongFieldVarHandleExactInvokerTest().run(); 495*795d594fSAndroid Build Coastguard Worker new FieldVarHandleInvokerTest().run(); 496*795d594fSAndroid Build Coastguard Worker new DivergenceExactInvokerTest().run(); 497*795d594fSAndroid Build Coastguard Worker new DivergenceInvokerTest().run(); 498*795d594fSAndroid Build Coastguard Worker } 499*795d594fSAndroid Build Coastguard Worker } 500