# HG changeset patch # User Christian Wimmer # Date 1365808088 25200 # Node ID d24955427b0b6ef5eddd28a5ad31145ed98e24c0 # Parent ed81c74f92ff3622283c93094f8cad3c19934b50 Remove MetaUtil.getMirrorOrFail; Add necessary functionality to the Graal API so that all previous usages of java.lang.Class can now use ResolvedJavaType diff -r ed81c74f92ff -r d24955427b0b graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri Apr 12 16:05:56 2013 -0700 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri Apr 12 16:08:08 2013 -0700 @@ -47,6 +47,17 @@ } /** + * Calls {@link JavaType#resolve(ResolvedJavaType)} on an array of types. + */ + public static ResolvedJavaType[] resolveJavaTypes(JavaType[] types, ResolvedJavaType accessingClass) { + ResolvedJavaType[] result = new ResolvedJavaType[types.length]; + for (int i = 0; i < result.length; i++) { + result[i] = types[i].resolve(accessingClass); + } + return result; + } + + /** * Calls {@link MetaAccessProvider#lookupJavaType(Class)} on an array of classes. */ public static ResolvedJavaType[] lookupJavaTypes(MetaAccessProvider metaAccess, Class[] classes) { @@ -58,54 +69,6 @@ } /** - * Gets the {@link Class} mirror for a given resolved type. - * - * @param type the type for which the Java mirror is requested - * @param loader class loader from which the class must be loaded (null means use the class - * loader of the {@link MetaUtil} class) - * @return the mirror for {@code type} - * @throws NoClassDefFoundError if the mirror is not available - */ - public static Class getMirrorOrFail(ResolvedJavaType type, ClassLoader loader) throws NoClassDefFoundError { - ResolvedJavaType elementalType = getElementalType(type); - Class elementalClass; - if (elementalType.isPrimitive()) { - elementalClass = elementalType.getKind().toJavaClass(); - } else { - try { - elementalClass = Class.forName(toJavaName(elementalType), true, loader); - } catch (ClassNotFoundException e) { - throw (NoClassDefFoundError) new NoClassDefFoundError().initCause(e); - } - } - if (type.isArray()) { - ResolvedJavaType t = type; - while (t.getComponentType() != null) { - elementalClass = Array.newInstance(elementalClass, 0).getClass(); - t = t.getComponentType(); - } - } - assert elementalClass != null : toJavaName(type); - return elementalClass; - } - - /** - * Gets the {@link Class} mirror for a given resolved type. - * - * @param type the type for which the Java mirror is requested - * @param loader class loader from which the class must be loaded (null means use the class - * loader of the {@link MetaUtil} class) - * @return the mirror for {@code type} or null if it is not available - */ - public static Class getMirror(ResolvedJavaType type, ClassLoader loader) { - try { - return getMirrorOrFail(type, loader); - } catch (NoClassDefFoundError e) { - return null; - } - } - - /** * Gets the elemental type for a given type. The elemental type of an array type is the * corresponding zero dimensional (e.g., the elemental type of {@code int[][][]} is {@code int} * ). A non-array type is its own elemental type. diff -r ed81c74f92ff -r d24955427b0b graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Fri Apr 12 16:05:56 2013 -0700 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Fri Apr 12 16:08:08 2013 -0700 @@ -180,4 +180,26 @@ * Returns the localvariable table of this method. */ LocalVariableTable getLocalVariableTable(); + + /** + * Invokes the underlying method represented by this object, on the specified object with the + * specified parameters. This method is similar to a reflective method invocation by + * {@link Method#invoke}. + * + * @param receiver The receiver for the invocation, or {@code null} if it is a static method. + * @param arguments The arguments for the invocation. + * @return The value returned by the method invocation, or {@code null} if the return type is + * {@code void}. + */ + Constant invoke(Constant receiver, Constant[] arguments); + + /** + * Uses the constructor represented by this object to create and initialize a new instance of + * the constructor's declaring class, with the specified initialization parameters. This method + * is similar to a reflective instantiation by {@link Constructor#newInstance}. + * + * @param arguments The arguments for the constructor. + * @return The newly created and initialized object. + */ + Constant newInstance(Constant[] arguments); } diff -r ed81c74f92ff -r d24955427b0b graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Fri Apr 12 16:05:56 2013 -0700 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Fri Apr 12 16:08:08 2013 -0700 @@ -274,4 +274,22 @@ * Returns the enclosing type of this type, if it exists, or {@code null}. */ ResolvedJavaType getEnclosingType(); + + /** + * Returns an array reflecting all the constructors declared by this type. This method is + * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors. + */ + ResolvedJavaMethod[] getDeclaredConstructors(); + + /** + * Returns an array reflecting all the methods declared by this type. This method is similar to + * {@link Class#getDeclaredMethods()} in terms of returned methods. + */ + ResolvedJavaMethod[] getDeclaredMethods(); + + /** + * Creates a new array with this type as the component type and the specified length. This + * method is similar to {@link Array#newInstance(Class, int)}. + */ + Constant newArray(int length); } diff -r ed81c74f92ff -r d24955427b0b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 12 16:05:56 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 12 16:08:08 2013 -0700 @@ -367,4 +367,46 @@ HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); return unsafe.getByte(metaspaceMethod + config.methodIntrinsicIdOffset) & 0xff; } + + @Override + public Constant invoke(Constant receiver, Constant[] arguments) { + assert !isConstructor(); + Method javaMethod = toJava(); + javaMethod.setAccessible(true); + + Object[] objArguments = new Object[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + objArguments[i] = arguments[i].asBoxedValue(); + } + Object objReceiver = receiver != null ? receiver.asObject() : null; + + try { + Object objResult = javaMethod.invoke(objReceiver, objArguments); + return javaMethod.getReturnType() == void.class ? null : Constant.forBoxed(getSignature().getReturnKind(), objResult); + + } catch (IllegalAccessException | InvocationTargetException ex) { + throw new IllegalArgumentException(ex); + } + } + + @Override + public Constant newInstance(Constant[] arguments) { + assert isConstructor(); + Constructor javaConstructor = toJavaConstructor(); + javaConstructor.setAccessible(true); + + Object[] objArguments = new Object[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + objArguments[i] = arguments[i].asBoxedValue(); + } + + try { + Object objResult = javaConstructor.newInstance(objArguments); + assert objResult != null; + return Constant.forObject(objResult); + + } catch (IllegalAccessException | InvocationTargetException | InstantiationException ex) { + throw new IllegalArgumentException(ex); + } + } } diff -r ed81c74f92ff -r d24955427b0b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Apr 12 16:05:56 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Apr 12 16:08:08 2013 -0700 @@ -519,4 +519,31 @@ final Class encl = mirror().getEnclosingClass(); return encl == null ? null : fromClass(encl); } + + @Override + public ResolvedJavaMethod[] getDeclaredConstructors() { + Constructor[] constructors = javaMirror.getDeclaredConstructors(); + ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length]; + for (int i = 0; i < constructors.length; i++) { + result[i] = HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaConstructor(constructors[i]); + assert result[i].isConstructor(); + } + return result; + } + + @Override + public ResolvedJavaMethod[] getDeclaredMethods() { + Method[] methods = javaMirror.getDeclaredMethods(); + ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length]; + for (int i = 0; i < methods.length; i++) { + result[i] = HotSpotGraalRuntime.getInstance().getRuntime().lookupJavaMethod(methods[i]); + assert !result[i].isConstructor(); + } + return result; + } + + @Override + public Constant newArray(int length) { + return Constant.forObject(Array.newInstance(javaMirror, length)); + } } diff -r ed81c74f92ff -r d24955427b0b graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Fri Apr 12 16:05:56 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Fri Apr 12 16:08:08 2013 -0700 @@ -210,4 +210,19 @@ public ResolvedJavaType getEnclosingType() { return null; } + + @Override + public ResolvedJavaMethod[] getDeclaredConstructors() { + return new ResolvedJavaMethod[0]; + } + + @Override + public ResolvedJavaMethod[] getDeclaredMethods() { + return new ResolvedJavaMethod[0]; + } + + @Override + public Constant newArray(int length) { + return Constant.forObject(Array.newInstance(javaMirror, length)); + } } diff -r ed81c74f92ff -r d24955427b0b graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Apr 12 16:05:56 2013 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Fri Apr 12 16:08:08 2013 -0700 @@ -22,8 +22,6 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.api.meta.MetaUtil.*; - import java.lang.reflect.*; import java.util.*; @@ -67,41 +65,26 @@ } } - public static Class[] signatureToTypes(Signature signature, JavaType receiverType, ResolvedJavaType accessingClass) { - int count = signature.getParameterCount(receiverType != null); - Class[] result = new Class[count]; - int j = 0; - if (receiverType != null) { - result[0] = getMirrorOrFail(receiverType.resolve(accessingClass), Thread.currentThread().getContextClassLoader()); - j = 1; - } - for (int i = 0; i + j < result.length; ++i) { - result[i + j] = getMirrorOrFail(signature.getParameterType(i, accessingClass).resolve(accessingClass), Thread.currentThread().getContextClassLoader()); - } - return result; - } - private boolean tryIntrinsify(Invoke invoke, List cleanUpReturnList) { ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod(); NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class); ResolvedJavaType declaringClass = target.getDeclaringClass(); - JavaType receiverType = invoke.methodCallTarget().isStatic() ? null : declaringClass; if (intrinsic != null) { assert target.getAnnotation(Fold.class) == null; + assert Modifier.isStatic(target.getModifiers()) : "node intrinsic must be static: " + target; - // TODO mjj non-static intrinsic? - Class[] parameterTypes = signatureToTypes(target.getSignature(), null, declaringClass); + ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass); ResolvedJavaType returnType = target.getSignature().getReturnType(declaringClass).resolve(declaringClass); // Prepare the arguments for the reflective constructor call on the node class. - Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false); + Constant[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false); if (nodeConstructorArguments == null) { return false; } // Create the new node instance. - Class c = getNodeClass(target, intrinsic); - Node newInstance = createNodeInstance(runtime, c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments); + ResolvedJavaType c = getNodeClass(target, intrinsic); + Node newInstance = createNodeInstance(c, parameterTypes, returnType, intrinsic.setStampFromReturnType(), nodeConstructorArguments); // Replace the invoke with the new node. invoke.asNode().graph().add(newInstance); @@ -110,23 +93,22 @@ // Clean up checkcast instructions inserted by javac if the return type is generic. cleanUpReturnList.add(newInstance); } else if (target.getAnnotation(Fold.class) != null) { - Class[] parameterTypes = signatureToTypes(target.getSignature(), receiverType, declaringClass); + ResolvedJavaType[] parameterTypes = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(target), declaringClass); // Prepare the arguments for the reflective method call - Object[] arguments = prepareArguments(invoke, parameterTypes, target, true); + Constant[] arguments = prepareArguments(invoke, parameterTypes, target, true); if (arguments == null) { return false; } - Object receiver = null; + Constant receiver = null; if (!invoke.methodCallTarget().isStatic()) { receiver = arguments[0]; - arguments = Arrays.asList(arguments).subList(1, arguments.length).toArray(); - parameterTypes = Arrays.asList(parameterTypes).subList(1, parameterTypes.length).toArray(new Class[parameterTypes.length - 1]); + arguments = Arrays.copyOfRange(arguments, 1, arguments.length); + parameterTypes = Arrays.copyOfRange(parameterTypes, 1, parameterTypes.length); } // Call the method - Constant constant = callMethod(target.getSignature().getReturnKind(), getMirrorOrFail(declaringClass, Thread.currentThread().getContextClassLoader()), target.getName(), parameterTypes, - receiver, arguments); + Constant constant = target.invoke(receiver, arguments); if (constant != null) { // Replace the invoke with the result of the call @@ -151,9 +133,9 @@ * @return the arguments for the reflective invocation or null if an argument of {@code invoke} * that is expected to be constant isn't */ - private Object[] prepareArguments(Invoke invoke, Class[] parameterTypes, ResolvedJavaMethod target, boolean folding) { + private Constant[] prepareArguments(Invoke invoke, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) { NodeInputList arguments = invoke.callTarget().arguments(); - Object[] reflectionCallArguments = new Object[arguments.size()]; + Constant[] reflectionCallArguments = new Constant[arguments.size()]; for (int i = 0; i < reflectionCallArguments.length; ++i) { int parameterIndex = i; if (!invoke.methodCallTarget().isStatic()) { @@ -168,130 +150,70 @@ Constant constant = constantNode.asConstant(); Object o = constant.asBoxedValue(); if (o instanceof Class) { - reflectionCallArguments[i] = runtime.lookupJavaType((Class) o); - parameterTypes[i] = ResolvedJavaType.class; + reflectionCallArguments[i] = Constant.forObject(runtime.lookupJavaType((Class) o)); + parameterTypes[i] = runtime.lookupJavaType(ResolvedJavaType.class); } else { - if (parameterTypes[i] == boolean.class) { - reflectionCallArguments[i] = Boolean.valueOf(constant.asInt() != 0); - } else if (parameterTypes[i] == byte.class) { - reflectionCallArguments[i] = Byte.valueOf((byte) constant.asInt()); - } else if (parameterTypes[i] == short.class) { - reflectionCallArguments[i] = Short.valueOf((short) constant.asInt()); - } else if (parameterTypes[i] == char.class) { - reflectionCallArguments[i] = Character.valueOf((char) constant.asInt()); + if (parameterTypes[i].getKind() == Kind.Boolean) { + reflectionCallArguments[i] = Constant.forObject(Boolean.valueOf(constant.asInt() != 0)); + } else if (parameterTypes[i].getKind() == Kind.Byte) { + reflectionCallArguments[i] = Constant.forObject(Byte.valueOf((byte) constant.asInt())); + } else if (parameterTypes[i].getKind() == Kind.Short) { + reflectionCallArguments[i] = Constant.forObject(Short.valueOf((short) constant.asInt())); + } else if (parameterTypes[i].getKind() == Kind.Char) { + reflectionCallArguments[i] = Constant.forObject(Character.valueOf((char) constant.asInt())); } else { - reflectionCallArguments[i] = o; + reflectionCallArguments[i] = constant; } } } else { - reflectionCallArguments[i] = argument; - parameterTypes[i] = ValueNode.class; + reflectionCallArguments[i] = Constant.forObject(argument); + parameterTypes[i] = runtime.lookupJavaType(ValueNode.class); } } return reflectionCallArguments; } - private static Class getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { - Class result = intrinsic.value(); - if (result == NodeIntrinsic.class) { - return getMirrorOrFail(target.getDeclaringClass(), Thread.currentThread().getContextClassLoader()); + private ResolvedJavaType getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { + ResolvedJavaType result; + if (intrinsic.value() == NodeIntrinsic.class) { + result = target.getDeclaringClass(); + } else { + result = runtime.lookupJavaType(intrinsic.value()); } - assert Node.class.isAssignableFrom(result); + assert runtime.lookupJavaType(ValueNode.class).isAssignableFrom(result); return result; } - private static Class asBoxedType(Class type) { + private ResolvedJavaType asBoxedType(ResolvedJavaType type) { if (!type.isPrimitive()) { return type; } - - if (Boolean.TYPE == type) { - return Boolean.class; - } - if (Character.TYPE == type) { - return Character.class; - } - if (Byte.TYPE == type) { - return Byte.class; - } - if (Short.TYPE == type) { - return Short.class; - } - if (Integer.TYPE == type) { - return Integer.class; - } - if (Long.TYPE == type) { - return Long.class; - } - if (Float.TYPE == type) { - return Float.class; - } - assert Double.TYPE == type; - return Double.class; + return runtime.lookupJavaType(type.getKind().toBoxedJavaClass()); } - static final int VARARGS = 0x00000080; + private Node createNodeInstance(ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType, Constant[] nodeConstructorArguments) { + ResolvedJavaMethod constructor = null; + Constant[] arguments = null; - private static Node createNodeInstance(MetaAccessProvider runtime, Class nodeClass, Class[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType, - Object[] nodeConstructorArguments) { - Object[] arguments = null; - Constructor constructor = null; - boolean needsMetaAccessProviderArgument = false; - nextConstructor: for (Constructor c : nodeClass.getDeclaredConstructors()) { - needsMetaAccessProviderArgument = false; - Class[] signature = c.getParameterTypes(); - if (signature.length != 0 && signature[0] == MetaAccessProvider.class) { - // Chop off the MetaAccessProvider first parameter - signature = Arrays.copyOfRange(signature, 1, signature.length); - needsMetaAccessProviderArgument = true; - } - if ((c.getModifiers() & VARARGS) != 0) { - int fixedArgs = signature.length - 1; - if (parameterTypes.length < fixedArgs) { - continue nextConstructor; - } + for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) { + Constant[] match = match(c, parameterTypes, nodeConstructorArguments); - for (int i = 0; i < fixedArgs; i++) { - if (!parameterTypes[i].equals(signature[i])) { - continue nextConstructor; - } - } - - Class componentType = signature[fixedArgs].getComponentType(); - assert componentType != null : "expected last parameter of varargs constructor " + c + " to be an array type"; - Class boxedType = asBoxedType(componentType); - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { - if (!boxedType.isInstance(nodeConstructorArguments[i])) { - continue nextConstructor; - } + if (match != null) { + if (constructor == null) { + constructor = c; + arguments = match; + } else { + throw new GraalInternalError("Found multiple constructors in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes) + ": " + constructor + ", " + c); } - arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1); - int varargsLength = nodeConstructorArguments.length - fixedArgs; - Object varargs = Array.newInstance(componentType, varargsLength); - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { - Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i]); - } - arguments[fixedArgs] = varargs; - constructor = c; - break; - } else if (Arrays.equals(parameterTypes, signature)) { - arguments = nodeConstructorArguments; - constructor = c; - break; } } if (constructor == null) { throw new GraalInternalError("Could not find constructor in " + nodeClass + " compatible with signature " + Arrays.toString(parameterTypes)); } - if (needsMetaAccessProviderArgument) { - Object[] copy = new Object[arguments.length + 1]; - System.arraycopy(arguments, 0, copy, 1, arguments.length); - copy[0] = runtime; - arguments = copy; - } - constructor.setAccessible(true); + try { - ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments); + ValueNode intrinsicNode = (ValueNode) constructor.newInstance(arguments).asObject(); + if (setStampFromReturnType) { if (returnType.getKind() == Kind.Object) { intrinsicNode.setStamp(StampFactory.declared(returnType)); @@ -305,26 +227,59 @@ } } - /** - * Calls a Java method via reflection. - */ - private static Constant callMethod(Kind returnKind, Class holder, String name, Class[] parameterTypes, Object receiver, Object[] arguments) { - Method method; - try { - method = holder.getDeclaredMethod(name, parameterTypes); - method.setAccessible(true); - } catch (Exception e) { - throw new RuntimeException(e); + private Constant[] match(ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Constant[] nodeConstructorArguments) { + Constant[] arguments = null; + boolean needsMetaAccessProviderArgument = false; + + ResolvedJavaType[] signature = MetaUtil.resolveJavaTypes(MetaUtil.signatureToTypes(c.getSignature(), null), c.getDeclaringClass()); + if (signature.length != 0 && signature[0].equals(runtime.lookupJavaType(MetaAccessProvider.class))) { + // Chop off the MetaAccessProvider first parameter + signature = Arrays.copyOfRange(signature, 1, signature.length); + needsMetaAccessProviderArgument = true; } - try { - Object result = method.invoke(receiver, arguments); - if (result == null) { + + if (Arrays.equals(parameterTypes, signature)) { + // Exact match + arguments = nodeConstructorArguments; + + } else if (signature.length > 0 && signature[signature.length - 1].isArray()) { + // Last constructor parameter is an array, so check if we have a vararg match + int fixedArgs = signature.length - 1; + if (parameterTypes.length < fixedArgs) { return null; } - return Constant.forBoxed(returnKind, result); - } catch (Exception e) { - throw new RuntimeException(e); + for (int i = 0; i < fixedArgs; i++) { + if (!parameterTypes[i].equals(signature[i])) { + return null; + } + } + + ResolvedJavaType componentType = signature[fixedArgs].getComponentType(); + assert componentType != null; + ResolvedJavaType boxedType = asBoxedType(componentType); + for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { + if (!boxedType.isAssignableFrom(runtime.lookupJavaType(nodeConstructorArguments[i]))) { + return null; + } + } + arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1); + arguments[fixedArgs] = componentType.newArray(nodeConstructorArguments.length - fixedArgs); + + Object varargs = arguments[fixedArgs].asObject(); + for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { + Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i].asBoxedValue()); + } + } else { + return null; } + + if (needsMetaAccessProviderArgument) { + Constant[] copy = new Constant[arguments.length + 1]; + System.arraycopy(arguments, 0, copy, 1, arguments.length); + copy[0] = Constant.forObject(runtime); + arguments = copy; + } + return arguments; } private static String sourceLocation(Node n) {