src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java

changeset 101
f8221ce53c2e
parent 90
5a820fb11814
child 404
18d467e94150
equal deleted inserted replaced
100:3245e174fe3a 101:f8221ce53c2e
89 import java.util.LinkedList; 89 import java.util.LinkedList;
90 import java.util.List; 90 import java.util.List;
91 import jdk.internal.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest; 91 import jdk.internal.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest;
92 import jdk.internal.dynalink.linker.LinkerServices; 92 import jdk.internal.dynalink.linker.LinkerServices;
93 import jdk.internal.dynalink.support.TypeUtilities; 93 import jdk.internal.dynalink.support.TypeUtilities;
94
95 94
96 /** 95 /**
97 * Represents an overloaded method. 96 * Represents an overloaded method.
98 * 97 *
99 * @author Attila Szegedi 98 * @author Attila Szegedi
202 // Very lucky, we ended up with a single candidate method handle based on the call site signature; we 201 // Very lucky, we ended up with a single candidate method handle based on the call site signature; we
203 // can link it very simply by delegating to a SimpleDynamicMethod. 202 // can link it very simply by delegating to a SimpleDynamicMethod.
204 final MethodHandle mh = invokables.iterator().next(); 203 final MethodHandle mh = invokables.iterator().next();
205 return new SimpleDynamicMethod(mh).getInvocation(callSiteType, linkerServices); 204 return new SimpleDynamicMethod(mh).getInvocation(callSiteType, linkerServices);
206 } 205 }
207 } 206 default: {
208 207 // We have more than one candidate. We have no choice but to link to a method that resolves overloads on
209 // We have more than one candidate. We have no choice but to link to a method that resolves overloads on every 208 // every invocation (alternatively, we could opportunistically link the one method that resolves for the
210 // invocation (alternatively, we could opportunistically link the one method that resolves for the current 209 // current arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd
211 // arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd go back all the 210 // go back all the way to candidate selection.
212 // way to candidate selection. 211 // TODO: cache per call site type
213 // TODO: cache per call site type 212 return new OverloadedMethod(invokables, this, callSiteType, linkerServices).getInvoker();
214 return new OverloadedMethod(invokables, this, callSiteType, linkerServices).getInvoker(); 213 }
214 }
215
215 } 216 }
216 217
217 @Override 218 @Override
218 public boolean contains(MethodHandle mh) { 219 public boolean contains(MethodHandle mh) {
219 final MethodType type = mh.type(); 220 final MethodType type = mh.type();
246 MethodHandle m) { 247 MethodHandle m) {
247 final MethodType methodType = m.type(); 248 final MethodType methodType = m.type();
248 final boolean varArgs = m.isVarargsCollector(); 249 final boolean varArgs = m.isVarargsCollector();
249 final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0); 250 final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0);
250 final int callSiteArgLen = callSiteType.parameterCount(); 251 final int callSiteArgLen = callSiteType.parameterCount();
252
253 // Arity checks
251 if(varArgs) { 254 if(varArgs) {
252 if(callSiteArgLen < fixedArgLen) { 255 if(callSiteArgLen < fixedArgLen) {
253 return false; 256 return false;
254 } 257 }
255 } else if(callSiteArgLen != fixedArgLen) { 258 } else if(callSiteArgLen != fixedArgLen) {
256 return false; 259 return false;
257 } 260 }
258 // Starting from 1, as receiver type doesn't participate 261
262 // Fixed arguments type checks, starting from 1, as receiver type doesn't participate
259 for(int i = 1; i < fixedArgLen; ++i) { 263 for(int i = 1; i < fixedArgLen; ++i) {
260 if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), methodType.parameterType(i))) { 264 if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), methodType.parameterType(i))) {
261 return false; 265 return false;
262 } 266 }
263 } 267 }
264 if(varArgs) { 268 if(!varArgs) {
265 final Class<?> varArgArrayType = methodType.parameterType(fixedArgLen); 269 // Not vararg; both arity and types matched.
266 final Class<?> varArgType = varArgArrayType.getComponentType();
267 if(fixedArgLen == callSiteArgLen - 1) {
268 final Class<?> callSiteArgType = callSiteType.parameterType(fixedArgLen);
269 // Exactly one vararg; check both exact matching and component
270 // matching.
271 return isApplicableDynamically(linkerServices, callSiteArgType, varArgArrayType)
272 || isApplicableDynamically(linkerServices, callSiteArgType, varArgType);
273 } else {
274 for(int i = fixedArgLen; i < callSiteArgLen; ++i) {
275 if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), varArgType)) {
276 return false;
277 }
278 }
279 return true;
280 }
281 } else {
282 return true; 270 return true;
283 } 271 }
272
273 final Class<?> varArgArrayType = methodType.parameterType(fixedArgLen);
274 final Class<?> varArgType = varArgArrayType.getComponentType();
275
276 if(fixedArgLen == callSiteArgLen - 1) {
277 // Exactly one vararg; check both array type matching and array component type matching.
278 final Class<?> callSiteArgType = callSiteType.parameterType(fixedArgLen);
279 return isApplicableDynamically(linkerServices, callSiteArgType, varArgArrayType)
280 || isApplicableDynamically(linkerServices, callSiteArgType, varArgType);
281 }
282
283 // Either zero, or more than one vararg; check if all actual vararg types match the vararg array component type.
284 for(int i = fixedArgLen; i < callSiteArgLen; ++i) {
285 if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), varArgType)) {
286 return false;
287 }
288 }
289
290 return true;
284 } 291 }
285 292
286 private static boolean isApplicableDynamically(LinkerServices linkerServices, Class<?> callSiteType, 293 private static boolean isApplicableDynamically(LinkerServices linkerServices, Class<?> callSiteType,
287 Class<?> methodType) { 294 Class<?> methodType) {
288 return TypeUtilities.isPotentiallyConvertible(callSiteType, methodType) 295 return TypeUtilities.isPotentiallyConvertible(callSiteType, methodType)
296 /** 303 /**
297 * Add a method identified by a {@link SimpleDynamicMethod} to this overloaded method's set. 304 * Add a method identified by a {@link SimpleDynamicMethod} to this overloaded method's set.
298 * 305 *
299 * @param method the method to add. 306 * @param method the method to add.
300 */ 307 */
301 public void addMethod(SimpleDynamicMethod method) { 308 void addMethod(SimpleDynamicMethod method) {
302 addMethod(method.getTarget()); 309 addMethod(method.getTarget());
303 } 310 }
304 311
305 /** 312 /**
306 * Add a method to this overloaded method's set. 313 * Add a method to this overloaded method's set.

mercurial