# HG changeset patch # User Christos Kotselidis # Date 1365884164 -7200 # Node ID 368ed6c6a02b838cbaef264043f5c4173d3cf28d # Parent 0c8ec85fa01343de519805ecde93e511ab836505# Parent 3495149b9531d8a1b91b9f9422d30bbf9825a576 Merge diff -r 0c8ec85fa013 -r 368ed6c6a02b 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 Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Sat Apr 13 22:16:04 2013 +0200 @@ -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 0c8ec85fa013 -r 368ed6c6a02b 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 Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Sat Apr 13 22:16:04 2013 +0200 @@ -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 0c8ec85fa013 -r 368ed6c6a02b 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 Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Sat Apr 13 22:16:04 2013 +0200 @@ -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 0c8ec85fa013 -r 368ed6c6a02b graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java Sat Apr 13 22:16:04 2013 +0200 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug.test; + +import java.io.*; + +import org.junit.*; + +import com.oracle.graal.debug.*; + +public class DebugHistogramTest { + + @Test + public void testEmptyHistogram() { + DebugHistogram histogram = Debug.createHistogram("TestHistogram"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + histogram.print(new PrintStream(outputStream)); + Assert.assertEquals("TestHistogram is empty.\n", outputStream.toString()); + } + + @Test + public void testSingleEntryHistogram() { + DebugHistogram histogram = Debug.createHistogram("TestHistogram"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + histogram.add(new Integer(1)); + histogram.add(new Integer(1)); + histogram.print(new PrintStream(outputStream)); + String[] lines = outputStream.toString().split("\n"); + Assert.assertEquals(4, lines.length); + Assert.assertEquals("TestHistogram has 1 unique elements and 2 total elements:", lines[0]); + Assert.assertEquals( + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + lines[1]); + Assert.assertEquals( + "| 1 | 2 | ==================================================================================================== |", + lines[2]); + Assert.assertEquals( + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + lines[3]); + } + + @Test + public void testMultipleEntryHistogram() { + DebugHistogram histogram = Debug.createHistogram("TestHistogram"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + histogram.add(new Integer(1)); + histogram.add(new Integer(2)); + histogram.add(new Integer(2)); + histogram.print(new PrintStream(outputStream)); + String[] lines = outputStream.toString().split("\n"); + Assert.assertEquals(5, lines.length); + Assert.assertEquals("TestHistogram has 2 unique elements and 3 total elements:", lines[0]); + Assert.assertEquals( + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + lines[1]); + Assert.assertEquals( + "| 2 | 2 | ==================================================================================================== |", + lines[2]); + Assert.assertEquals( + "| 1 | 1 | ================================================== |", + lines[3]); + Assert.assertEquals( + "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", + lines[4]); + } + + @Test + public void testTooLongValueString() { + DebugHistogram histogram = Debug.createHistogram("TestHistogram"); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + histogram.add("MyCustomValue"); + histogram.print(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10); + String[] lines = outputStream.toString().split("\n"); + Assert.assertEquals(4, lines.length); + Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]); + Assert.assertEquals("----------------------------------------", lines[1]); + Assert.assertEquals("| MyCusto... | 1 | ========== |", lines[2]); + Assert.assertEquals("----------------------------------------", lines[3]); + } +} diff -r 0c8ec85fa013 -r 368ed6c6a02b graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat Apr 13 22:16:04 2013 +0200 @@ -189,6 +189,10 @@ } } + public static DebugHistogram createHistogram(String name) { + return new DebugHistogramImpl(name); + } + public static DebugConfig fixedConfig(final boolean isLogEnabled, final boolean isDumpEnabled, final boolean isMeterEnabled, final boolean isTimerEnabled, final Collection dumpHandlers, final PrintStream output) { return new DebugConfig() { diff -r 0c8ec85fa013 -r 368ed6c6a02b graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java Sat Apr 13 22:16:04 2013 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug; + +import java.io.*; + +public interface DebugHistogram { + + String getName(); + + void add(Object value); + + void print(PrintStream os); + + void print(PrintStream os, int limit, int nameSize, int barSize); +} diff -r 0c8ec85fa013 -r 368ed6c6a02b graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java Sat Apr 13 22:16:04 2013 +0200 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug.internal; + +import java.io.*; +import java.util.*; + +import com.oracle.graal.debug.*; + +public class DebugHistogramImpl implements DebugHistogram { + + public static final int NumberSize = 10; + public static final int DefaultNameSize = 50; + public static final int DefaultBarSize = 100; + private final String name; + private HashMap map = new HashMap<>(); + + public DebugHistogramImpl(String name) { + this.name = name; + } + + public void add(Object value) { + if (!map.containsKey(value)) { + map.put(value, 1); + } else { + map.put(value, map.get(value) + 1); + } + } + + @Override + public String getName() { + return name; + } + + @Override + public void print(PrintStream os) { + print(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize); + } + + public void print(PrintStream os, int limit, int nameSize, int barSize) { + + List list = new ArrayList<>(map.keySet()); + if (list.size() == 0) { + // No elements in the histogram. + os.printf("%s is empty.\n", name); + return; + } + + // Sort from highest to smallest. + Collections.sort(list, new Comparator() { + + @Override + public int compare(Object o1, Object o2) { + return map.get(o2) - map.get(o1); + } + }); + + // Sum up the total number of elements. + int total = 0; + for (Object o : list) { + total += map.get(o); + } + + // Print header. + os.printf("%s has %d unique elements and %d total elements:\n", name, list.size(), total); + + int max = map.get(list.get(0)); + final int lineSize = nameSize + NumberSize + barSize + 10; + printLine(os, '-', lineSize); + String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n"; + for (int i = 0; i < list.size() && i < limit; ++i) { + Object o = list.get(i); + int value = map.get(o); + char[] bar = new char[(int) (((double) value / (double) max) * barSize)]; + Arrays.fill(bar, '='); + String objectString = o.toString(); + if (objectString.length() > nameSize) { + objectString = objectString.substring(0, nameSize - 3) + "..."; + } + os.printf(formatString, objectString, value, new String(bar)); + } + printLine(os, '-', lineSize); + } + + private static void printLine(PrintStream printStream, char c, int lineSize) { + char[] charArr = new char[lineSize]; + Arrays.fill(charArr, c); + printStream.printf("%s\n", new String(charArr)); + } +} diff -r 0c8ec85fa013 -r 368ed6c6a02b 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 Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Sat Apr 13 22:16:04 2013 +0200 @@ -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 0c8ec85fa013 -r 368ed6c6a02b 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 Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Sat Apr 13 22:16:04 2013 +0200 @@ -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 0c8ec85fa013 -r 368ed6c6a02b 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 Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedPrimitiveType.java Sat Apr 13 22:16:04 2013 +0200 @@ -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 0c8ec85fa013 -r 368ed6c6a02b graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Sat Apr 13 22:16:04 2013 +0200 @@ -50,7 +50,7 @@ public interface CustomCanonicalizer { - ValueNode canonicalize(Node node); + ValueNode canonicalize(ValueNode node); } @Override @@ -187,11 +187,9 @@ public boolean tryCanonicalize(final Node node, final StructuredGraph graph) { boolean result = baseTryCanonicalize(node, graph); - if (!result && customCanonicalizer != null) { - ValueNode canonical = customCanonicalizer.canonicalize(node); - if (canonical == node && customCanonicalizer != null) { - canonical = customCanonicalizer.canonicalize(node); - } + if (!result && customCanonicalizer != null && node instanceof ValueNode) { + ValueNode valueNode = (ValueNode) node; + ValueNode canonical = customCanonicalizer.canonicalize(valueNode); result = performReplacement(node, graph, canonical); } return result; diff -r 0c8ec85fa013 -r 368ed6c6a02b 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 Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Sat Apr 13 22:16:04 2013 +0200 @@ -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,63 @@ 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) { - if (!type.isPrimitive()) { - return type; - } + private Node createNodeInstance(ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, ResolvedJavaType returnType, boolean setStampFromReturnType, Constant[] nodeConstructorArguments) { + ResolvedJavaMethod constructor = null; + Constant[] arguments = null; - 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; - } - - static final int VARARGS = 0x00000080; + for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) { + Constant[] match = match(c, parameterTypes, nodeConstructorArguments); - 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; + 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); } - - 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; - } - } - 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 +220,58 @@ } } - /** - * 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; + for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { + if (!parameterTypes[i].equals(componentType)) { + 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) { diff -r 0c8ec85fa013 -r 368ed6c6a02b graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Sat Apr 13 00:33:37 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Sat Apr 13 22:16:04 2013 +0200 @@ -60,8 +60,8 @@ public static class SnippetInfo { protected final ResolvedJavaMethod method; - protected final ConstantParameter[] constantParameters; - protected final VarargsParameter[] varargsParameters; + protected final boolean[] constantParameters; + protected final boolean[] varargsParameters; /** * The parameter names, taken from the local variables table. Only used for assertion @@ -74,11 +74,11 @@ assert Modifier.isStatic(method.getModifiers()) : "snippet method must be static: " + MetaUtil.format("%H.%n", method); int count = method.getSignature().getParameterCount(false); - constantParameters = new ConstantParameter[count]; - varargsParameters = new VarargsParameter[count]; + constantParameters = new boolean[count]; + varargsParameters = new boolean[count]; for (int i = 0; i < count; i++) { - constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method); - varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); + constantParameters[i] = MetaUtil.getParameterAnnotation(ConstantParameter.class, i, method) != null; + varargsParameters[i] = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method) != null; assert !isConstantParameter(i) || !isVarargsParameter(i) : "Parameter cannot be annotated with both @" + ConstantParameter.class.getSimpleName() + " and @" + VarargsParameter.class.getSimpleName(); @@ -109,11 +109,11 @@ } public boolean isConstantParameter(int paramIdx) { - return constantParameters[paramIdx] != null; + return constantParameters[paramIdx]; } public boolean isVarargsParameter(int paramIdx) { - return varargsParameters[paramIdx] != null; + return varargsParameters[paramIdx]; } } diff -r 0c8ec85fa013 -r 368ed6c6a02b mx/projects --- a/mx/projects Sat Apr 13 00:33:37 2013 +0200 +++ b/mx/projects Sat Apr 13 22:16:04 2013 +0200 @@ -155,6 +155,13 @@ project@com.oracle.graal.debug@checkstyle=com.oracle.graal.graph project@com.oracle.graal.debug@javaCompliance=1.7 +# graal.debug.test +project@com.oracle.graal.debug.test@subDir=graal +project@com.oracle.graal.debug.test@sourceDirs=src +project@com.oracle.graal.debug.test@dependencies=JUNIT,com.oracle.graal.debug +project@com.oracle.graal.debug.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.debug.test@javaCompliance=1.7 + # graal.lir project@com.oracle.graal.lir@subDir=graal project@com.oracle.graal.lir@sourceDirs=src