27 |
27 |
28 import java.util.Arrays; |
28 import java.util.Arrays; |
29 import java.util.Collections; |
29 import java.util.Collections; |
30 import java.util.HashMap; |
30 import java.util.HashMap; |
31 import java.util.List; |
31 import java.util.List; |
32 import sun.dyn.Access; |
|
33 import sun.dyn.Invokers; |
|
34 import sun.dyn.MethodHandleImpl; |
|
35 import sun.dyn.MethodTypeImpl; |
|
36 import sun.dyn.util.BytecodeDescriptor; |
32 import sun.dyn.util.BytecodeDescriptor; |
37 import static sun.dyn.MemberName.newIllegalArgumentException; |
33 import static java.dyn.MethodHandleStatics.*; |
38 |
34 |
39 /** |
35 /** |
40 * A method type represents the arguments and return type accepted and |
36 * A method type represents the arguments and return type accepted and |
41 * returned by a method handle, or the arguments and return type passed |
37 * returned by a method handle, or the arguments and return type passed |
42 * and expected by a method handle caller. Method types must be properly |
38 * and expected by a method handle caller. Method types must be properly |
94 // The remaining fields are caches of various sorts: |
90 // The remaining fields are caches of various sorts: |
95 private MethodTypeForm form; // erased form, plus cached data about primitives |
91 private MethodTypeForm form; // erased form, plus cached data about primitives |
96 private MethodType wrapAlt; // alternative wrapped/unwrapped version |
92 private MethodType wrapAlt; // alternative wrapped/unwrapped version |
97 private Invokers invokers; // cache of handy higher-order adapters |
93 private Invokers invokers; // cache of handy higher-order adapters |
98 |
94 |
99 private static final Access IMPL_TOKEN = Access.getToken(); |
|
100 |
|
101 // share a cache with a friend in this package |
|
102 Invokers getInvokers() { return invokers; } |
|
103 void setInvokers(Invokers inv) { invokers = inv; } |
|
104 |
|
105 static { |
|
106 // This hack allows the implementation package special access to |
|
107 // the internals of MethodType. In particular, the MTImpl has all sorts |
|
108 // of cached information useful to the implementation code. |
|
109 MethodTypeImpl.setMethodTypeFriend(IMPL_TOKEN, new MethodTypeImpl.MethodTypeFriend() { |
|
110 public Class<?>[] ptypes(MethodType mt) { return mt.ptypes; } |
|
111 public MethodTypeImpl form(MethodType mt) { return mt.form; } |
|
112 public void setForm(MethodType mt, MethodTypeImpl form) { |
|
113 assert(mt.form == null); |
|
114 mt.form = (MethodTypeForm) form; |
|
115 } |
|
116 public MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) { |
|
117 return MethodType.makeImpl(rtype, ptypes, trusted); |
|
118 } |
|
119 public MethodTypeImpl newMethodTypeForm(MethodType mt) { |
|
120 return new MethodTypeForm(mt); |
|
121 } |
|
122 public Invokers getInvokers(MethodType mt) { return mt.invokers; } |
|
123 public void setInvokers(MethodType mt, Invokers inv) { mt.invokers = inv; } |
|
124 }); |
|
125 } |
|
126 |
|
127 /** |
95 /** |
128 * Check the given parameters for validity and store them into the final fields. |
96 * Check the given parameters for validity and store them into the final fields. |
129 */ |
97 */ |
130 private MethodType(Class<?> rtype, Class<?>[] ptypes) { |
98 private MethodType(Class<?> rtype, Class<?>[] ptypes) { |
131 checkRtype(rtype); |
99 checkRtype(rtype); |
132 checkPtypes(ptypes); |
100 checkPtypes(ptypes); |
133 this.rtype = rtype; |
101 this.rtype = rtype; |
134 this.ptypes = ptypes; |
102 this.ptypes = ptypes; |
135 } |
103 } |
|
104 |
|
105 /*trusted*/ MethodTypeForm form() { return form; } |
|
106 /*trusted*/ Class<?> rtype() { return rtype; } |
|
107 /*trusted*/ Class<?>[] ptypes() { return ptypes; } |
136 |
108 |
137 private static void checkRtype(Class<?> rtype) { |
109 private static void checkRtype(Class<?> rtype) { |
138 rtype.equals(rtype); // null check |
110 rtype.equals(rtype); // null check |
139 } |
111 } |
140 private static int checkPtype(Class<?> ptype) { |
112 private static int checkPtype(Class<?> ptype) { |
251 * @param rtype desired return type |
223 * @param rtype desired return type |
252 * @param ptypes desired parameter types |
224 * @param ptypes desired parameter types |
253 * @param trusted whether the ptypes can be used without cloning |
225 * @param trusted whether the ptypes can be used without cloning |
254 * @return the unique method type of the desired structure |
226 * @return the unique method type of the desired structure |
255 */ |
227 */ |
256 private static |
228 /*trusted*/ static |
257 MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) { |
229 MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) { |
258 if (ptypes == null || ptypes.length == 0) { |
230 if (ptypes == null || ptypes.length == 0) { |
259 ptypes = NO_PTYPES; trusted = true; |
231 ptypes = NO_PTYPES; trusted = true; |
260 } |
232 } |
261 MethodType mt1 = new MethodType(rtype, ptypes); |
233 MethodType mt1 = new MethodType(rtype, ptypes); |
267 } |
239 } |
268 if (!trusted) |
240 if (!trusted) |
269 // defensively copy the array passed in by the user |
241 // defensively copy the array passed in by the user |
270 mt1 = new MethodType(rtype, ptypes.clone()); |
242 mt1 = new MethodType(rtype, ptypes.clone()); |
271 // promote the object to the Real Thing, and reprobe |
243 // promote the object to the Real Thing, and reprobe |
272 MethodTypeImpl.initForm(IMPL_TOKEN, mt1); |
244 MethodTypeForm form = MethodTypeForm.findForm(mt1); |
|
245 mt1.form = form; |
|
246 if (form.erasedType == mt1) { |
|
247 // This is a principal (erased) type; show it to the JVM. |
|
248 MethodHandleNatives.init(mt1); |
|
249 } |
273 synchronized (internTable) { |
250 synchronized (internTable) { |
274 mt0 = internTable.get(mt1); |
251 mt0 = internTable.get(mt1); |
275 if (mt0 != null) |
252 if (mt0 != null) |
276 return mt0; |
253 return mt0; |
277 internTable.put(mt1, mt1); |
254 internTable.put(mt1, mt1); |
278 } |
255 } |
279 return mt1; |
256 return mt1; |
280 } |
|
281 |
|
282 // Entry point from JVM. TODO: Change the name & signature. |
|
283 private static MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, |
|
284 boolean ignore1, boolean ignore2) { |
|
285 return makeImpl(rtype, ptypes, true); |
|
286 } |
257 } |
287 |
258 |
288 private static final MethodType[] objectOnlyTypes = new MethodType[20]; |
259 private static final MethodType[] objectOnlyTypes = new MethodType[20]; |
289 |
260 |
290 /** |
261 /** |
545 private static MethodType unwrapWithNoPrims(MethodType wt) { |
516 private static MethodType unwrapWithNoPrims(MethodType wt) { |
546 assert(!wt.hasPrimitives()); |
517 assert(!wt.hasPrimitives()); |
547 MethodType uwt = wt.wrapAlt; |
518 MethodType uwt = wt.wrapAlt; |
548 if (uwt == null) { |
519 if (uwt == null) { |
549 // fill in lazily |
520 // fill in lazily |
550 uwt = MethodTypeImpl.canonicalize(wt, MethodTypeImpl.UNWRAP, MethodTypeImpl.UNWRAP); |
521 uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP); |
551 if (uwt == null) |
522 if (uwt == null) |
552 uwt = wt; // type has no wrappers or prims at all |
523 uwt = wt; // type has no wrappers or prims at all |
553 wt.wrapAlt = uwt; |
524 wt.wrapAlt = uwt; |
554 } |
525 } |
555 return uwt; |
526 return uwt; |
664 * number of long and double parameters (if any). |
635 * number of long and double parameters (if any). |
665 * <p> |
636 * <p> |
666 * This method is included for the benfit of applications that must |
637 * This method is included for the benfit of applications that must |
667 * generate bytecodes that process method handles and invokedynamic. |
638 * generate bytecodes that process method handles and invokedynamic. |
668 * @return the number of JVM stack slots for this type's parameters |
639 * @return the number of JVM stack slots for this type's parameters |
669 * @deprecated Will be removed for PFD. |
640 */ |
670 */ |
641 /*non-public*/ int parameterSlotCount() { |
671 public int parameterSlotCount() { |
|
672 return form.parameterSlotCount(); |
642 return form.parameterSlotCount(); |
|
643 } |
|
644 |
|
645 /*non-public*/ Invokers invokers() { |
|
646 Invokers inv = invokers; |
|
647 if (inv != null) return inv; |
|
648 invokers = inv = new Invokers(this); |
|
649 return inv; |
673 } |
650 } |
674 |
651 |
675 /** Reports the number of JVM stack slots which carry all parameters including and after |
652 /** Reports the number of JVM stack slots which carry all parameters including and after |
676 * the given position, which must be in the range of 0 to |
653 * the given position, which must be in the range of 0 to |
677 * {@code parameterCount} inclusive. Successive parameters are |
654 * {@code parameterCount} inclusive. Successive parameters are |
692 * generate bytecodes that process method handles and invokedynamic. |
669 * generate bytecodes that process method handles and invokedynamic. |
693 * @param num an index (zero-based, inclusive) within the parameter types |
670 * @param num an index (zero-based, inclusive) within the parameter types |
694 * @return the index of the (shallowest) JVM stack slot transmitting the |
671 * @return the index of the (shallowest) JVM stack slot transmitting the |
695 * given parameter |
672 * given parameter |
696 * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()} |
673 * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()} |
697 * @deprecated Will be removed for PFD. |
674 */ |
698 */ |
675 /*non-public*/ int parameterSlotDepth(int num) { |
699 public int parameterSlotDepth(int num) { |
|
700 if (num < 0 || num > ptypes.length) |
676 if (num < 0 || num > ptypes.length) |
701 parameterType(num); // force a range check |
677 parameterType(num); // force a range check |
702 return form.parameterToArgSlot(num-1); |
678 return form.parameterToArgSlot(num-1); |
703 } |
679 } |
704 |
680 |
708 * else if the return type is long or double, it will be two, else one. |
684 * else if the return type is long or double, it will be two, else one. |
709 * <p> |
685 * <p> |
710 * This method is included for the benfit of applications that must |
686 * This method is included for the benfit of applications that must |
711 * generate bytecodes that process method handles and invokedynamic. |
687 * generate bytecodes that process method handles and invokedynamic. |
712 * @return the number of JVM stack slots (0, 1, or 2) for this type's return value |
688 * @return the number of JVM stack slots (0, 1, or 2) for this type's return value |
713 * @deprecated Will be removed for PFD. |
689 * Will be removed for PFD. |
714 */ |
690 */ |
715 public int returnSlotCount() { |
691 /*non-public*/ int returnSlotCount() { |
716 return form.returnSlotCount(); |
692 return form.returnSlotCount(); |
717 } |
693 } |
718 |
694 |
719 /** |
695 /** |
720 * Find or create an instance of a method type, given the spelling of its bytecode descriptor. |
696 * Find or create an instance of a method type, given the spelling of its bytecode descriptor. |