1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 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 java.lang.invoke.MethodHandle; 18*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandles; 19*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandles.Lookup; 20*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodType; 21*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.WrongMethodTypeException; 22*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.Transformers.Transformer; 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker import dalvik.system.EmulatedStackFrame; 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker public class Main { 27*795d594fSAndroid Build Coastguard Worker testDelegate_allTypes(boolean z, char a, short b, int c, long d, float e, double f, String g, Object h)28*795d594fSAndroid Build Coastguard Worker public static void testDelegate_allTypes(boolean z, char a, short b, int c, long d, 29*795d594fSAndroid Build Coastguard Worker float e, double f, String g, Object h) { 30*795d594fSAndroid Build Coastguard Worker System.out.println("boolean: " + z); 31*795d594fSAndroid Build Coastguard Worker System.out.println("char: " + a); 32*795d594fSAndroid Build Coastguard Worker System.out.println("short: " + b); 33*795d594fSAndroid Build Coastguard Worker System.out.println("int: " + c); 34*795d594fSAndroid Build Coastguard Worker System.out.println("long: " + d); 35*795d594fSAndroid Build Coastguard Worker System.out.println("float: " + e); 36*795d594fSAndroid Build Coastguard Worker System.out.println("double: " + f); 37*795d594fSAndroid Build Coastguard Worker System.out.println("String: " + g); 38*795d594fSAndroid Build Coastguard Worker System.out.println("Object: " + h); 39*795d594fSAndroid Build Coastguard Worker } 40*795d594fSAndroid Build Coastguard Worker testDelegate_returnBoolean()41*795d594fSAndroid Build Coastguard Worker public static boolean testDelegate_returnBoolean() { 42*795d594fSAndroid Build Coastguard Worker return true; 43*795d594fSAndroid Build Coastguard Worker } 44*795d594fSAndroid Build Coastguard Worker testDelegate_returnChar()45*795d594fSAndroid Build Coastguard Worker public static char testDelegate_returnChar() { 46*795d594fSAndroid Build Coastguard Worker return 'a'; 47*795d594fSAndroid Build Coastguard Worker } 48*795d594fSAndroid Build Coastguard Worker testDelegate_returnInt()49*795d594fSAndroid Build Coastguard Worker public static int testDelegate_returnInt() { 50*795d594fSAndroid Build Coastguard Worker return 42; 51*795d594fSAndroid Build Coastguard Worker } 52*795d594fSAndroid Build Coastguard Worker testDelegate_returnLong()53*795d594fSAndroid Build Coastguard Worker public static long testDelegate_returnLong() { 54*795d594fSAndroid Build Coastguard Worker return 43; 55*795d594fSAndroid Build Coastguard Worker } 56*795d594fSAndroid Build Coastguard Worker testDelegate_returnFloat()57*795d594fSAndroid Build Coastguard Worker public static float testDelegate_returnFloat() { 58*795d594fSAndroid Build Coastguard Worker return 43.0f; 59*795d594fSAndroid Build Coastguard Worker } 60*795d594fSAndroid Build Coastguard Worker testDelegate_returnDouble()61*795d594fSAndroid Build Coastguard Worker public static double testDelegate_returnDouble() { 62*795d594fSAndroid Build Coastguard Worker return 43.0; 63*795d594fSAndroid Build Coastguard Worker } 64*795d594fSAndroid Build Coastguard Worker testDelegate_returnString()65*795d594fSAndroid Build Coastguard Worker public static String testDelegate_returnString() { 66*795d594fSAndroid Build Coastguard Worker return "plank"; 67*795d594fSAndroid Build Coastguard Worker } 68*795d594fSAndroid Build Coastguard Worker 69*795d594fSAndroid Build Coastguard Worker public static class DelegatingTransformer extends Transformer { 70*795d594fSAndroid Build Coastguard Worker private final MethodHandle delegate; 71*795d594fSAndroid Build Coastguard Worker DelegatingTransformer(MethodHandle delegate)72*795d594fSAndroid Build Coastguard Worker public DelegatingTransformer(MethodHandle delegate) { 73*795d594fSAndroid Build Coastguard Worker super(delegate.type()); 74*795d594fSAndroid Build Coastguard Worker this.delegate = delegate; 75*795d594fSAndroid Build Coastguard Worker } 76*795d594fSAndroid Build Coastguard Worker 77*795d594fSAndroid Build Coastguard Worker @Override transform(EmulatedStackFrame stackFrame)78*795d594fSAndroid Build Coastguard Worker public void transform(EmulatedStackFrame stackFrame) throws Throwable { 79*795d594fSAndroid Build Coastguard Worker invokeFromTransform(delegate, stackFrame); 80*795d594fSAndroid Build Coastguard Worker } 81*795d594fSAndroid Build Coastguard Worker } 82*795d594fSAndroid Build Coastguard Worker main(String[] args)83*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Throwable { 84*795d594fSAndroid Build Coastguard Worker MethodHandle specialFunctionHandle = MethodHandles.lookup().findStatic( 85*795d594fSAndroid Build Coastguard Worker Main.class, "testDelegate_allTypes", MethodType.methodType(void.class, 86*795d594fSAndroid Build Coastguard Worker new Class<?>[] { boolean.class, char.class, short.class, int.class, long.class, 87*795d594fSAndroid Build Coastguard Worker float.class, double.class, String.class, Object.class })); 88*795d594fSAndroid Build Coastguard Worker 89*795d594fSAndroid Build Coastguard Worker MethodHandle delegate = new DelegatingTransformer(specialFunctionHandle); 90*795d594fSAndroid Build Coastguard Worker 91*795d594fSAndroid Build Coastguard Worker // Test an exact invoke. 92*795d594fSAndroid Build Coastguard Worker // 93*795d594fSAndroid Build Coastguard Worker // Note that the shorter form below doesn't work and must be 94*795d594fSAndroid Build Coastguard Worker // investigated on the jack side : b/32536744 95*795d594fSAndroid Build Coastguard Worker // 96*795d594fSAndroid Build Coastguard Worker // delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l, 97*795d594fSAndroid Build Coastguard Worker // 0.56f, 100.0d, "hello", (Object) "goodbye"); 98*795d594fSAndroid Build Coastguard Worker 99*795d594fSAndroid Build Coastguard Worker Object obj = "goodbye"; 100*795d594fSAndroid Build Coastguard Worker delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l, 101*795d594fSAndroid Build Coastguard Worker 0.56f, 100.0d, "hello", obj); 102*795d594fSAndroid Build Coastguard Worker 103*795d594fSAndroid Build Coastguard Worker // Test a non exact invoke with one int -> long conversion and a float -> double 104*795d594fSAndroid Build Coastguard Worker // conversion. 105*795d594fSAndroid Build Coastguard Worker delegate.invoke(false, 'h', (short) 56, 72, 73, 106*795d594fSAndroid Build Coastguard Worker 0.56f, 100.0f, "hello", "goodbye"); 107*795d594fSAndroid Build Coastguard Worker 108*795d594fSAndroid Build Coastguard Worker // Should throw a WrongMethodTypeException if the types don't align. 109*795d594fSAndroid Build Coastguard Worker try { 110*795d594fSAndroid Build Coastguard Worker delegate.invoke(false); 111*795d594fSAndroid Build Coastguard Worker throw new AssertionError("Call to invoke unexpectedly succeeded"); 112*795d594fSAndroid Build Coastguard Worker } catch (WrongMethodTypeException expected) { 113*795d594fSAndroid Build Coastguard Worker } 114*795d594fSAndroid Build Coastguard Worker 115*795d594fSAndroid Build Coastguard Worker // Test return values. 116*795d594fSAndroid Build Coastguard Worker 117*795d594fSAndroid Build Coastguard Worker // boolean. 118*795d594fSAndroid Build Coastguard Worker MethodHandle returner = MethodHandles.lookup().findStatic( 119*795d594fSAndroid Build Coastguard Worker Main.class, "testDelegate_returnBoolean", MethodType.methodType(boolean.class)); 120*795d594fSAndroid Build Coastguard Worker delegate = new DelegatingTransformer(returner); 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker System.out.println((boolean) delegate.invoke()); 123*795d594fSAndroid Build Coastguard Worker System.out.println((boolean) delegate.invokeExact()); 124*795d594fSAndroid Build Coastguard Worker 125*795d594fSAndroid Build Coastguard Worker // char. 126*795d594fSAndroid Build Coastguard Worker returner = MethodHandles.lookup().findStatic( 127*795d594fSAndroid Build Coastguard Worker Main.class, "testDelegate_returnChar", MethodType.methodType(char.class)); 128*795d594fSAndroid Build Coastguard Worker delegate = new DelegatingTransformer(returner); 129*795d594fSAndroid Build Coastguard Worker 130*795d594fSAndroid Build Coastguard Worker System.out.println((char) delegate.invoke()); 131*795d594fSAndroid Build Coastguard Worker System.out.println((char) delegate.invokeExact()); 132*795d594fSAndroid Build Coastguard Worker 133*795d594fSAndroid Build Coastguard Worker // int. 134*795d594fSAndroid Build Coastguard Worker returner = MethodHandles.lookup().findStatic( 135*795d594fSAndroid Build Coastguard Worker Main.class, "testDelegate_returnInt", MethodType.methodType(int.class)); 136*795d594fSAndroid Build Coastguard Worker delegate = new DelegatingTransformer(returner); 137*795d594fSAndroid Build Coastguard Worker 138*795d594fSAndroid Build Coastguard Worker System.out.println((int) delegate.invoke()); 139*795d594fSAndroid Build Coastguard Worker System.out.println((int) delegate.invokeExact()); 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker // long. 142*795d594fSAndroid Build Coastguard Worker returner = MethodHandles.lookup().findStatic( 143*795d594fSAndroid Build Coastguard Worker Main.class, "testDelegate_returnLong", MethodType.methodType(long.class)); 144*795d594fSAndroid Build Coastguard Worker delegate = new DelegatingTransformer(returner); 145*795d594fSAndroid Build Coastguard Worker 146*795d594fSAndroid Build Coastguard Worker System.out.println((long) delegate.invoke()); 147*795d594fSAndroid Build Coastguard Worker System.out.println((long) delegate.invokeExact()); 148*795d594fSAndroid Build Coastguard Worker 149*795d594fSAndroid Build Coastguard Worker // float. 150*795d594fSAndroid Build Coastguard Worker returner = MethodHandles.lookup().findStatic( 151*795d594fSAndroid Build Coastguard Worker Main.class, "testDelegate_returnFloat", MethodType.methodType(float.class)); 152*795d594fSAndroid Build Coastguard Worker delegate = new DelegatingTransformer(returner); 153*795d594fSAndroid Build Coastguard Worker 154*795d594fSAndroid Build Coastguard Worker System.out.println((float) delegate.invoke()); 155*795d594fSAndroid Build Coastguard Worker System.out.println((float) delegate.invokeExact()); 156*795d594fSAndroid Build Coastguard Worker 157*795d594fSAndroid Build Coastguard Worker // double. 158*795d594fSAndroid Build Coastguard Worker returner = MethodHandles.lookup().findStatic( 159*795d594fSAndroid Build Coastguard Worker Main.class, "testDelegate_returnDouble", MethodType.methodType(double.class)); 160*795d594fSAndroid Build Coastguard Worker delegate = new DelegatingTransformer(returner); 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker System.out.println((double) delegate.invoke()); 163*795d594fSAndroid Build Coastguard Worker System.out.println((double) delegate.invokeExact()); 164*795d594fSAndroid Build Coastguard Worker 165*795d594fSAndroid Build Coastguard Worker // references. 166*795d594fSAndroid Build Coastguard Worker returner = MethodHandles.lookup().findStatic( 167*795d594fSAndroid Build Coastguard Worker Main.class, "testDelegate_returnString", MethodType.methodType(String.class)); 168*795d594fSAndroid Build Coastguard Worker delegate = new DelegatingTransformer(returner); 169*795d594fSAndroid Build Coastguard Worker 170*795d594fSAndroid Build Coastguard Worker System.out.println((String) delegate.invoke()); 171*795d594fSAndroid Build Coastguard Worker System.out.println((String) delegate.invokeExact()); 172*795d594fSAndroid Build Coastguard Worker } 173*795d594fSAndroid Build Coastguard Worker } 174*795d594fSAndroid Build Coastguard Worker 175*795d594fSAndroid Build Coastguard Worker 176