1 /*
   2  * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @summary smoke tests for CallSite
  27  * @library /lib/testlibrary/bytecode /java/lang/invoke/common
  28  * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
  29  * @run main test.java.lang.invoke.CallSiteTest
  30  */
  31 
  32 package test.java.lang.invoke;
  33 
  34 import java.lang.invoke.CallSite;
  35 import java.lang.invoke.MethodHandle;
  36 import java.lang.invoke.MethodHandles;
  37 import java.lang.invoke.MethodType;
  38 import java.lang.invoke.MutableCallSite;
  39 import java.lang.invoke.VolatileCallSite;
  40 
  41 import static java.lang.invoke.MethodHandles.Lookup;
  42 import static java.lang.invoke.MethodHandles.lookup;
  43 import static java.lang.invoke.MethodType.methodType;
  44 import static test.java.lang.invoke.lib.InstructionHelper.invokedynamic;
  45 
  46 public class CallSiteTest {
  47     private static final Class<?> CLASS = CallSiteTest.class;
  48 
  49     private static final CallSite mcs;
  50     private static final CallSite vcs;
  51     private static final MethodHandle mh_foo;
  52     private static final MethodHandle mh_bar;
  53 
  54     private static final MethodHandle indy_mcs;
  55     private static final MethodHandle indy_vcs;
  56     static {
  57         try {
  58             MethodHandles.Lookup l = lookup();
  59             mh_foo = l.findStatic(CLASS, "foo", methodType(int.class, int.class, int.class));
  60             mh_bar = l.findStatic(CLASS, "bar", methodType(int.class, int.class, int.class));
  61             mcs = new MutableCallSite(mh_foo);
  62             vcs = new VolatileCallSite(mh_foo);
  63 
  64             MethodType bsmType = methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
  65             indy_mcs = invokedynamic(l, "mcs", methodType(int.class, int.class, int.class), "bsm_mcs", bsmType, S -> {});
  66             indy_vcs = invokedynamic(l, "vcs", methodType(int.class, int.class, int.class), "bsm_vcs", bsmType, S -> {});
  67         } catch (Exception e) {
  68             throw new Error(e);
  69         }
  70     }
  71 
  72     public static void main(String... av) throws Throwable {
  73         testMutableCallSite();
  74         testVolatileCallSite();
  75     }
  76 
  77     private static final int N = Integer.MAX_VALUE / 100;
  78     private static final int RESULT1 = 762786192;
  79     private static final int RESULT2 = -21474836;
  80 
  81     private static void assertEquals(int expected, int actual) {
  82         if (expected != actual)
  83             throw new AssertionError("expected: " + expected + ", actual: " + actual);
  84     }
  85 
  86     private static void testMutableCallSite() throws Throwable {
  87         // warm-up
  88         for (int i = 0; i < 20000; i++) {
  89             mcs.setTarget(mh_foo);
  90         }
  91         // run
  92         for (int n = 0; n < 2; n++) {
  93             mcs.setTarget(mh_foo);
  94             for (int i = 0; i < 5; i++) {
  95                 assertEquals(RESULT1, runMutableCallSite());
  96             }
  97             mcs.setTarget(mh_bar);
  98             for (int i = 0; i < 5; i++) {
  99                 assertEquals(RESULT2, runMutableCallSite());
 100             }
 101         }
 102     }
 103     private static void testVolatileCallSite() throws Throwable {
 104         // warm-up
 105         for (int i = 0; i < 20000; i++) {
 106             vcs.setTarget(mh_foo);
 107         }
 108         // run
 109         for (int n = 0; n < 2; n++) {
 110             vcs.setTarget(mh_foo);
 111             for (int i = 0; i < 5; i++) {
 112                 assertEquals(RESULT1, runVolatileCallSite());
 113             }
 114             vcs.setTarget(mh_bar);
 115             for (int i = 0; i < 5; i++) {
 116                 assertEquals(RESULT2, runVolatileCallSite());
 117             }
 118         }
 119     }
 120 
 121     private static int runMutableCallSite() throws Throwable {
 122         int sum = 0;
 123         for (int i = 0; i < N; i++) {
 124             sum += (int) indy_mcs.invokeExact(i, i+1);
 125         }
 126         return sum;
 127     }
 128     private static int runVolatileCallSite() throws Throwable {
 129         int sum = 0;
 130         for (int i = 0; i < N; i++) {
 131             sum += (int) indy_vcs.invokeExact(i, i+1);
 132         }
 133         return sum;
 134     }
 135 
 136     static int foo(int a, int b) { return a + b; }
 137     static int bar(int a, int b) { return a - b; }
 138 
 139     static CallSite bsm_mcs(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
 140         return mcs;
 141     }
 142 
 143     static CallSite bsm_vcs(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
 144         return vcs;
 145     }
 146 }