45 import java.lang.invoke.CallSite;
46 import java.lang.invoke.MethodHandle;
47 import java.lang.invoke.MethodHandleHelper;
48 import java.lang.invoke.MethodHandles;
49 import java.lang.invoke.MethodType;
50 import java.lang.invoke.MutableCallSite;
51 import java.lang.ref.PhantomReference;
52 import java.lang.ref.Reference;
53 import java.lang.ref.ReferenceQueue;
54 import java.lang.reflect.Field;
55
56 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
57 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
58 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
59 import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
60 import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
61
62 public class CallSiteDepContextTest {
63 static final Unsafe UNSAFE = Unsafe.getUnsafe();
64 static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
65 static final String CLASS_NAME = "java/lang/invoke/Test";
66 static final String METHOD_NAME = "m";
67 static final MethodType TYPE = MethodType.methodType(int.class);
68
69 static MutableCallSite mcs;
70 static MethodHandle bsmMH;
71
72 static {
73 try {
74 bsmMH = LOOKUP.findStatic(
75 CallSiteDepContextTest.class, "bootstrap",
76 MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class));
77 } catch(Throwable e) {
78 throw new InternalError(e);
79 }
80 }
81
82 public static CallSite bootstrap(MethodHandles.Lookup caller,
83 String invokedName,
84 MethodType invokedType) {
85 return mcs;
112
113 private static void execute(int expected, MethodHandle... mhs) throws Throwable {
114 for (int i = 0; i < 20_000; i++) {
115 for (MethodHandle mh : mhs) {
116 int r = (int) mh.invokeExact();
117 if (r != expected) {
118 throw new Error(r + " != " + expected);
119 }
120 }
121 }
122 }
123
124 public static void testHiddenDepField() {
125 try {
126 Field f = MethodHandleHelper.MHN_CALL_SITE_CONTEXT_CLASS.getDeclaredField("vmdependencies");
127 throw new AssertionError("Context.dependencies field should be hidden");
128 } catch(NoSuchFieldException e) { /* expected */ }
129 }
130
131 public static void testSharedCallSite() throws Throwable {
132 Class<?> cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_1"), null);
133 Class<?> cls2 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("CS_2"), null);
134
135 MethodHandle[] mhs = new MethodHandle[] {
136 LOOKUP.findStatic(cls1, METHOD_NAME, TYPE),
137 LOOKUP.findStatic(cls2, METHOD_NAME, TYPE)
138 };
139
140 mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
141 execute(1, mhs);
142 mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
143 execute(2, mhs);
144 }
145
146 public static void testNonBoundCallSite() throws Throwable {
147 mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
148
149 // mcs.context == null
150 MethodHandle mh = mcs.dynamicInvoker();
151 execute(1, mh);
152
153 // mcs.context == cls1
154 Class<?> cls1 = UNSAFE.defineAnonymousClass(Object.class, getClassFile("NonBound_1"), null);
155 MethodHandle mh1 = LOOKUP.findStatic(cls1, METHOD_NAME, TYPE);
156
157 execute(1, mh1);
158
159 mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
160
161 execute(2, mh, mh1);
162 }
163
164 static ReferenceQueue rq = new ReferenceQueue();
165 static PhantomReference ref;
166
167 public static void testGC(boolean clear, boolean precompile) throws Throwable {
168 String id = "_" + clear + "_" + precompile;
169
170 mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
171
172 Class<?>[] cls = new Class[] {
173 UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_1" + id), null),
174 UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_2" + id), null),
175 };
176
177 MethodHandle[] mhs = new MethodHandle[] {
178 LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE),
179 LOOKUP.findStatic(cls[1], METHOD_NAME, TYPE),
180 };
181
182 // mcs.context == cls[0]
183 int r = (int) mhs[0].invokeExact();
184
185 execute(1, mhs);
186
187 ref = new PhantomReference<>(cls[0], rq);
188 cls[0] = UNSAFE.defineAnonymousClass(Object.class, getClassFile("GC_3" + id), null);
189 mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE);
190
191 do {
192 System.gc();
193 try {
194 Reference ref1 = rq.remove(100);
195 if (ref1 == ref) {
196 break;
197 }
198 } catch(InterruptedException e) { /* ignore */ }
199 } while (true);
200
201 if (clear) {
202 ref.clear();
203 System.gc(); // Ensure that the stale context is unloaded
204 }
205 if (precompile) {
206 execute(1, mhs);
207 }
208 mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
|
45 import java.lang.invoke.CallSite;
46 import java.lang.invoke.MethodHandle;
47 import java.lang.invoke.MethodHandleHelper;
48 import java.lang.invoke.MethodHandles;
49 import java.lang.invoke.MethodType;
50 import java.lang.invoke.MutableCallSite;
51 import java.lang.ref.PhantomReference;
52 import java.lang.ref.Reference;
53 import java.lang.ref.ReferenceQueue;
54 import java.lang.reflect.Field;
55
56 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC;
57 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC;
58 import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER;
59 import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
60 import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
61
62 public class CallSiteDepContextTest {
63 static final Unsafe UNSAFE = Unsafe.getUnsafe();
64 static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
65 static final String CLASS_NAME = "compiler/jsr292/Test";
66 static final String METHOD_NAME = "m";
67 static final MethodType TYPE = MethodType.methodType(int.class);
68
69 static MutableCallSite mcs;
70 static MethodHandle bsmMH;
71
72 static {
73 try {
74 bsmMH = LOOKUP.findStatic(
75 CallSiteDepContextTest.class, "bootstrap",
76 MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class));
77 } catch(Throwable e) {
78 throw new InternalError(e);
79 }
80 }
81
82 public static CallSite bootstrap(MethodHandles.Lookup caller,
83 String invokedName,
84 MethodType invokedType) {
85 return mcs;
112
113 private static void execute(int expected, MethodHandle... mhs) throws Throwable {
114 for (int i = 0; i < 20_000; i++) {
115 for (MethodHandle mh : mhs) {
116 int r = (int) mh.invokeExact();
117 if (r != expected) {
118 throw new Error(r + " != " + expected);
119 }
120 }
121 }
122 }
123
124 public static void testHiddenDepField() {
125 try {
126 Field f = MethodHandleHelper.MHN_CALL_SITE_CONTEXT_CLASS.getDeclaredField("vmdependencies");
127 throw new AssertionError("Context.dependencies field should be hidden");
128 } catch(NoSuchFieldException e) { /* expected */ }
129 }
130
131 public static void testSharedCallSite() throws Throwable {
132 Class<?> cls1 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("CS_1"), null);
133 Class<?> cls2 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("CS_2"), null);
134
135 MethodHandle[] mhs = new MethodHandle[] {
136 LOOKUP.findStatic(cls1, METHOD_NAME, TYPE),
137 LOOKUP.findStatic(cls2, METHOD_NAME, TYPE)
138 };
139
140 mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
141 execute(1, mhs);
142 mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
143 execute(2, mhs);
144 }
145
146 public static void testNonBoundCallSite() throws Throwable {
147 mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
148
149 // mcs.context == null
150 MethodHandle mh = mcs.dynamicInvoker();
151 execute(1, mh);
152
153 // mcs.context == cls1
154 Class<?> cls1 = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("NonBound_1"), null);
155 MethodHandle mh1 = LOOKUP.findStatic(cls1, METHOD_NAME, TYPE);
156
157 execute(1, mh1);
158
159 mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
160
161 execute(2, mh, mh1);
162 }
163
164 static ReferenceQueue rq = new ReferenceQueue();
165 static PhantomReference ref;
166
167 public static void testGC(boolean clear, boolean precompile) throws Throwable {
168 String id = "_" + clear + "_" + precompile;
169
170 mcs = new MutableCallSite(LOOKUP.findStatic(T.class, "f1", TYPE));
171
172 Class<?>[] cls = new Class[] {
173 UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_1" + id), null),
174 UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_2" + id), null),
175 };
176
177 MethodHandle[] mhs = new MethodHandle[] {
178 LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE),
179 LOOKUP.findStatic(cls[1], METHOD_NAME, TYPE),
180 };
181
182 // mcs.context == cls[0]
183 int r = (int) mhs[0].invokeExact();
184
185 execute(1, mhs);
186
187 ref = new PhantomReference<>(cls[0], rq);
188 cls[0] = UNSAFE.defineAnonymousClass(CallSiteDepContextTest.class, getClassFile("GC_3" + id), null);
189 mhs[0] = LOOKUP.findStatic(cls[0], METHOD_NAME, TYPE);
190
191 do {
192 System.gc();
193 try {
194 Reference ref1 = rq.remove(100);
195 if (ref1 == ref) {
196 break;
197 }
198 } catch(InterruptedException e) { /* ignore */ }
199 } while (true);
200
201 if (clear) {
202 ref.clear();
203 System.gc(); // Ensure that the stale context is unloaded
204 }
205 if (precompile) {
206 execute(1, mhs);
207 }
208 mcs.setTarget(LOOKUP.findStatic(T.class, "f2", TYPE));
|