# HG changeset patch # User Doug Simon # Date 1353681000 -3600 # Node ID 62818f15608114c476f3af5a02d0d454c032986e # Parent b618f7c63d17b7e586c96ee3df5dc449ddc1b750 added ResolvedJavaType.isClass(Class c) to replace some uses of ResolvedJavaType.toJava() added MetaAccessProviderTest - more meta API tests to come diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.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/TestMetaAccessProvider.java Fri Nov 23 15:30:00 2012 +0100 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2011, 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 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 com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; + + +public class TestMetaAccessProvider { + + public TestMetaAccessProvider() { + } + + public static final MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class); + public static final List> classes = new ArrayList<>(Arrays.asList( + void.class, + boolean.class, + byte.class, + short.class, + char.class, + int.class, + float.class, + long.class, + double.class, + Object.class, + Serializable.class, + Cloneable.class, + Test.class, + TestMetaAccessProvider.class + )); + + static { + for (Class c : new ArrayList<>(classes)) { + if (c != void.class) { + classes.add(Array.newInstance(c, 0).getClass()); + } + } + } + + @Test + public void lookupJavaTypeTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + assertNotNull(type); + assertTrue(type.isClass(c)); + assertEquals(c.getModifiers(), type.getModifiers()); + if (!type.isArrayClass()) { + assertEquals(type.getName(), toInternalName(c.getName())); + assertEquals(toJavaName(type), c.getName()); + } + } + } + + @Test + public void lookupJavaMethodTest() { + for (Class c : classes) { + for (Method reflect : c.getDeclaredMethods()) { + ResolvedJavaMethod method = runtime.lookupJavaMethod(reflect); + assertNotNull(method); + assertEquals(reflect.getModifiers(), method.getModifiers()); + assertTrue(method.getDeclaringClass().isClass(reflect.getDeclaringClass())); + } + } + } + + @Test + public void lookupJavaFieldTest() { + for (Class c : classes) { + for (Field reflect : c.getDeclaredFields()) { + ResolvedJavaField field = runtime.lookupJavaField(reflect); + assertNotNull(field); + assertEquals(reflect.getModifiers(), field.getModifiers()); + assertTrue(field.getDeclaringClass().isClass(reflect.getDeclaringClass())); + } + } + } + + 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) { + constants.add(Constant.forObject(Array.newInstance(c, 42))); + } + } + } + + @Test + public void lookupJavaTypeConstantTest() { + for (Constant c : constants) { + if (c.getKind().isObject() && !c.isNull()) { + Object o = c.asObject(); + ResolvedJavaType type = runtime.lookupJavaType(c); + assertNotNull(type); + assertTrue(type.isClass(o.getClass())); + } else { + assertEquals(runtime.lookupJavaType(c), null); + } + } + } + + @Test + public void constantEqualsTest() { + for (Constant c1 : constants) { + for (Constant c2 : constants) { + // test symmetry + assertEquals(runtime.constantEquals(c1, c2), runtime.constantEquals(c2, c1)); + if (!c1.getKind().isObject() && !c2.getKind().isObject()) { + assertEquals(c1.equals(c2), runtime.constantEquals(c2, c1)); + } + } + } + } + + @Test + public void lookupArrayLengthTest() { + for (Constant c : constants) { + if (!c.getKind().isObject() || c.isNull() || !c.asObject().getClass().isArray()) { + try { + int length = runtime.lookupArrayLength(c); + fail("Expected " + IllegalArgumentException.class.getName() + " for " + c + ", not " + length); + } catch (IllegalArgumentException e) { + // pass + } + } else { + assertEquals(Array.getLength(c.asObject()), runtime.lookupArrayLength(c)); + } + } + } +} diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Fri Nov 23 15:30:00 2012 +0100 @@ -56,8 +56,10 @@ /** * Compares two constants for equality. - * This is used instead of {@link Constant#equals(Object)} in case where the runtime - * may have an interpretation for object equality other than {@code x.asObject() == y.asObject()}. + * This is used instead of {@link Constant#equals(Object)} in case the runtime + * has an interpretation for object equality other than {@code x.asObject() == y.asObject()}. + * For primitive constants, this is equivalent to calling {@code x.equals(y)}. + * The equality relationship is symmetric. * * @return {@code true} if the two parameters represent the same runtime object, {@code false} otherwise */ @@ -65,6 +67,8 @@ /** * Returns the length of an array that is wrapped in a {@link Constant} object. + * + * @throws IllegalArgumentException if {@code array} is not an array */ int lookupArrayLength(Constant array); } diff -r b618f7c63d17 -r 62818f156081 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 Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Fri Nov 23 15:30:00 2012 +0100 @@ -46,9 +46,16 @@ } /** + * Determines if a given type represents a primitive type. + */ + public static boolean isPrimitive(ResolvedJavaType type) { + return type.getSuperclass() == null && !type.isInstanceClass(); + } + + /** * Extends the functionality of {@link Class#getSimpleName()} to include a non-empty string for anonymous and local * classes. - * + * * @param clazz the class for which the simple name is being requested * @param withEnclosingClass specifies if the returned name should be qualified with the name(s) of the enclosing * class/classes of {@code clazz} (if any). This option is ignored if {@code clazz} denotes an anonymous @@ -84,7 +91,7 @@ /** * Converts a given type to its Java programming language name. The following are examples of strings returned by * this method: - * + * *
      *     qualified == true:
      *         java.lang.Object
@@ -95,7 +102,7 @@
      *         int
      *         boolean[][]
      * 
- * + * * @param type the type to be converted to a Java name * @param qualified specifies if the package prefix of the type should be included in the returned name * @return the Java name corresponding to {@code type} @@ -111,13 +118,13 @@ /** * Converts a given type to its Java programming language name. The following are examples of strings returned by * this method: - * + * *
      *      java.lang.Object
      *      int
      *      boolean[][]
      * 
- * + * * @param type the type to be converted to a Java name * @return the Java name corresponding to {@code type} */ @@ -153,7 +160,7 @@ * composed of characters that are to be copied verbatim to the result and specifiers that denote an attribute of * the method that is to be copied to the result. A specifier is a single character preceded by a '%' character. The * accepted specifiers and the method attributes they denote are described below: - * + * *
      *     Specifier | Description                                          | Example(s)
      *     ----------+------------------------------------------------------------------------------------------
@@ -167,7 +174,7 @@
      *     'f'       | Indicator if method is unresolved, static or virtual | "unresolved" "static" "virtual"
      *     '%'       | A '%' character                                      | "%"
      * 
- * + * * @param format a format specification * @param method the method to be formatted * @return the result of formatting this method according to {@code format} @@ -246,7 +253,7 @@ * composed of characters that are to be copied verbatim to the result and specifiers that denote an attribute of * the field that is to be copied to the result. A specifier is a single character preceded by a '%' character. The * accepted specifiers and the field attributes they denote are described below: - * + * *
      *     Specifier | Description                                          | Example(s)
      *     ----------+------------------------------------------------------------------------------------------
@@ -258,7 +265,7 @@
      *     'f'       | Indicator if field is unresolved, static or instance | "unresolved" "static" "instance"
      *     '%'       | A '%' character                                      | "%"
      * 
- * + * * @param format a format specification * @param field the field to be formatted * @return the result of formatting this field according to {@code format} @@ -316,7 +323,7 @@ /** * Gets the annotations of a particular type for the formal parameters of a given method. - * + * * @param annotationClass the Class object corresponding to the annotation type * @param method the method for which a parameter annotations are being requested * @return the annotation of type {@code annotationClass} (if any) for each formal parameter present @@ -337,7 +344,7 @@ /** * Gets the annotation of a particular type for a formal parameter of a given method. - * + * * @param annotationClass the Class object corresponding to the annotation type * @param parameterIndex the index of a formal parameter of {@code method} * @param method the method for which a parameter annotation is being requested @@ -370,18 +377,18 @@ * {@linkplain ResolvedJavaMethod#asStackTraceElement(int) available} for the given method, then the string returned * is the {@link StackTraceElement#toString()} value of the stack trace element, suffixed by the bci location. For * example: - * + * *
      *     java.lang.String.valueOf(String.java:2930) [bci: 12]
      * 
- * + * * Otherwise, the string returned is the value of applying {@link #format(String, JavaMethod)} with the format * string {@code "%H.%n(%p)"}, suffixed by the bci location. For example: - * + * *
      *     java.lang.String.valueOf(int) [bci: 12]
      * 
- * + * * @param sb * @param method * @param bci @@ -433,7 +440,7 @@ /** * Formats some profiling information associated as a string. - * + * * @param info the profiling info to format * @param method an optional method that augments the profile string returned * @param sep the separator to use for each separate profile record @@ -500,12 +507,46 @@ /** * Converts a Java source-language class name into the internal form. - * + * * @param className the class name * @return the internal name form of the class name */ public static String toInternalName(String className) { - return "L" + className.replace('.', '/') + ";"; + String prefix = ""; + String base = className; + while (base.endsWith("[]")) { + prefix += "["; + base = base.substring(base.length() - 2); + } + + if (className.equals("boolean")) { + return prefix + "Z"; + } + if (className.equals("byte")) { + return prefix + "B"; + } + if (className.equals("short")) { + return prefix + "S"; + } + if (className.equals("char")) { + return prefix + "C"; + } + if (className.equals("int")) { + return prefix + "I"; + } + if (className.equals("float")) { + return prefix + "F"; + } + if (className.equals("long")) { + return prefix + "J"; + } + if (className.equals("double")) { + return prefix + "D"; + } + if (className.equals("void")) { + return prefix + "V"; + } + return prefix + "L" + className.replace('.', '/') + ";"; } /** diff -r b618f7c63d17 -r 62818f156081 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 Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Fri Nov 23 15:30:00 2012 +0100 @@ -155,7 +155,8 @@ ResolvedJavaType getSuperclass(); /** - * Gets the interfaces that this type defines. This method is analogous to {@link Class#getInterfaces()}. + * Gets the interfaces implemented or extended by this type. This method is analogous to {@link Class#getInterfaces()} + * and as such, only returns the interfaces directly implemented or extended by this type. */ ResolvedJavaType[] getInterfaces(); @@ -223,6 +224,11 @@ T getAnnotation(Class annotationClass); /** + * Determines if this type is the same as that represented by a given {@link Class}. + */ + boolean isClass(Class c); + + /** * Returns the {@link java.lang.Class} object representing this type. */ Class< ? > toJava(); diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Nov 23 15:30:00 2012 +0100 @@ -143,13 +143,6 @@ JavaType getUniqueConcreteSubtype(HotSpotResolvedJavaType klass); - int getArrayLength(Constant array); - - /** - * Gets the type of an object constant. - */ - JavaType getJavaType(Constant constant); - HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedJavaType klass); /** diff -r b618f7c63d17 -r 62818f156081 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 Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Nov 23 15:30:00 2012 +0100 @@ -113,20 +113,6 @@ public native ResolvedJavaType getResolvedType(Class javaClass); @Override - public int getArrayLength(Constant array) { - return Array.getLength(array.asObject()); - } - - @Override - public JavaType getJavaType(Constant constant) { - Object o = constant.asObject(); - if (o == null) { - return null; - } - return HotSpotResolvedJavaType.fromClass(o.getClass()); - } - - @Override public native HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedJavaType klass); @Override diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Fri Nov 23 15:30:00 2012 +0100 @@ -254,7 +254,10 @@ @Override public boolean isInstance(Constant obj) { - return javaMirror.isInstance(obj); + if (obj.getKind().isObject() && !obj.isNull()) { + return javaMirror.isInstance(obj.asObject()); + } + return false; } @Override @@ -392,6 +395,11 @@ } @Override + public boolean isClass(Class c) { + return c == javaMirror; + } + + @Override public T getAnnotation(Class annotationClass) { return javaMirror.getAnnotation(annotationClass); } diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Nov 23 15:30:00 2012 +0100 @@ -330,7 +330,11 @@ @Override public ResolvedJavaType lookupJavaType(Constant constant) { - return (ResolvedJavaType) graalRuntime.getCompilerToVM().getJavaType(constant); + if (!constant.getKind().isObject() || constant.isNull()) { + return null; + } + Object o = constant.asObject(); + return HotSpotResolvedJavaType.fromClass(o.getClass()); } @Override @@ -363,7 +367,10 @@ @Override public int lookupArrayLength(Constant array) { - return graalRuntime.getCompilerToVM().getArrayLength(array); + if (!array.getKind().isObject() || array.isNull() || !array.asObject().getClass().isArray()) { + throw new IllegalArgumentException(array + " is not an array"); + } + return Array.getLength(array.asObject()); } @Override diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java Fri Nov 23 15:30:00 2012 +0100 @@ -167,6 +167,11 @@ } @Override + public boolean isClass(Class c) { + return c == javaMirror; + } + + @Override public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { return this; } diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java --- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java Fri Nov 23 15:30:00 2012 +0100 @@ -1207,7 +1207,7 @@ } private void instanceOf(InterpreterFrame frame, char cpi) { - frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).toJava().isInstance(frame.popObject()) ? 1 : 0); + frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).isInstance(Constant.forObject(frame.popObject())) ? 1 : 0); } private void pushCPConstant(InterpreterFrame frame, char cpi) { diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java Fri Nov 23 15:30:00 2012 +0100 @@ -133,7 +133,7 @@ if (boxing == null) { return false; } - return method.getDeclaringClass().toJava() == boxing.type && method.getName().equals("valueOf"); + return method.getDeclaringClass().isClass(boxing.type) && method.getName().equals("valueOf"); } public static boolean isUnboxingMethodStatic(ResolvedJavaMethod method) { diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Fri Nov 23 15:30:00 2012 +0100 @@ -385,8 +385,8 @@ private static boolean checkConstantArgument(final ResolvedJavaMethod method, Signature signature, int i, String name, Object arg, Kind kind) { if (kind.isObject()) { - Class type = signature.getParameterType(i, method.getDeclaringClass()).resolve(method.getDeclaringClass()).toJava(); - assert arg == null || type.isInstance(arg) : + ResolvedJavaType type = signature.getParameterType(i, method.getDeclaringClass()).resolve(method.getDeclaringClass()); + assert arg == null || type.isInstance(Constant.forObject(arg)) : method + ": wrong value type for " + name + ": expected " + type.getName() + ", got " + arg.getClass().getName(); } else { assert arg != null && kind.toBoxedJavaClass() == arg.getClass() : @@ -398,9 +398,8 @@ private static boolean checkVarargs(final ResolvedJavaMethod method, Signature signature, int i, String name, Varargs varargs) { Object arg = varargs.getArray(); ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); - Class< ? > javaType = type.toJava(); - assert javaType.isArray() : "varargs parameter must be an array type"; - assert javaType.isInstance(arg) : "value for " + name + " is not a " + javaType.getName() + " instance: " + arg; + assert type.isArrayClass() : "varargs parameter must be an array type"; + assert type.isInstance(Constant.forObject(arg)) : "value for " + name + " is not a " + MetaUtil.toJavaName(type) + " instance: " + arg; return true; } diff -r b618f7c63d17 -r 62818f156081 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Fri Nov 23 09:02:12 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Fri Nov 23 15:30:00 2012 +0100 @@ -83,7 +83,7 @@ ValueNode argument = arguments.get(argc); if (argument == node) { ResolvedJavaType type = (ResolvedJavaType) signature.getParameterType(i, method.getDeclaringClass()); - verify((type.toJava() == Word.class) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); + verify((type.isClass(Word.class)) == isWord(argument), node, invoke.node(), "cannot pass word value to non-word parameter " + i + " or vice-versa"); } argc++; } diff -r b618f7c63d17 -r 62818f156081 mx/projects --- a/mx/projects Fri Nov 23 09:02:12 2012 +0100 +++ b/mx/projects Fri Nov 23 15:30:00 2012 +0100 @@ -41,6 +41,13 @@ project@com.oracle.graal.api.meta@checkstyle=com.oracle.graal.graph project@com.oracle.graal.api.meta@javaCompliance=1.7 +# graal.api.meta.test +project@com.oracle.graal.api.meta.test@subDir=graal +project@com.oracle.graal.api.meta.test@sourceDirs=src +project@com.oracle.graal.api.meta.test@dependencies=JUNIT,com.oracle.graal.api.meta,com.oracle.graal.api.runtime +project@com.oracle.graal.api.meta.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.api.meta.test@javaCompliance=1.7 + # graal.api.code project@com.oracle.graal.api.code@subDir=graal project@com.oracle.graal.api.code@sourceDirs=src