private static RuntimeException noApplicableOverloadsException(SingleMethodDesc[] overloads, Object[] args) { String message = String.format("no applicable overload found (overloads: %s, arguments: %s)", Arrays.toString(overloads), arrayToStringWithTypes(args)); return UnsupportedTypeException.raise(new IllegalArgumentException(message), args); }
private static boolean isAssignableFrom(Class<?> toType, Class<?> fromType) { if (toType.isAssignableFrom(fromType)) { return true; } boolean fromIsPrimitive = fromType.isPrimitive(); boolean toIsPrimitive = toType.isPrimitive(); Class<?> fromAsPrimitive = fromIsPrimitive ? fromType : boxedTypeToPrimitiveType(fromType); Class<?> toAsPrimitive = toIsPrimitive ? toType : boxedTypeToPrimitiveType(toType); if (toAsPrimitive != null && fromAsPrimitive != null) { if (toAsPrimitive == fromAsPrimitive) { assert fromIsPrimitive != toIsPrimitive; // primitive <: boxed return fromIsPrimitive; } else if (isWideningPrimitiveConversion(toAsPrimitive, fromAsPrimitive)) { // primitive|boxed <: wider primitive|boxed return true; } } else if (fromAsPrimitive == char.class && (toType == String.class || toType == CharSequence.class)) { // char|Character <: String|CharSequence return true; } else if (toAsPrimitive == null && fromAsPrimitive != null && toType.isAssignableFrom(primitiveTypeToBoxedType(fromAsPrimitive))) { // primitive|boxed <: Number et al return true; } return false; }
private static SingleMethodDesc findMostSpecificOverload(List<SingleMethodDesc> candidates, Object[] args, boolean varArgs) { assert candidates.size() >= 2; if (candidates.size() == 2) { int res = compareOverloads(candidates.get(0), candidates.get(1), args, varArgs); return res == 0 ? null : (res < 0 ? candidates.get(0) : candidates.get(1)); boolean add = false; for (Iterator<SingleMethodDesc> bestIt = best.iterator(); bestIt.hasNext();) { int res = compareOverloads(cand, bestIt.next(), args, varArgs); if (res == 0) { add = true;
private static boolean isSubtypeOf(Object argument, Class<?> parameterType) { Object value = argument; if (argument instanceof JavaObject) { value = ((JavaObject) argument).obj; } if (!parameterType.isPrimitive()) { return value == null || parameterType.isInstance(value); } else { if (value != null) { Class<?> boxedToPrimitive = boxedTypeToPrimitiveType(value.getClass()); if (boxedToPrimitive != null) { return (boxedToPrimitive == parameterType || isWideningPrimitiveConversion(parameterType, boxedToPrimitive)); } } } return false; }
boolean applicable = true; for (int i = 0; i < paramCount; i++) { if (!isSubtypeOf(args[i], parameterTypes[i]) && !toJavaNode.canConvert(args[i], parameterTypes[i], genericParameterTypes[i], languageContext, strict)) { applicable = false; break; boolean applicable = true; for (int i = 0; i < parameterCount - 1; i++) { if (!isSubtypeOf(args[i], parameterTypes[i]) && !toJavaNode.canConvert(args[i], parameterTypes[i], genericParameterTypes[i], languageContext, strict)) { applicable = false; break; if (!isSubtypeOf(args[i], varArgsComponentType) && !toJavaNode.canConvert(args[i], varArgsComponentType, varArgsGenericComponentType, languageContext, strict)) { applicable = false; break; fillArgTypesArray(args, cachedArgTypes, best, varArgs, applicableByArity); SingleMethodDesc best = findMostSpecificOverload(candidates, args, varArgs); if (best != null) { if (cachedArgTypes != null) { fillArgTypesArray(args, cachedArgTypes, best, varArgs, applicableByArity); throw ambiguousOverloadsException(candidates, args);
@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); }
@Specialization(replaces = "doOverloadedCached") Object doOverloadedUncached(OverloadedMethodDesc method, Object obj, Object[] args, Object languageContext, @Cached("create()") ToJavaNode toJavaNode, @Cached("createBinaryProfile()") ConditionProfile isVarArgsProfile) { SingleMethodDesc overload = selectOverload(method, args, languageContext, toJavaNode); Object[] convertedArguments = prepareArgumentsUncached(overload, args, languageContext, toJavaNode, isVarArgsProfile); return doInvoke(overload, 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; }
for (int i = 0; i < args.length; i++) { Object arg = args[i]; Class<?> targetType = getParameterType(selected.getParameterTypes(), i, varArgs); continue; Class<?> paramType = getParameterType(other.getParameterTypes(), i, varArgs); if (paramType == targetType) { continue; if ((ToJavaNode.isAssignableFromTrufflePrimitiveType(paramType) || ToJavaNode.isAssignableFromTrufflePrimitiveType(targetType)) && isAssignableFrom(targetType, paramType)) { otherPossibleTypes.add(paramType); assert checkArgTypes(args, cachedArgTypes, ToJavaNode.create(), false) : Arrays.toString(cachedArgTypes);
@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 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 ExecuteMethodNode executeMethod() { if (executeMethod == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); executeMethod = insert(ExecuteMethodNode.create()); } return executeMethod; }
@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); }
public Object access(JavaObject receiver, Object[] args) { if (TruffleOptions.AOT) { throw UnsupportedMessageException.raise(EXECUTE); } if (receiver.obj != null && !receiver.isClass()) { JavaMethodDesc method = lookupFunctionalInterfaceMethod(receiver); if (method != null) { if (doExecute == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); doExecute = insert(ExecuteMethodNode.create()); } return doExecute.execute(method, receiver.obj, args, receiver.languageContext); } } throw UnsupportedMessageException.raise(EXECUTE); }
private ExecuteMethodNode executeMethod() { if (executeMethod == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); executeMethod = insert(ExecuteMethodNode.create()); } return executeMethod; } }
private static RuntimeException ambiguousOverloadsException(List<SingleMethodDesc> candidates, Object[] args) { String message = String.format("Multiple applicable overloads found for method name %s (candidates: %s, arguments: %s)", candidates.get(0).getName(), candidates, arrayToStringWithTypes(args)); return UnsupportedTypeException.raise(new IllegalArgumentException(message), args); }