@CompilerDirectives.TruffleBoundary static boolean isApplicableByArity(JavaMethodDesc method, int nArgs) { if (method instanceof SingleMethodDesc) { return nArgs == ((SingleMethodDesc) method).getParameterCount() || ((SingleMethodDesc) method).isVarArgs() && nArgs >= ((SingleMethodDesc) method).getParameterCount() - 1; } else { SingleMethodDesc[] overloads = ((OverloadedMethodDesc) method).getOverloads(); for (SingleMethodDesc overload : overloads) { if (isApplicableByArity(overload, nArgs)) { return true; } } return false; } }
private static int compareOverloads(SingleMethodDesc m1, SingleMethodDesc m2, Object[] args, boolean varArgs) { int res = 0; int maxParamCount = Math.max(m1.getParameterCount(), m2.getParameterCount()); assert !varArgs || m1.isVarArgs() && m2.isVarArgs(); assert varArgs || (m1.getParameterCount() == m2.getParameterCount() && args.length == m1.getParameterCount()); assert maxParamCount <= args.length; for (int i = 0; i < maxParamCount; i++) { Class<?> t1 = getParameterType(m1.getParameterTypes(), i, varArgs); Class<?> t2 = getParameterType(m2.getParameterTypes(), i, varArgs); if (t1 == t2) { continue; } int r = compareAssignable(t1, t2); if (r == 0) { continue; } if (res == 0) { res = r; } else if (res != r) { // cannot determine definite ranking between these two overloads res = 0; break; } } return res; }
private static Object doInvoke(SingleMethodDesc method, Object obj, Object[] arguments, Object languageContext) { assert arguments.length == method.getParameterCount(); Object ret; try { ret = method.invoke(obj, arguments); } catch (Throwable e) { throw JavaInteropReflect.rethrow(JavaInterop.wrapHostException(languageContext, e)); } return JavaInterop.toGuestValue(ret, languageContext); }
@TruffleBoundary static boolean asVarArgs(Object[] args, SingleMethodDesc overload) { if (overload.isVarArgs()) { int parameterCount = overload.getParameterCount(); if (args.length == parameterCount) { return !isSubtypeOf(args[parameterCount - 1], overload.getParameterTypes()[parameterCount - 1]); } else { assert args.length != parameterCount; return true; } } else { return false; } }
boolean anyVarArgs = false; for (SingleMethodDesc overload : overloads) { int paramCount = overload.getParameterCount(); if (!overload.isVarArgs()) { if (args.length != paramCount) {
int paramCount = candidate.getParameterCount(); if (!candidate.isVarArgs() || paramCount == args.length) { assert paramCount == args.length; for (SingleMethodDesc candidate : applicableByArity) { if (candidate.isVarArgs()) { int parameterCount = candidate.getParameterCount(); Class<?>[] parameterTypes = candidate.getParameterTypes(); Type[] genericParameterTypes = candidate.getGenericParameterTypes();
@Specialization(replaces = {"doFixed", "doVarArgs"}) Object doSingleUncached(SingleMethodDesc method, Object obj, Object[] args, Object languageContext, @Cached("create()") ToJavaNode toJavaNode, @Cached("createBinaryProfile()") ConditionProfile isVarArgsProfile) { int parameterCount = method.getParameterCount(); int minArity = method.isVarArgs() ? parameterCount - 1 : parameterCount; if (args.length < minArity) { throw ArityException.raise(minArity, args.length); } Object[] convertedArguments = prepareArgumentsUncached(method, args, languageContext, toJavaNode, isVarArgsProfile); return doInvoke(method, obj, convertedArguments, languageContext); }
private static Object[] prepareArgumentsUncached(SingleMethodDesc method, Object[] args, Object languageContext, ToJavaNode toJavaNode, ConditionProfile isVarArgsProfile) { Class<?>[] types = method.getParameterTypes(); Type[] genericTypes = method.getGenericParameterTypes(); Object[] convertedArguments = new Object[args.length]; if (isVarArgsProfile.profile(method.isVarArgs()) && asVarArgs(args, method)) { int parameterCount = method.getParameterCount(); for (int i = 0; i < args.length; i++) { Class<?> expectedType = i < parameterCount - 1 ? types[i] : types[parameterCount - 1].getComponentType(); Type expectedGenericType = i < parameterCount - 1 ? genericTypes[i] : getGenericComponentType(genericTypes[parameterCount - 1]); convertedArguments[i] = toJavaNode.execute(args[i], expectedType, expectedGenericType, languageContext); } convertedArguments = createVarArgsArray(method, convertedArguments, parameterCount); } else { for (int i = 0; i < args.length; i++) { convertedArguments[i] = toJavaNode.execute(args[i], types[i], genericTypes[i], languageContext); } } return convertedArguments; }
@SuppressWarnings("unused") @ExplodeLoop @Specialization(guards = {"!method.isVarArgs()", "method == cachedMethod"}, limit = "LIMIT") Object doFixed(SingleMethodDesc method, Object obj, Object[] args, Object languageContext, @Cached("method") SingleMethodDesc cachedMethod, @Cached("createToJava(method.getParameterCount())") ToJavaNode[] toJavaNodes, @Cached("createClassProfile()") ValueProfile receiverProfile) { int arity = cachedMethod.getParameterCount(); if (args.length != arity) { throw ArityException.raise(arity, args.length); } Class<?>[] types = cachedMethod.getParameterTypes(); Type[] genericTypes = cachedMethod.getGenericParameterTypes(); Object[] convertedArguments = new Object[args.length]; for (int i = 0; i < toJavaNodes.length; i++) { convertedArguments[i] = toJavaNodes[i].execute(args[i], types[i], genericTypes[i], languageContext); } return doInvoke(cachedMethod, receiverProfile.profile(obj), convertedArguments, languageContext); }
@SuppressWarnings("unused") @Specialization(guards = {"method.isVarArgs()", "method == cachedMethod"}, limit = "LIMIT") Object doVarArgs(SingleMethodDesc method, Object obj, Object[] args, Object languageContext, @Cached("method") SingleMethodDesc cachedMethod, @Cached("create()") ToJavaNode toJavaNode, @Cached("createClassProfile()") ValueProfile receiverProfile) { int parameterCount = cachedMethod.getParameterCount(); int minArity = parameterCount - 1; if (args.length < minArity) { throw ArityException.raise(minArity, args.length); } Class<?>[] types = cachedMethod.getParameterTypes(); Type[] genericTypes = cachedMethod.getGenericParameterTypes(); Object[] convertedArguments = new Object[args.length]; for (int i = 0; i < minArity; i++) { convertedArguments[i] = toJavaNode.execute(args[i], types[i], genericTypes[i], languageContext); } if (asVarArgs(args, cachedMethod)) { for (int i = minArity; i < args.length; i++) { Class<?> expectedType = types[minArity].getComponentType(); Type expectedGenericType = getGenericComponentType(genericTypes[minArity]); convertedArguments[i] = toJavaNode.execute(args[i], expectedType, expectedGenericType, languageContext); } convertedArguments = createVarArgsArray(cachedMethod, convertedArguments, parameterCount); } else { convertedArguments[minArity] = toJavaNode.execute(args[minArity], types[minArity], genericTypes[minArity], languageContext); } return doInvoke(cachedMethod, receiverProfile.profile(obj), convertedArguments, languageContext); }
@SuppressWarnings("unused") @ExplodeLoop @Specialization(guards = {"method == cachedMethod", "checkArgTypes(args, cachedArgTypes, toJavaNode, asVarArgs)"}, limit = "LIMIT") Object doOverloadedCached(OverloadedMethodDesc method, Object obj, Object[] args, Object languageContext, @Cached("method") OverloadedMethodDesc cachedMethod, @Cached("create()") ToJavaNode toJavaNode, @Cached(value = "createArgTypesArray(args)", dimensions = 1) Type[] cachedArgTypes, @Cached("selectOverload(method, args, languageContext, toJavaNode, cachedArgTypes)") SingleMethodDesc overload, @Cached("asVarArgs(args, overload)") boolean asVarArgs, @Cached("createClassProfile()") ValueProfile receiverProfile) { assert overload == selectOverload(method, args, languageContext, toJavaNode); Class<?>[] types = overload.getParameterTypes(); Type[] genericTypes = overload.getGenericParameterTypes(); Object[] convertedArguments = new Object[cachedArgTypes.length]; if (asVarArgs) { assert overload.isVarArgs(); int parameterCount = overload.getParameterCount(); for (int i = 0; i < cachedArgTypes.length; i++) { Class<?> expectedType = i < parameterCount - 1 ? types[i] : types[parameterCount - 1].getComponentType(); Type expectedGenericType = i < parameterCount - 1 ? genericTypes[i] : getGenericComponentType(genericTypes[parameterCount - 1]); convertedArguments[i] = toJavaNode.execute(args[i], expectedType, expectedGenericType, languageContext); } convertedArguments = createVarArgsArray(overload, convertedArguments, parameterCount); } else { for (int i = 0; i < cachedArgTypes.length; i++) { convertedArguments[i] = toJavaNode.execute(args[i], types[i], genericTypes[i], languageContext); } } return doInvoke(overload, receiverProfile.profile(obj), convertedArguments, languageContext); }