Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 import annotations.BootstrapMethod;
     18 import annotations.CalledByIndy;
     19 import java.lang.invoke.CallSite;
     20 import java.lang.invoke.ConstantCallSite;
     21 import java.lang.invoke.MethodHandle;
     22 import java.lang.invoke.MethodHandles;
     23 import java.lang.invoke.MethodType;
     24 
     25 class TestReturnValues extends TestBase {
     26     static CallSite bsm(MethodHandles.Lookup lookup, String name, MethodType methodType)
     27             throws Throwable {
     28         MethodHandle mh = lookup.findStatic(TestReturnValues.class, name, methodType);
     29         return new ConstantCallSite(mh);
     30     }
     31 
     32     //
     33     // Methods that pass through a single argument.
     34     // Used to check return path.
     35     //
     36     static byte passThrough(byte value) {
     37         return value;
     38     }
     39 
     40     static char passThrough(char value) {
     41         return value;
     42     }
     43 
     44     static double passThrough(double value) {
     45         return value;
     46     }
     47 
     48     static float passThrough(float value) {
     49         return value;
     50     }
     51 
     52     static int passThrough(int value) {
     53         return value;
     54     }
     55 
     56     static Object passThrough(Object value) {
     57         return value;
     58     }
     59 
     60     static Object[] passThrough(Object[] value) {
     61         return value;
     62     }
     63 
     64     static long passThrough(long value) {
     65         return value;
     66     }
     67 
     68     static short passThrough(short value) {
     69         return value;
     70     }
     71 
     72     static void passThrough() {}
     73 
     74     static boolean passThrough(boolean value) {
     75         return value;
     76     }
     77 
     78     // byte
     79     @CalledByIndy(
     80             bootstrapMethod =
     81                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
     82             fieldOrMethodName = "passThrough",
     83             returnType = byte.class,
     84             parameterTypes = {byte.class})
     85     private static byte passThroughCallSite(byte value) {
     86         assertNotReached();
     87         return (byte) 0;
     88     }
     89 
     90     // char
     91     @CalledByIndy(
     92             bootstrapMethod =
     93                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
     94             fieldOrMethodName = "passThrough",
     95             returnType = char.class,
     96             parameterTypes = {char.class})
     97     private static char passThroughCallSite(char value) {
     98         assertNotReached();
     99         return 'Z';
    100     }
    101 
    102     // double
    103     @CalledByIndy(
    104             bootstrapMethod =
    105                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    106             fieldOrMethodName = "passThrough",
    107             returnType = double.class,
    108             parameterTypes = {double.class})
    109     private static double passThroughCallSite(double value) {
    110         assertNotReached();
    111         return Double.NaN;
    112     }
    113 
    114     // float
    115     @CalledByIndy(
    116             bootstrapMethod =
    117                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    118             fieldOrMethodName = "passThrough",
    119             returnType = float.class,
    120             parameterTypes = {float.class})
    121     private static float passThroughCallSite(float value) {
    122         assertNotReached();
    123         return Float.NaN;
    124     }
    125 
    126     // int
    127     @CalledByIndy(
    128             bootstrapMethod =
    129                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    130             fieldOrMethodName = "passThrough",
    131             returnType = int.class,
    132             parameterTypes = {int.class})
    133     private static int passThroughCallSite(int value) {
    134         assertNotReached();
    135         return 0;
    136     }
    137 
    138     // long
    139     @CalledByIndy(
    140             bootstrapMethod =
    141                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    142             fieldOrMethodName = "passThrough",
    143             returnType = long.class,
    144             parameterTypes = {long.class})
    145     private static long passThroughCallSite(long value) {
    146         assertNotReached();
    147         return Long.MIN_VALUE;
    148     }
    149 
    150     // Object
    151     @CalledByIndy(
    152             bootstrapMethod =
    153                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    154             fieldOrMethodName = "passThrough",
    155             returnType = Object.class,
    156             parameterTypes = {Object.class})
    157     private static Object passThroughCallSite(Object value) {
    158         assertNotReached();
    159         return null;
    160     }
    161 
    162     // Object[]
    163     @CalledByIndy(
    164             bootstrapMethod =
    165                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    166             fieldOrMethodName = "passThrough",
    167             returnType = Object[].class,
    168             parameterTypes = {Object[].class})
    169     private static Object[] passThroughCallSite(Object[] value) {
    170         assertNotReached();
    171         return null;
    172     }
    173 
    174     // short
    175     @CalledByIndy(
    176             bootstrapMethod =
    177                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    178             fieldOrMethodName = "passThrough",
    179             returnType = short.class,
    180             parameterTypes = {short.class})
    181     private static short passThroughCallSite(short value) {
    182         assertNotReached();
    183         return (short) 0;
    184     }
    185 
    186     // void
    187     @CalledByIndy(
    188             bootstrapMethod =
    189                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    190             fieldOrMethodName = "passThrough",
    191             returnType = void.class,
    192             parameterTypes = {})
    193     private static void passThroughCallSite() {
    194         assertNotReached();
    195     }
    196 
    197     // boolean
    198     @CalledByIndy(
    199             bootstrapMethod =
    200                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
    201             fieldOrMethodName = "passThrough",
    202             returnType = boolean.class,
    203             parameterTypes = {boolean.class})
    204     private static boolean passThroughCallSite(boolean value) {
    205         assertNotReached();
    206         return false;
    207     }
    208 
    209     private static void testByteReturnValues() {
    210         byte[] values = {Byte.MIN_VALUE, Byte.MAX_VALUE};
    211         for (byte value : values) {
    212             assertEquals(value, (byte) passThroughCallSite(value));
    213         }
    214     }
    215 
    216     private static void testCharReturnValues() {
    217         char[] values = {
    218             Character.MIN_VALUE,
    219             Character.MAX_HIGH_SURROGATE,
    220             Character.MAX_LOW_SURROGATE,
    221             Character.MAX_VALUE
    222         };
    223         for (char value : values) {
    224             assertEquals(value, (char) passThroughCallSite(value));
    225         }
    226     }
    227 
    228     private static void testDoubleReturnValues() {
    229         double[] values = {
    230             Double.MIN_VALUE,
    231             Double.MIN_NORMAL,
    232             Double.NaN,
    233             Double.POSITIVE_INFINITY,
    234             Double.NEGATIVE_INFINITY,
    235             Double.MAX_VALUE
    236         };
    237         for (double value : values) {
    238             assertEquals(value, (double) passThroughCallSite(value));
    239         }
    240     }
    241 
    242     private static void testFloatReturnValues() {
    243         float[] values = {
    244             Float.MIN_VALUE,
    245             Float.MIN_NORMAL,
    246             Float.NaN,
    247             Float.POSITIVE_INFINITY,
    248             Float.NEGATIVE_INFINITY,
    249             Float.MAX_VALUE
    250         };
    251         for (float value : values) {
    252             assertEquals(value, (float) passThroughCallSite(value));
    253         }
    254     }
    255 
    256     private static void testIntReturnValues() {
    257         int[] values = {Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.SIZE, -Integer.SIZE};
    258         for (int value : values) {
    259             assertEquals(value, (int) passThroughCallSite(value));
    260         }
    261     }
    262 
    263     private static void testLongReturnValues() {
    264         long[] values = {Long.MIN_VALUE, Long.MAX_VALUE, (long) Long.SIZE, (long) -Long.SIZE};
    265         for (long value : values) {
    266             assertEquals(value, (long) passThroughCallSite(value));
    267         }
    268     }
    269 
    270     private static void testObjectReturnValues() {
    271         Object[] values = {null, "abc", Integer.valueOf(123)};
    272         for (Object value : values) {
    273             assertEquals(value, (Object) passThroughCallSite(value));
    274         }
    275 
    276         Object[] otherValues = (Object[]) passThroughCallSite(values);
    277         assertEquals(values.length, otherValues.length);
    278         for (int i = 0; i < otherValues.length; ++i) {
    279             assertEquals(values[i], otherValues[i]);
    280         }
    281     }
    282 
    283     private static void testShortReturnValues() {
    284         short[] values = {
    285             Short.MIN_VALUE, Short.MAX_VALUE, (short) Short.SIZE, (short) -Short.SIZE
    286         };
    287         for (short value : values) {
    288             assertEquals(value, (short) passThroughCallSite(value));
    289         }
    290     }
    291 
    292     private static void testVoidReturnValues() {
    293         long l = Long.MIN_VALUE;
    294         double d = Double.MIN_VALUE;
    295         passThroughCallSite(); // Initializes call site
    296         assertEquals(Long.MIN_VALUE, l);
    297         assertEquals(Double.MIN_VALUE, d);
    298 
    299         l = Long.MAX_VALUE;
    300         d = Double.MAX_VALUE;
    301         passThroughCallSite(); // re-uses existing call site
    302         assertEquals(Long.MAX_VALUE, l);
    303         assertEquals(Double.MAX_VALUE, d);
    304     }
    305 
    306     private static void testBooleanReturnValues() {
    307         boolean[] values = {true, false, true, false, false};
    308         for (boolean value : values) {
    309             assertEquals(value, (boolean) passThroughCallSite(value));
    310         }
    311     }
    312 
    313     public static void test() {
    314         System.out.println(TestReturnValues.class.getName());
    315         // Two passes here - the first is for the call site creation and invoke path, the second
    316         // for the lookup and invoke path.
    317         for (int pass = 0; pass < 2; ++pass) {
    318             testByteReturnValues(); // B
    319             testCharReturnValues(); // C
    320             testDoubleReturnValues(); // D
    321             testFloatReturnValues(); // F
    322             testIntReturnValues(); // I
    323             testLongReturnValues(); // J
    324             testObjectReturnValues(); // L
    325             testShortReturnValues(); // S
    326             testVoidReturnValues(); // S
    327             testBooleanReturnValues(); // Z
    328         }
    329     }
    330 }
    331