24 */ |
24 */ |
25 |
25 |
26 package sun.dyn; |
26 package sun.dyn; |
27 |
27 |
28 import java.dyn.*; |
28 import java.dyn.*; |
29 import java.util.logging.Level; |
|
30 import java.util.logging.Logger; |
|
31 |
29 |
32 /** |
30 /** |
33 * Parts of CallSite known to the JVM. |
31 * Parts of CallSite known to the JVM. |
34 * FIXME: Merge all this into CallSite proper. |
|
35 * @author jrose |
32 * @author jrose |
36 */ |
33 */ |
37 public class CallSiteImpl { |
34 public class CallSiteImpl { |
38 // Field used only by the JVM. Do not use or change. |
35 // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite: |
39 private Object vmmethod; |
36 static CallSite makeSite(MethodHandle bootstrapMethod, |
40 |
37 // Callee information: |
41 // Values supplied by the JVM: |
38 String name, MethodType type, |
42 protected int callerMID, callerBCI; |
39 // Call-site attributes, if any: |
43 |
40 Object info, |
44 private MethodHandle target; |
41 // Caller information: |
45 protected final Object caller; // usually a class |
42 MemberName callerMethod, int callerBCI) { |
46 protected final String name; |
43 Class<?> caller = callerMethod.getDeclaringClass(); |
47 protected final MethodType type; |
44 if (bootstrapMethod == null) { |
48 |
45 // If there is no bootstrap method, throw IncompatibleClassChangeError. |
49 /** called only directly from CallSite() */ |
46 // This is a valid generic error type for resolution (JLS 12.3.3). |
50 protected CallSiteImpl(Access token, Object caller, String name, MethodType type) { |
47 throw new IncompatibleClassChangeError |
51 Access.check(token); |
48 ("Class "+caller.getName()+" has not declared a bootstrap method for invokedynamic"); |
52 this.caller = caller; |
49 } |
53 this.name = name; |
|
54 this.type = type; |
|
55 } |
|
56 |
|
57 /** native version of setTarget */ |
|
58 protected void setTarget(MethodHandle mh) { |
|
59 //System.out.println("setTarget "+this+" := "+mh); |
|
60 // XXX I don't know how to fix this properly. |
|
61 // if (false && MethodHandleNatives.JVM_SUPPORT) // FIXME: enable this |
|
62 // MethodHandleNatives.linkCallSite(this, mh); |
|
63 // else |
|
64 this.target = mh; |
|
65 } |
|
66 |
|
67 protected MethodHandle getTarget() { |
|
68 return target; |
|
69 } |
|
70 |
|
71 private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE = |
|
72 MethodHandleImpl.IMPL_LOOKUP.findStatic(CallSite.class, "privateInitializeCallSite", |
|
73 MethodType.methodType(void.class, CallSite.class, int.class, int.class)); |
|
74 |
|
75 // this is the up-call from the JVM: |
|
76 static CallSite makeSite(Class<?> caller, String name, MethodType type, |
|
77 int callerMID, int callerBCI) { |
|
78 MethodHandle bsm = Linkage.getBootstrapMethod(caller); |
|
79 if (bsm == null) |
|
80 throw new InvokeDynamicBootstrapError("class has no bootstrap method: "+caller); |
|
81 CallSite site; |
50 CallSite site; |
82 try { |
51 try { |
83 site = bsm.<CallSite>invoke(caller, name, type); |
52 if (bootstrapMethod.type().parameterCount() == 3) |
|
53 site = bootstrapMethod.<CallSite>invokeExact(caller, name, type); |
|
54 else if (bootstrapMethod.type().parameterCount() == 4) |
|
55 site = bootstrapMethod.<CallSite>invokeExact(caller, name, type, |
|
56 !(info instanceof java.lang.annotation.Annotation[]) ? null |
|
57 : (java.lang.annotation.Annotation[]) info); |
|
58 else |
|
59 throw new InternalError("bad BSM: "+bootstrapMethod); |
|
60 if (!(site instanceof CallSite)) |
|
61 throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller); |
|
62 PRIVATE_INITIALIZE_CALL_SITE.<void>invokeExact(site, |
|
63 name, type, |
|
64 callerMethod, callerBCI); |
|
65 assert(site.getTarget() != null); |
|
66 assert(site.getTarget().type().equals(type)); |
84 } catch (Throwable ex) { |
67 } catch (Throwable ex) { |
85 throw new InvokeDynamicBootstrapError("exception thrown while linking", ex); |
68 InvokeDynamicBootstrapError bex; |
86 } |
69 if (ex instanceof InvokeDynamicBootstrapError) |
87 if (site == null) |
70 bex = (InvokeDynamicBootstrapError) ex; |
88 throw new InvokeDynamicBootstrapError("class bootstrap method failed to create a call site: "+caller); |
71 else |
89 if (site.type() != type) |
72 bex = new InvokeDynamicBootstrapError("call site initialization exception", ex); |
90 throw new InvokeDynamicBootstrapError("call site type not initialized correctly: "+site); |
73 throw bex; |
91 if (site.callerClass() != caller) |
|
92 throw new InvokeDynamicBootstrapError("call site caller not initialized correctly: "+site); |
|
93 if ((Object)site.name() != name) |
|
94 throw new InvokeDynamicBootstrapError("call site name not initialized correctly: "+site); |
|
95 try { |
|
96 PRIVATE_INITIALIZE_CALL_SITE.<void>invoke(site, callerMID, callerBCI); |
|
97 } catch (Throwable ex) { |
|
98 throw new InvokeDynamicBootstrapError("call site initialization exception", ex); |
|
99 } |
74 } |
100 return site; |
75 return site; |
101 } |
76 } |
|
77 |
|
78 // This method is private in CallSite because it touches private fields in CallSite. |
|
79 // These private fields (vmmethod, vmindex) are specific to the JVM. |
|
80 private static final MethodHandle PRIVATE_INITIALIZE_CALL_SITE = |
|
81 MethodHandleImpl.IMPL_LOOKUP.findVirtual(CallSite.class, "initializeFromJVM", |
|
82 MethodType.methodType(void.class, |
|
83 String.class, MethodType.class, |
|
84 MemberName.class, int.class)); |
|
85 |
|
86 public static void setCallSiteTarget(Access token, CallSite site, MethodHandle target) { |
|
87 Access.check(token); |
|
88 MethodHandleNatives.setCallSiteTarget(site, target); |
|
89 } |
102 } |
90 } |