Path: blob/master/test/hotspot/jtreg/compiler/jsr292/CallSiteDepContextTest.java
41149 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 805796726* @requires vm.opt.final.ClassUnloading27* @modules java.base/jdk.internal.misc28* java.base/jdk.internal.org.objectweb.asm29* @library patches /30*31* @build java.base/java.lang.invoke.MethodHandleHelper32* @run main/bootclasspath/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -Xlog:class+unload33* -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC34* -verbose:gc35* compiler.jsr292.CallSiteDepContextTest36*/3738package compiler.jsr292;3940import jdk.internal.org.objectweb.asm.ClassWriter;41import jdk.internal.org.objectweb.asm.Handle;42import jdk.internal.org.objectweb.asm.MethodVisitor;4344import java.lang.invoke.CallSite;45import java.lang.invoke.MethodHandle;46import java.lang.invoke.MethodHandleHelper;47import java.lang.invoke.MethodHandles;48import java.lang.invoke.MethodHandles.Lookup;49import java.lang.invoke.MethodType;50import java.lang.invoke.MutableCallSite;51import java.lang.ref.PhantomReference;52import java.lang.ref.Reference;53import java.lang.ref.ReferenceQueue;54import java.lang.reflect.Field;5556import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;57import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;58import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;59import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;60import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;6162public class CallSiteDepContextTest {63static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;64static final String CLASS_NAME = "compiler/jsr292/Test";65static final String METHOD_NAME = "m";66static final MethodType TYPE = MethodType.methodType(int.class);6768static MutableCallSite mcs;69static MethodHandle bsmMH;7071static {72try {73bsmMH = LOOKUP.findStatic(74CallSiteDepContextTest.class, "bootstrap",75MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class));76} catch(Throwable e) {77throw new InternalError(e);78}79}8081public static CallSite bootstrap(MethodHandles.Lookup caller,82String invokedName,83MethodType invokedType) {84return mcs;85}8687static class T {88static int f1() { return 1; }89static int f2() { return 2; }90}9192static byte[] getClassFile(String suffix) {93ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);94MethodVisitor mv;95cw.visit(52, ACC_PUBLIC | ACC_SUPER, CLASS_NAME + suffix, null, "java/lang/Object", null);96{97mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, METHOD_NAME, TYPE.toMethodDescriptorString(), null, null);98mv.visitCode();99Handle bsm = new Handle(H_INVOKESTATIC,100CallSiteDepContextTest.class.getName().replace(".", "/"),101"bootstrap",102bsmMH.type().toMethodDescriptorString());103mv.visitInvokeDynamicInsn("methodName", TYPE.toMethodDescriptorString(), bsm);104mv.visitInsn(IRETURN);105mv.visitMaxs(0, 0);106mv.visitEnd();107}108cw.visitEnd();109return cw.toByteArray();110}111112private static void execute(int expected, MethodHandle... mhs) throws Throwable {113for (int i = 0; i < 20_000; i++) {114for (MethodHandle mh : mhs) {115int r = (int) mh.invokeExact();116if (r != expected) {117throw new Error(r + " != " + expected);118}119}120}121}122123public static void testHiddenDepField() {124try {125Field f = MethodHandleHelper.MHN_CALL_SITE_CONTEXT_CLASS.getDeclaredField("vmdependencies");126throw new AssertionError("Context.dependencies field should be hidden");127} catch(NoSuchFieldException e) { /* expected */ }128}129130public static void testSharedCallSite() throws Throwable {131Lookup lookup = MethodHandles.lookup();132Class<?> cls1 = lookup.defineHiddenClass(getClassFile("CS_1"), true).lookupClass();133Class<?> cls2 = lookup.defineHiddenClass(getClassFile("CS_2"), true).lookupClass();134135MethodHandle[] mhs = new MethodHandle[] {136LOOKUP.findStatic(cls1, METHOD_NAME, TYPE),137LOOKUP.findStatic(cls2, METHOD_NAME, TYPE)138};139140mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));141execute(1, mhs);142mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));143execute(2, mhs);144}145146public static void testNonBoundCallSite() throws Throwable {147mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));148149// mcs.context == null150MethodHandle mh = mcs.dynamicInvoker();151execute(1, mh);152153// mcs.context == cls1154Lookup lookup = MethodHandles.lookup();155Class<?> cls1 = lookup.defineHiddenClass(getClassFile("NonBound_1"), true).lookupClass();156MethodHandle mh1 = LOOKUP.findStatic(cls1, METHOD_NAME, TYPE);157158execute(1, mh1);159160mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));161162execute(2, mh, mh1);163}164165static ReferenceQueue rq = new ReferenceQueue();166static PhantomReference ref;167168public static void testGC(boolean clear, boolean precompile) throws Throwable {169String id = "_" + clear + "_" + precompile;170171mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));172173Lookup lookup = MethodHandles.lookup();174Class<?>[] cls = new Class[] {175lookup.defineHiddenClass(getClassFile("GC_1"), true).lookupClass(),176lookup.defineHiddenClass(getClassFile("GC_2"), true).lookupClass(),177};178179MethodHandle[] mhs = new MethodHandle[] {180LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE),181LOOKUP.findStatic(cls[1], METHOD_NAME, TYPE),182};183184// mcs.context == cls[0]185int r = (int) mhs[0].invokeExact();186187execute(1, mhs);188189ref = new PhantomReference<>(cls[0], rq);190cls[0] = lookup.defineHiddenClass(getClassFile("GC_3"), true).lookupClass();191mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE);192193do {194System.gc();195try {196Reference ref1 = rq.remove(100);197if (ref1 == ref) {198break;199}200} catch(InterruptedException e) { /* ignore */ }201} while (true);202203if (clear) {204ref.clear();205System.gc(); // Ensure that the stale context is unloaded206}207if (precompile) {208execute(1, mhs);209}210mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));211execute(2, mhs);212}213214public static void main(String[] args) throws Throwable {215testHiddenDepField();216testSharedCallSite();217testNonBoundCallSite();218testGC(false, false);219testGC(false, true);220testGC( true, false);221testGC( true, true);222System.out.println("TEST PASSED");223}224}225226227