# HG changeset patch # User Lukas Stadler # Date 1369386139 -7200 # Node ID 097630441baf2d015dc652c0d7362164ae6b86e6 # Parent b49fdcee6cb0e2c7f63c17368b367c9539c174d2# Parent d552919fbb05a8f080abde767df1837170907cab Merge diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Fri May 24 11:02:19 2013 +0200 @@ -492,6 +492,9 @@ * @return the code annotations or {@code null} if there are none */ public List getAnnotations() { + if (annotations == null) { + return Collections.emptyList(); + } return annotations; } diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/MethodUniverse.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/MethodUniverse.java Fri May 24 11:02:19 2013 +0200 @@ -0,0 +1,49 @@ +/* + * 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.api.meta.test; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; + +/** + * Context for method related api.meta tests. + */ +public class MethodUniverse extends TypeUniverse { + + public final Map methods = new HashMap<>(); + public final Map constructors = new HashMap<>(); + + public MethodUniverse() { + for (Class c : classes) { + for (Method m : c.getDeclaredMethods()) { + ResolvedJavaMethod method = runtime.lookupJavaMethod(m); + methods.put(m, method); + } + for (Constructor m : c.getDeclaredConstructors()) { + constructors.put(m, runtime.lookupJavaConstructor(m)); + } + } + } +} diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java Fri May 24 11:02:19 2013 +0200 @@ -30,7 +30,7 @@ /** * Tests for {@link BytecodeDisassemblerProvider}. */ -public class TestBytecodeDisassemblerProvider { +public class TestBytecodeDisassemblerProvider extends MethodUniverse { public TestBytecodeDisassemblerProvider() { } @@ -43,7 +43,7 @@ BytecodeDisassemblerProvider dis = Graal.getRuntime().getCapability(BytecodeDisassemblerProvider.class); if (dis != null) { int count = 0; - for (ResolvedJavaMethod m : TestJavaMethod.methods.values()) { + for (ResolvedJavaMethod m : methods.values()) { String disasm1 = dis.disassemble(m); String disasm2 = dis.disassemble(m); if (disasm1 == null) { diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaMethod.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaMethod.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaMethod.java Fri May 24 11:02:19 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.api.meta.test; -import static com.oracle.graal.api.meta.test.TestMetaAccessProvider.*; import static org.junit.Assert.*; import java.lang.reflect.*; @@ -35,24 +34,7 @@ /** * Tests for {@link JavaMethod}. */ -public class TestJavaMethod { - - public TestJavaMethod() { - } - - public static final Map methods = new HashMap<>(); - public static final Map constructors = new HashMap<>(); - static { - for (Class c : classes) { - for (Method m : c.getDeclaredMethods()) { - ResolvedJavaMethod method = runtime.lookupJavaMethod(m); - methods.put(m, method); - } - for (Constructor m : c.getDeclaredConstructors()) { - constructors.put(m, runtime.lookupJavaConstructor(m)); - } - } - } +public class TestJavaMethod extends MethodUniverse { @Test public void getNameTest() { diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestJavaType.java Fri May 24 11:02:19 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.api.meta.test; -import static com.oracle.graal.api.meta.test.TestMetaAccessProvider.*; import static org.junit.Assert.*; import org.junit.*; @@ -32,7 +31,7 @@ /** * Tests for {@link JavaType}. */ -public class TestJavaType { +public class TestJavaType extends TypeUniverse { public TestJavaType() { } diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java Fri May 24 11:02:19 2013 +0200 @@ -25,125 +25,16 @@ import static com.oracle.graal.api.meta.MetaUtil.*; import static org.junit.Assert.*; -import java.io.*; import java.lang.reflect.*; -import java.util.*; import org.junit.*; -import sun.misc.Unsafe; - import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; /** * Tests for {@link MetaAccessProvider}. */ -public class TestMetaAccessProvider { - - public static final Unsafe unsafe; - static { - Unsafe theUnsafe = null; - try { - theUnsafe = Unsafe.getUnsafe(); - } catch (Exception e) { - try { - Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeField.setAccessible(true); - theUnsafe = (Unsafe) theUnsafeField.get(null); - } catch (Exception e1) { - throw (InternalError) new InternalError("unable to initialize unsafe").initCause(e1); - } - } - unsafe = theUnsafe; - } - - public TestMetaAccessProvider() { - } - - public static final MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class); - public static final Collection> classes = new HashSet<>(); - public static final Map, Class> arrayClasses = new HashMap<>(); - - public static synchronized Class getArrayClass(Class componentType) { - Class arrayClass = arrayClasses.get(componentType); - if (arrayClass == null) { - arrayClass = Array.newInstance(componentType, 0).getClass(); - arrayClasses.put(componentType, arrayClass); - } - return arrayClass; - } - - public static int dimensions(Class c) { - if (c.getComponentType() != null) { - return 1 + dimensions(c.getComponentType()); - } - return 0; - } - - private static void addClass(Class c) { - if (classes.add(c)) { - if (c.getSuperclass() != null) { - addClass(c.getSuperclass()); - } - for (Class sc : c.getInterfaces()) { - addClass(sc); - } - for (Class dc : c.getDeclaredClasses()) { - addClass(dc); - } - for (Method m : c.getDeclaredMethods()) { - addClass(m.getReturnType()); - for (Class p : m.getParameterTypes()) { - addClass(p); - } - } - - if (c != void.class && dimensions(c) < 2) { - Class arrayClass = Array.newInstance(c, 0).getClass(); - arrayClasses.put(c, arrayClass); - addClass(arrayClass); - } - } - } - - static { - Class[] initialClasses = {void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, ClassLoader.class, - String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class, HashMap.class, - LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class}; - for (Class c : initialClasses) { - addClass(c); - } - } - - public static final List constants = new ArrayList<>(); - static { - for (Field f : Constant.class.getDeclaredFields()) { - int mods = f.getModifiers(); - if (f.getType() == Constant.class && Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) { - try { - Constant c = (Constant) f.get(null); - if (c != null) { - constants.add(c); - } - } catch (Exception e) { - } - } - } - for (Class c : classes) { - if (c != void.class && !c.isArray()) { - constants.add(Constant.forObject(Array.newInstance(c, 42))); - } - } - constants.add(Constant.forObject(new ArrayList<>())); - constants.add(Constant.forObject(new IdentityHashMap<>())); - constants.add(Constant.forObject(new LinkedHashMap<>())); - constants.add(Constant.forObject(new TreeMap<>())); - constants.add(Constant.forObject(new ArrayDeque<>())); - constants.add(Constant.forObject(new LinkedList<>())); - constants.add(Constant.forObject("a string")); - constants.add(Constant.forObject(42)); - } +public class TestMetaAccessProvider extends TypeUniverse { @Test public void lookupJavaTypeTest() { diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Fri May 24 11:02:19 2013 +0200 @@ -22,10 +22,10 @@ */ package com.oracle.graal.api.meta.test; -import static com.oracle.graal.api.meta.test.TestJavaMethod.*; import static java.lang.reflect.Modifier.*; import static org.junit.Assert.*; +import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; @@ -36,7 +36,7 @@ /** * Tests for {@link ResolvedJavaMethod}. */ -public class TestResolvedJavaMethod { +public class TestResolvedJavaMethod extends MethodUniverse { public TestResolvedJavaMethod() { } @@ -94,21 +94,6 @@ } @Test - public void getCompilationComplexityTest() { - // TODO - } - - @Test - public void getMaxLocalsTest() { - // TODO - } - - @Test - public void getMaxStackSizeTest() { - // TODO - } - - @Test public void getModifiersTest() { for (Map.Entry e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); @@ -148,52 +133,167 @@ @Test public void canBeStaticallyBoundTest() { - // TODO + for (Map.Entry e : methods.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers())); + } + for (Map.Entry e : constructors.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + assertEquals(m.canBeStaticallyBound(), canBeStaticallyBound(e.getKey().getModifiers())); + } } - @Test - public void getExceptionHandlersTest() { - // TODO + private static boolean canBeStaticallyBound(int modifiers) { + return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers)) && !Modifier.isAbstract(modifiers); + } + + private static String methodWithExceptionHandlers(String p1, Object o2) { + try { + return p1.substring(100) + o2.toString(); + } catch (IndexOutOfBoundsException e) { + e.printStackTrace(); + } catch (NullPointerException e) { + e.printStackTrace(); + } catch (RuntimeException e) { + e.printStackTrace(); + } + return null; } @Test - public void asStackTraceElementTest() { - // TODO + public void getExceptionHandlersTest() throws NoSuchMethodException { + ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithExceptionHandlers", String.class, Object.class)); + ExceptionHandler[] handlers = method.getExceptionHandlers(); + assertNotNull(handlers); + assertEquals(handlers.length, 3); + handlers[0].getCatchType().equals(runtime.lookupJavaType(IndexOutOfBoundsException.class)); + handlers[1].getCatchType().equals(runtime.lookupJavaType(NullPointerException.class)); + handlers[2].getCatchType().equals(runtime.lookupJavaType(RuntimeException.class)); + } + + private static String nullPointerExceptionOnFirstLine(Object o, String ignored) { + return o.toString() + ignored; } @Test - public void getProfilingInfoTest() { - // TODO - } - - @Test - public void getCompilerStorageTest() { - // TODO + public void asStackTraceElementTest() throws NoSuchMethodException { + try { + nullPointerExceptionOnFirstLine(null, "ignored"); + Assert.fail("should not reach here"); + } catch (NullPointerException e) { + StackTraceElement expected = e.getStackTrace()[0]; + ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class)); + StackTraceElement actual = method.asStackTraceElement(0); + assertEquals(expected, actual); + } } @Test public void getConstantPoolTest() { - // TODO + for (Map.Entry e : methods.entrySet()) { + ResolvedJavaMethod m = e.getValue(); + ConstantPool cp = m.getConstantPool(); + assertTrue(cp.length() > 0); + } + } + + @Test(timeout = 1000L) + public void getAnnotationTest() throws NoSuchMethodException { + ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("getAnnotationTest")); + Test annotation = method.getAnnotation(Test.class); + assertNotNull(annotation); + assertEquals(1000L, annotation.timeout()); + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.PARAMETER) + @interface NonNull { + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.PARAMETER) + @interface Special { + } + + private static native void methodWithAnnotatedParameters(@NonNull HashMap p1, @Special @NonNull Class p2); + + @Test + public void getParameterAnnotationsTest() throws NoSuchMethodException { + ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class)); + Annotation[][] annotations = method.getParameterAnnotations(); + assertEquals(2, annotations.length); + assertEquals(1, annotations[0].length); + assertEquals(NonNull.class, annotations[0][0].annotationType()); + assertEquals(2, annotations[1].length); + assertEquals(Special.class, annotations[1][0].annotationType()); + assertEquals(NonNull.class, annotations[1][1].annotationType()); } @Test - public void getAnnotationTest() { - // TODO + public void getGenericParameterTypesTest() throws NoSuchMethodException { + ResolvedJavaMethod method = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class)); + Type[] genericParameterTypes = method.getGenericParameterTypes(); + assertEquals(2, genericParameterTypes.length); + assertEquals("java.util.HashMap", genericParameterTypes[0].toString()); + assertEquals("java.lang.Class", genericParameterTypes[1].toString()); } @Test - public void getParameterAnnotationsTest() { - // TODO - } - - @Test - public void getGenericParameterTypesTest() { - // TODO + public void getMaxLocalsTest() throws NoSuchMethodException { + ResolvedJavaMethod method1 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class)); + ResolvedJavaMethod method2 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class)); + assertEquals(0, method1.getMaxLocals()); + assertEquals(2, method2.getMaxLocals()); } @Test - public void canBeInlinedTest() { - // TODO + public void getMaxStackSizeTest() throws NoSuchMethodException { + ResolvedJavaMethod method1 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("methodWithAnnotatedParameters", HashMap.class, Class.class)); + ResolvedJavaMethod method2 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class)); + assertEquals(0, method1.getMaxStackSize()); + assertEquals(3, method2.getMaxStackSize()); + } + + private Method findTestMethod(Method apiMethod) { + String testName = apiMethod.getName() + "Test"; + for (Method m : getClass().getDeclaredMethods()) { + if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) { + return m; + } + } + return null; + } + + // @formatter:off + private static final String[] untestedApiMethods = { + "invoke", + "newInstance", + "getDeclaringClass", + "getEncoding", + "getProfilingInfo", + "reprofile", + "getCompilerStorage", + "canBeInlined", + "getLineNumberTable", + "getLocalVariableTable", + "isInVirtualMethodTable" + }; + // @formatter:on + + /** + * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written + * for them or are added to {@link #untestedApiMethods}. + */ + @Test + public void testCoverage() { + Set known = new HashSet<>(Arrays.asList(untestedApiMethods)); + for (Method m : ResolvedJavaMethod.class.getDeclaredMethods()) { + if (findTestMethod(m) == null) { + assertTrue("test missing for " + m, known.contains(m.getName())); + } else { + assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName())); + } + } } } diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java Fri May 24 11:02:19 2013 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.api.meta.test; -import static com.oracle.graal.api.meta.test.TestMetaAccessProvider.*; import static java.lang.Integer.*; import static java.lang.reflect.Modifier.*; import static org.junit.Assert.*; @@ -41,7 +40,7 @@ /** * Tests for {@link ResolvedJavaType}. */ -public class TestResolvedJavaType { +public class TestResolvedJavaType extends TypeUniverse { public TestResolvedJavaType() { } @@ -83,7 +82,7 @@ } @Test - public void isArrayClassTest() { + public void isArrayTest() { for (Class c : classes) { ResolvedJavaType type = runtime.lookupJavaType(c); boolean expected = c.isArray(); @@ -103,7 +102,7 @@ } @Test - public void isAssignableToTest() { + public void isAssignableFromTest() { Class[] all = classes.toArray(new Class[classes.size()]); for (int i = 0; i < all.length; i++) { Class c1 = all[i]; @@ -194,7 +193,7 @@ } } - public static Class getSupertype(Class c) { + public Class getSupertype(Class c) { assert !c.isPrimitive(); if (c.isArray()) { Class componentType = c.getComponentType(); @@ -209,7 +208,7 @@ return c.getSuperclass(); } - public static Class findLeastCommonAncestor(Class c1Initial, Class c2Initial) { + public Class findLeastCommonAncestor(Class c1Initial, Class c2Initial) { if (c1Initial.isPrimitive() || c2Initial.isPrimitive()) { return null; } else { @@ -270,7 +269,7 @@ abstract static class Abstract4 extends Concrete3 { } - static void checkConcreteSubtype(ResolvedJavaType type, Class expected) { + void checkConcreteSubtype(ResolvedJavaType type, Class expected) { ResolvedJavaType subtype = type.findUniqueConcreteSubtype(); if (subtype == null) { // findUniqueConcreteSubtype() is conservative @@ -455,8 +454,10 @@ } @Test - public void findUniqueConcreteMethodTest() { - // TODO + public void findUniqueConcreteMethodTest() throws NoSuchMethodException { + ResolvedJavaMethod thisMethod = runtime.lookupJavaMethod(getClass().getDeclaredMethod("findUniqueConcreteMethodTest")); + ResolvedJavaMethod ucm = runtime.lookupJavaType(getClass()).findUniqueConcreteMethod(thisMethod); + assertEquals(thisMethod, ucm); } public static Set getInstanceFields(Class c, boolean includeSuperclasses) { @@ -475,12 +476,12 @@ return result; } - public static boolean fieldsEqual(Field f, ResolvedJavaField rjf) { + public boolean fieldsEqual(Field f, ResolvedJavaField rjf) { return rjf.getDeclaringClass().equals(runtime.lookupJavaType(f.getDeclaringClass())) && rjf.getName().equals(f.getName()) && rjf.getType().resolve(rjf.getDeclaringClass()).equals(runtime.lookupJavaType(f.getType())); } - public static ResolvedJavaField lookupField(ResolvedJavaField[] fields, Field key) { + public ResolvedJavaField lookupField(ResolvedJavaField[] fields, Field key) { for (ResolvedJavaField rf : fields) { if (fieldsEqual(key, rf)) { assert (fieldModifiers() & key.getModifiers()) == rf.getModifiers() : key + ": " + toHexString(key.getModifiers()) + " != " + toHexString(rf.getModifiers()); @@ -490,7 +491,7 @@ return null; } - public static Field lookupField(Set fields, ResolvedJavaField key) { + public Field lookupField(Set fields, ResolvedJavaField key) { for (Field f : fields) { if (fieldsEqual(f, key)) { assert key.getModifiers() == (fieldModifiers() & f.getModifiers()) : key + ": " + toHexString(key.getModifiers()) + " != " + toHexString(f.getModifiers()); @@ -500,7 +501,7 @@ return null; } - private static boolean isHiddenFromReflection(ResolvedJavaField f) { + private boolean isHiddenFromReflection(ResolvedJavaField f) { if (f.getDeclaringClass().equals(runtime.lookupJavaType(Throwable.class)) && f.getName().equals("backtrace")) { return true; } @@ -574,4 +575,50 @@ } } } + + private Method findTestMethod(Method apiMethod) { + String testName = apiMethod.getName() + "Test"; + for (Method m : getClass().getDeclaredMethods()) { + if (m.getName().equals(testName) && m.getAnnotation(Test.class) != null) { + return m; + } + } + return null; + } + + // @formatter:off + private static final String[] untestedApiMethods = { + "initialize", + "isPrimitive", + "newArray", + "getDeclaredMethods", + "getDeclaredConstructors", + "isInitialized", + "getEncoding", + "hasFinalizableSubclass", + "hasFinalizer", + "getSourceFileName", + "getClassFilePath", + "isLocal", + "isMember", + "getEnclosingType" + }; + // @formatter:on + + /** + * Ensures that any new methods added to {@link ResolvedJavaMethod} either have a test written + * for them or are added to {@link #untestedApiMethods}. + */ + @Test + public void testCoverage() { + Set known = new HashSet<>(Arrays.asList(untestedApiMethods)); + for (Method m : ResolvedJavaType.class.getDeclaredMethods()) { + if (findTestMethod(m) == null) { + assertTrue("test missing for " + m, known.contains(m.getName())); + } else { + assertFalse("test should be removed from untestedApiMethods" + m, known.contains(m.getName())); + } + } + } + } diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java Fri May 24 11:02:19 2013 +0200 @@ -0,0 +1,137 @@ +/* + * 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.api.meta.test; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.Queue; + +import org.junit.*; + +import sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; + +/** + * Context for type related api.meta tests. + */ +public class TypeUniverse { + + public final Unsafe unsafe; + public final MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class); + public final Collection> classes = new HashSet<>(); + public final Map, Class> arrayClasses = new HashMap<>(); + public final List constants = new ArrayList<>(); + + public TypeUniverse() { + Unsafe theUnsafe = null; + try { + theUnsafe = Unsafe.getUnsafe(); + } catch (Exception e) { + try { + Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeField.setAccessible(true); + theUnsafe = (Unsafe) theUnsafeField.get(null); + } catch (Exception e1) { + throw (InternalError) new InternalError("unable to initialize unsafe").initCause(e1); + } + } + unsafe = theUnsafe; + + Class[] initialClasses = {void.class, boolean.class, byte.class, short.class, char.class, int.class, float.class, long.class, double.class, Object.class, Class.class, ClassLoader.class, + String.class, Serializable.class, Cloneable.class, Test.class, TestMetaAccessProvider.class, List.class, Collection.class, Map.class, Queue.class, HashMap.class, + LinkedHashMap.class, IdentityHashMap.class, AbstractCollection.class, AbstractList.class, ArrayList.class}; + for (Class c : initialClasses) { + addClass(c); + } + for (Field f : Constant.class.getDeclaredFields()) { + int mods = f.getModifiers(); + if (f.getType() == Constant.class && Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) { + try { + Constant c = (Constant) f.get(null); + if (c != null) { + constants.add(c); + } + } catch (Exception e) { + } + } + } + for (Class c : classes) { + if (c != void.class && !c.isArray()) { + constants.add(Constant.forObject(Array.newInstance(c, 42))); + } + } + constants.add(Constant.forObject(new ArrayList<>())); + constants.add(Constant.forObject(new IdentityHashMap<>())); + constants.add(Constant.forObject(new LinkedHashMap<>())); + constants.add(Constant.forObject(new TreeMap<>())); + constants.add(Constant.forObject(new ArrayDeque<>())); + constants.add(Constant.forObject(new LinkedList<>())); + constants.add(Constant.forObject("a string")); + constants.add(Constant.forObject(42)); + } + + public synchronized Class getArrayClass(Class componentType) { + Class arrayClass = arrayClasses.get(componentType); + if (arrayClass == null) { + arrayClass = Array.newInstance(componentType, 0).getClass(); + arrayClasses.put(componentType, arrayClass); + } + return arrayClass; + } + + public static int dimensions(Class c) { + if (c.getComponentType() != null) { + return 1 + dimensions(c.getComponentType()); + } + return 0; + } + + private void addClass(Class c) { + if (classes.add(c)) { + if (c.getSuperclass() != null) { + addClass(c.getSuperclass()); + } + for (Class sc : c.getInterfaces()) { + addClass(sc); + } + for (Class dc : c.getDeclaredClasses()) { + addClass(dc); + } + for (Method m : c.getDeclaredMethods()) { + addClass(m.getReturnType()); + for (Class p : m.getParameterTypes()) { + addClass(p); + } + } + + if (c != void.class && dimensions(c) < 2) { + Class arrayClass = Array.newInstance(c, 0).getClass(); + arrayClasses.put(c, arrayClass); + addClass(arrayClass); + } + } + } +} diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Fri May 24 11:02:19 2013 +0200 @@ -213,6 +213,8 @@ if (Debug.isDumpEnabled()) { Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } + // TTY.println(String.valueOf(graph)); + // TTY.println(graalRuntime.getRuntime().disassemble(installedCode)); } }); diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java Fri May 24 11:02:19 2013 +0200 @@ -25,9 +25,9 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.ExceptionHandler; -import com.oracle.graal.api.code.CompilationResult.Mark; -import com.oracle.graal.api.code.CompilationResult.Site; +import com.oracle.graal.api.code.CompilationResult.CodeComment; +import com.oracle.graal.api.code.CompilationResult.JumpTable; +import com.oracle.graal.api.code.CompilationResult.*; /** * A {@link CompilationResult} with additional HotSpot-specific information required for installing @@ -40,6 +40,18 @@ public final Site[] sites; public final ExceptionHandler[] exceptionHandlers; + public final Comment[] comments; + + public static class Comment { + + public final String text; + public final int pcOffset; + + public Comment(int pcOffset, String text) { + this.text = text; + this.pcOffset = pcOffset; + } + } public HotSpotCompiledCode(CompilationResult compResult) { this.comp = compResult; @@ -49,6 +61,24 @@ } else { exceptionHandlers = compResult.getExceptionHandlers().toArray(new ExceptionHandler[compResult.getExceptionHandlers().size()]); } + List annotations = compResult.getAnnotations(); + comments = new Comment[annotations.size()]; + if (!annotations.isEmpty()) { + for (int i = 0; i < comments.length; i++) { + CodeAnnotation annotation = annotations.get(i); + String text; + if (annotation instanceof CodeComment) { + CodeComment codeComment = (CodeComment) annotation; + text = codeComment.value; + } else if (annotation instanceof JumpTable) { + JumpTable jumpTable = (JumpTable) annotation; + text = "JumpTable [" + jumpTable.low + " .. " + jumpTable.high + "]"; + } else { + text = annotation.toString(); + } + comments[i] = new Comment(annotation.position, text); + } + } } static class SiteComparator implements Comparator { diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri May 24 11:02:19 2013 +0200 @@ -129,8 +129,9 @@ @Override public native long getMaxCallTargetOffset(long address); + // The HotSpot disassembler seems not to be thread safe so it's better to synchronize its usage @Override - public native String disassembleCodeBlob(long codeBlob); + public synchronized native String disassembleCodeBlob(long codeBlob); @Override public native byte[] getCode(long codeBlob); diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Fri May 24 11:02:19 2013 +0200 @@ -199,6 +199,7 @@ public void addInput(ValueNode x) { assert !(x instanceof PhiNode) || ((PhiNode) x).merge() instanceof LoopBeginNode || ((PhiNode) x).merge() != this.merge(); + assert x.kind() == kind() || type != PhiType.Value; values.add(x); } diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/MonitorTest.java Fri May 24 11:02:19 2013 +0200 @@ -31,33 +31,33 @@ @Test public void test0() { -// test("lockObjectSimple", new Object(), new Object()); -// test("lockObjectSimple", new Object(), null); + test("lockObjectSimple", new Object(), new Object()); + test("lockObjectSimple", new Object(), null); test("lockObjectSimple", null, null); } - // @Test + @Test public void test0_1() { test("lockThisSimple", "test1", new Object()); test("lockThisSimple", "test1", null); } - // @Test + @Test public void test0_2() { test("lockObjectSimple", null, "test1"); } - // @Test + @Test public void test1_1() { test("lockObject", new Object(), "test1", new String[1]); } - // @Test + @Test public void test1_2() { test("lockObject", null, "test1_1", new String[1]); } - // @Test + @Test public void test2() { test("lockThis", "test2", new String[1]); } @@ -65,7 +65,7 @@ /** * Tests monitor operations on {@link PartialEscapeAnalysisPhase virtual objects}. */ - // @Test + @Test public void test3() { test("lockLocalObject", "test3", new String[1]); } @@ -73,7 +73,7 @@ /** * Tests recursive locking of objects which should be biasable. */ - // @Test + @Test public void test4() { Chars src = new Chars("1234567890".toCharArray()); Chars dst = new Chars(src.data.length); @@ -83,7 +83,7 @@ /** * Tests recursive locking of objects which do not appear to be biasable. */ - // @Test + @Test public void test5() { char[] src = "1234567890".toCharArray(); char[] dst = new char[src.length]; @@ -93,7 +93,7 @@ /** * Extends {@link #test4()} with contention. */ - // @Test + @Test public void test6() { Chars src = new Chars("1234567890".toCharArray()); Chars dst = new Chars(src.data.length); @@ -104,7 +104,7 @@ /** * Extends {@link #test5()} with contention. */ - // @Test + @Test public void test7() { char[] src = "1234567890".toCharArray(); char[] dst = new char[src.length]; diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Fri May 24 11:02:19 2013 +0200 @@ -537,7 +537,13 @@ for (int i = 1; i < states.size(); i++) { ValueNode[] fields = objStates[i].getEntries(); if (phis[index] == null && values[index] != fields[index]) { - phis[index] = new PhiNode(values[index].kind(), merge); + Kind kind = values[index].kind(); + if (kind == Kind.Illegal) { + // Can happen if one of the values is virtual and is only + // materialized in the following loop. + kind = Kind.Object; + } + phis[index] = new PhiNode(kind, merge); } } } diff -r b49fdcee6cb0 -r 097630441baf graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Thu May 23 14:44:01 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Fri May 24 11:02:19 2013 +0200 @@ -89,11 +89,12 @@ if (valueState == null) { obj.setEntry(index, getReplacedValue(value)); } else { - if (valueState.getState() == EscapeState.Virtual) { - obj.setEntry(index, value); - } else { - obj.setEntry(index, valueState.getMaterializedValue()); + ValueNode newValue = value; + if (valueState.getState() != EscapeState.Virtual) { + newValue = valueState.getMaterializedValue(); } + assert obj.getEntry(index) == null || obj.getEntry(index).kind() == newValue.kind(); + obj.setEntry(index, newValue); } } diff -r b49fdcee6cb0 -r 097630441baf src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Thu May 23 14:44:01 2013 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri May 24 11:02:19 2013 +0200 @@ -186,6 +186,7 @@ do_klass(BitSet_klass, java_util_BitSet, Opt) \ /* graal.hotspot */ \ do_klass(HotSpotCompiledCode_klass, com_oracle_graal_hotspot_HotSpotCompiledCode, Opt) \ + do_klass(HotSpotCompiledCode_Comment_klass, com_oracle_graal_hotspot_HotSpotCompiledCode_Comment, Opt) \ do_klass(HotSpotCompiledNmethod_klass, com_oracle_graal_hotspot_HotSpotCompiledNmethod, Opt) \ do_klass(HotSpotCompiledRuntimeStub_klass, com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub, Opt) \ do_klass(HotSpotForeignCallLinkage_klass, com_oracle_graal_hotspot_HotSpotForeignCallLinkage, Opt) \ diff -r b49fdcee6cb0 -r 097630441baf src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Thu May 23 14:44:01 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri May 24 11:02:19 2013 +0200 @@ -297,6 +297,7 @@ template(com_oracle_graal_hotspot_HotSpotKlassOop, "com/oracle/graal/hotspot/HotSpotKlassOop") \ template(com_oracle_graal_hotspot_HotSpotOptions, "com/oracle/graal/hotspot/HotSpotOptions") \ template(com_oracle_graal_hotspot_HotSpotCompiledCode, "com/oracle/graal/hotspot/HotSpotCompiledCode") \ + template(com_oracle_graal_hotspot_HotSpotCompiledCode_Comment, "com/oracle/graal/hotspot/HotSpotCompiledCode$Comment") \ template(com_oracle_graal_hotspot_HotSpotCompiledNmethod, "com/oracle/graal/hotspot/HotSpotCompiledNmethod") \ template(com_oracle_graal_hotspot_HotSpotCompiledRuntimeStub, "com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub") \ template(com_oracle_graal_hotspot_HotSpotForeignCallLinkage, "com/oracle/graal/hotspot/HotSpotForeignCallLinkage") \ diff -r b49fdcee6cb0 -r 097630441baf src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Thu May 23 14:44:01 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Fri May 24 11:02:19 2013 +0200 @@ -410,6 +410,9 @@ // (very) conservative estimate: each site needs a constant section entry _constants_size = _sites->length() * (BytesPerLong*2); +#ifndef PRODUCT + _comments = (arrayOop) HotSpotCompiledCode::comments(compiled_code); +#endif _next_call_type = MARK_INVOKE_INVALID; } @@ -463,6 +466,19 @@ fatal("unexpected Site subclass"); } } + +#ifndef PRODUCT + if (_comments != NULL) { + oop* comments = (oop*) _comments->base(T_OBJECT); + for (int i = 0; i < _comments->length(); i++) { + oop comment = comments[i]; + assert(comment->is_a(HotSpotCompiledCode_Comment::klass()), "cce"); + jint offset = HotSpotCompiledCode_Comment::pcOffset(comment); + char* text = java_lang_String::as_utf8_string(HotSpotCompiledCode_Comment::text(comment)); + buffer.block_comment(offset, text); + } + } +#endif } void CodeInstaller::assumption_MethodContents(Handle assumption) { diff -r b49fdcee6cb0 -r 097630441baf src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Thu May 23 14:44:01 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Fri May 24 11:02:19 2013 +0200 @@ -60,6 +60,9 @@ jint _custom_stack_area_offset; jint _parameter_count; jint _constants_size; +#ifndef PRODUCT + arrayOop _comments; +#endif MarkId _next_call_type; address _invoke_mark_pc; diff -r b49fdcee6cb0 -r 097630441baf src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Thu May 23 14:44:01 2013 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri May 24 11:02:19 2013 +0200 @@ -87,6 +87,11 @@ oop_field(HotSpotCompiledCode, comp, "Lcom/oracle/graal/api/code/CompilationResult;") \ oop_field(HotSpotCompiledCode, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ oop_field(HotSpotCompiledCode, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \ + oop_field(HotSpotCompiledCode, comments, "[Lcom/oracle/graal/hotspot/HotSpotCompiledCode$Comment;") \ + end_class \ + start_class(HotSpotCompiledCode_Comment) \ + oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;") \ + int_field(HotSpotCompiledCode_Comment, pcOffset) \ end_class \ start_class(HotSpotCompiledNmethod) \ oop_field(HotSpotCompiledNmethod, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ @@ -95,8 +100,8 @@ start_class(HotSpotCompiledRuntimeStub) \ oop_field(HotSpotCompiledRuntimeStub, stubName, "Ljava/lang/String;") \ end_class \ - start_class(HotSpotForeignCallLinkage) \ - long_field(HotSpotForeignCallLinkage, address) \ + start_class(HotSpotForeignCallLinkage) \ + long_field(HotSpotForeignCallLinkage, address) \ end_class \ start_class(ExceptionHandler) \ int_field(ExceptionHandler, startBCI) \ @@ -139,7 +144,7 @@ int_field(CompilationResult_Site, pcOffset) \ end_class \ start_class(CompilationResult_Call) \ - oop_field(CompilationResult_Call, target, "Lcom/oracle/graal/api/meta/InvokeTarget;") \ + oop_field(CompilationResult_Call, target, "Lcom/oracle/graal/api/meta/InvokeTarget;") \ oop_field(CompilationResult_Call, debugInfo, "Lcom/oracle/graal/api/code/DebugInfo;") \ end_class \ start_class(CompilationResult_DataPatch) \ @@ -228,10 +233,10 @@ oop_field(VirtualObject, type, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ oop_field(VirtualObject, values, "[Lcom/oracle/graal/api/meta/Value;") \ end_class \ - start_class(HotSpotMonitorValue) \ - oop_field(HotSpotMonitorValue, owner, "Lcom/oracle/graal/api/meta/Value;") \ - oop_field(HotSpotMonitorValue, slot, "Lcom/oracle/graal/api/code/StackSlot;") \ - boolean_field(HotSpotMonitorValue, eliminated) \ + start_class(HotSpotMonitorValue) \ + oop_field(HotSpotMonitorValue, owner, "Lcom/oracle/graal/api/meta/Value;") \ + oop_field(HotSpotMonitorValue, slot, "Lcom/oracle/graal/api/code/StackSlot;") \ + boolean_field(HotSpotMonitorValue, eliminated) \ end_class \ /* end*/