# HG changeset patch # User Doug Simon # Date 1354011708 -3600 # Node ID dd81042f4eb150ea21d5237a31a0449ffd79f8f5 # Parent 8c4b757c2eb935de64a50f5e7d533b3d6fa1bf35 added unit tests for ResolvedJavaType replaced some CompilerToVM methods used by HotSpotResolvedJavaType with pure Java code diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Tue Nov 27 11:21:48 2012 +0100 @@ -84,7 +84,7 @@ double totalHintProbability = 0.0d; for (ProfiledType ptype : ptypes) { ResolvedJavaType hint = ptype.getType(); - if (type != null && hint.isSubtypeOf(type)) { + if (type != null && hint.isAssignableTo(type)) { hintTypes[hintCount++] = hint; totalHintProbability += ptype.getProbability(); } diff -r 8c4b757c2eb9 -r dd81042f4eb1 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 Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java Tue Nov 27 11:21:48 2012 +0100 @@ -41,29 +41,121 @@ } 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 - )); + 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 { - for (Class c : new ArrayList<>(classes)) { - if (c != void.class) { - classes.add(Array.newInstance(c, 0).getClass()); + 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); + } + } + + static { + System.out.println(classes.size() + " classes"); + } + + 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)); + } + + static { + System.out.println(constants.size() + " constants"); } @Test @@ -86,7 +178,9 @@ for (Method reflect : c.getDeclaredMethods()) { ResolvedJavaMethod method = runtime.lookupJavaMethod(reflect); assertNotNull(method); - assertEquals(reflect.getModifiers(), method.getModifiers()); + int expected = reflect.getModifiers() & Modifier.methodModifiers(); + int actual = method.getModifiers(); + assertEquals(String.format("%s: 0x%x != 0x%x", reflect, expected, actual), expected, actual); assertTrue(method.getDeclaringClass().isClass(reflect.getDeclaringClass())); } } @@ -98,33 +192,14 @@ for (Field reflect : c.getDeclaredFields()) { ResolvedJavaField field = runtime.lookupJavaField(reflect); assertNotNull(field); - assertEquals(reflect.getModifiers(), field.getModifiers()); + int expected = reflect.getModifiers() & Modifier.fieldModifiers(); + int actual = field.getModifiers(); + assertEquals(String.format("%s: 0x%x != 0x%x", reflect, expected, actual), expected, actual); 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) { diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.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/TestResolvedJavaType.java Tue Nov 27 11:21:48 2012 +0100 @@ -0,0 +1,540 @@ +/* + * 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.test.TestMetaAccessProvider.*; +import static java.lang.reflect.Modifier.*; +import static org.junit.Assert.*; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; + +import org.junit.*; + +import sun.reflect.ConstantPool; + +import com.oracle.graal.api.meta.*; + +public class TestResolvedJavaType { + + public TestResolvedJavaType() { + } + + @Test + public void isInterfaceTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + boolean expected = c.isInterface(); + boolean actual = type.isInterface(); + assertEquals(expected, actual); + } + } + + + @Test + public void isInstanceClassTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + boolean expected = !c.isArray() && !c.isPrimitive() && !c.isInterface(); + boolean actual = type.isInstanceClass(); + assertEquals(expected, actual); + } + } + + @Test + public void isArrayClassTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + boolean expected = c.isArray(); + boolean actual = type.isArrayClass(); + assertEquals(expected, actual); + } + } + + @Test + public void getModifiersTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + int expected = c.getModifiers(); + int actual = type.getModifiers(); + assertEquals(expected, actual); + } + } + + @Test + public void isAssignableToTest() { + Class[] all = classes.toArray(new Class[classes.size()]); + for (int i = 0; i < all.length; i++) { + Class c1 = all[i]; + for (int j = i; j < all.length; j++) { + Class c2 = all[j]; + ResolvedJavaType t1 = runtime.lookupJavaType(c1); + ResolvedJavaType t2 = runtime.lookupJavaType(c2); + boolean expected = c1.isAssignableFrom(c2); + boolean actual = t2.isAssignableTo(t1); + assertEquals(expected, actual); + if (expected && t1 != t2) { + assertFalse(t1.isAssignableTo(t2)); + } + } + } + } + + @Test + public void isInstanceTest() { + for (Constant c : constants) { + if (c.getKind().isObject() && !c.isNull()) { + Object o = c.asObject(); + Class< ? extends Object> cls = o.getClass(); + while (cls != null) { + ResolvedJavaType type = runtime.lookupJavaType(cls); + boolean expected = cls.isInstance(o); + boolean actual = type.isInstance(c); + assertEquals(expected, actual); + cls = cls.getSuperclass(); + } + } + } + } + + private static Class asExactClass(Class c) { + if (c.isArray()) { + if (asExactClass(c.getComponentType()) != null) { + return c; + } + } else { + if (c.isPrimitive() || Modifier.isFinal(c.getModifiers())) { + return c; + } + } + return null; + } + + @Test + public void asExactTypeTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + ResolvedJavaType exactType = type.asExactType(); + Class expected = asExactClass(c); + if (expected == null) { + assertTrue("exact(" + c.getName() + ") != null", exactType == null); + } else { + assertNotNull(exactType); + assertTrue(exactType.isClass(expected)); + } + } + } + + @Test + public void getSuperclassTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + Class expected = c.getSuperclass(); + ResolvedJavaType actual = type.getSuperclass(); + if (expected == null) { + assertTrue(actual == null); + } else { + assertNotNull(actual); + assertTrue(actual.isClass(expected)); + } + } + } + + @Test + public void getInterfacesTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + Class[] expected = c.getInterfaces(); + ResolvedJavaType[] actual = type.getInterfaces(); + assertEquals(expected.length, actual.length); + for (int i = 0; i < expected.length; i++) { + assertTrue(actual[i].isClass(expected[i])); + } + } + } + + public static Class getSupertype(Class c) { + assert !c.isPrimitive(); + if (c.isArray()) { + Class componentType = c.getComponentType(); + if (componentType.isPrimitive() || componentType == Object.class) { + return Object.class; + } + return getArrayClass(getSupertype(componentType)); + } + if (c.isInterface()) { + return Object.class; + } + return c.getSuperclass(); + } + + public static Class findLeastCommonAncestor(Class c1Initial, Class c2Initial) { + if (c1Initial.isPrimitive() || c2Initial.isPrimitive()) { + return null; + } else { + Class c1 = c1Initial; + Class c2 = c2Initial; + while (true) { + if (c1.isAssignableFrom(c2)) { + return c1; + } + if (c2.isAssignableFrom(c1)) { + return c2; + } + c1 = getSupertype(c1); + c2 = getSupertype(c2); + } + } + } + + @Test + public void findLeastCommonAncestorTest() { + Class[] all = classes.toArray(new Class[classes.size()]); + for (int i = 0; i < all.length; i++) { + Class c1 = all[i]; + for (int j = i; j < all.length; j++) { + Class c2 = all[j]; + ResolvedJavaType t1 = runtime.lookupJavaType(c1); + ResolvedJavaType t2 = runtime.lookupJavaType(c2); + Class expected = findLeastCommonAncestor(c1, c2); + ResolvedJavaType actual = t1.findLeastCommonAncestor(t2); + if (expected == null) { + assertTrue(actual == null); + } else { + assertNotNull(actual); + assertTrue(actual.isClass(expected)); + } + } + } + } + + private static class Base {} + abstract static class Abstract1 extends Base {} + interface Interface1 {} + static class Concrete1 extends Abstract1 {} + static class Concrete2 extends Abstract1 implements Interface1 {} + static class Concrete3 extends Concrete2 {} + abstract static class Abstract4 extends Concrete3 {} + + static void checkConcreteSubtype(ResolvedJavaType type, Class expected) { + ResolvedJavaType subtype = type.findUniqueConcreteSubtype(); + if (type.isInterface() && subtype == null) { + // A runtime may not record the subtype tree for interfaces in which case + // findUniqueConcreteSubtype() will return null for interfaces. + return; + } + + if (expected == null) { + assertNull(subtype); + } else { + assertTrue(subtype.isClass(expected)); + } + if (!type.isArrayClass()) { + ResolvedJavaType arrayType = type.getArrayClass(); + if (subtype == type) { + assertEquals(arrayType.findUniqueConcreteSubtype(), arrayType); + } else { + assertNull(arrayType.findUniqueConcreteSubtype()); + } + } + } + + @Test + public void findUniqueConcreteSubtypeTest() { + ResolvedJavaType base = runtime.lookupJavaType(Base.class); + checkConcreteSubtype(base, Base.class); + + ResolvedJavaType a1 = runtime.lookupJavaType(Abstract1.class); + ResolvedJavaType c1 = runtime.lookupJavaType(Concrete1.class); + + checkConcreteSubtype(base, null); + checkConcreteSubtype(a1, Concrete1.class); + checkConcreteSubtype(c1, Concrete1.class); + + ResolvedJavaType i1 = runtime.lookupJavaType(Interface1.class); + ResolvedJavaType c2 = runtime.lookupJavaType(Concrete2.class); + + checkConcreteSubtype(base, null); + checkConcreteSubtype(a1, null); + checkConcreteSubtype(c1, Concrete1.class); + checkConcreteSubtype(i1, Concrete2.class); + checkConcreteSubtype(c2, Concrete2.class); + + ResolvedJavaType c3 = runtime.lookupJavaType(Concrete3.class); + checkConcreteSubtype(c2, null); + checkConcreteSubtype(c3, Concrete3.class); + + ResolvedJavaType a4 = runtime.lookupJavaType(Abstract4.class); + checkConcreteSubtype(c3, null); + checkConcreteSubtype(a4, null); + } + + @Test + public void getComponentTypeTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + Class expected = c.getComponentType(); + ResolvedJavaType actual = type.getComponentType(); + if (expected == null) { + assertNull(actual); + } else { + assertTrue(actual.isClass(expected)); + } + } + } + + @Test + public void getArrayClassTest() { + for (Class c : classes) { + if (c != void.class) { + ResolvedJavaType type = runtime.lookupJavaType(c); + Class expected = getArrayClass(c); + ResolvedJavaType actual = type.getArrayClass(); + assertTrue(actual.isClass(expected)); + } + } + } + + static class Declarations { + final Method implementation; + final Set declarations; + + public Declarations(Method impl) { + this.implementation = impl; + declarations = new HashSet<>(); + } + } + + /** + * See Method overriding. + */ + static boolean isOverriderOf(Method impl, Method m) { + if (!isPrivate(m.getModifiers()) && !isFinal(m.getModifiers())) { + if (m.getName().equals(impl.getName())) { + if (m.getReturnType() == impl.getReturnType()) { + if (Arrays.equals(m.getParameterTypes(), impl.getParameterTypes())) { + if (isPublic(m.getModifiers()) || isProtected(m.getModifiers())) { + // m is public or protected + return isPublic(impl.getModifiers()) || isProtected(impl.getModifiers()); + } else { + // m is package-private + return impl.getDeclaringClass().getPackage() == m.getDeclaringClass().getPackage(); + } + } + } + } + } + return false; + } + + static final Map vtables = new HashMap<>(); + + static class NameAndSig { + final String name; + final Class returnType; + final Class[] parameterTypes; + public NameAndSig(Method m) { + this.name = m.getName(); + this.returnType = m.getReturnType(); + this.parameterTypes = m.getParameterTypes(); + } + @Override + public boolean equals(Object obj) { + if (obj instanceof NameAndSig) { + NameAndSig s = (NameAndSig) obj; + return s.returnType == returnType && name.equals(s.name) && Arrays.equals(s.parameterTypes, parameterTypes); + } + return false; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(name + "("); + String sep = ""; + for (Class p : parameterTypes) { + sb.append(sep); + sep = ", "; + sb.append(p.getName()); + } + return sb.append(')').append(returnType.getName()).toString(); + } + } + + static class VTable { + final Map methods = new HashMap<>(); + } + + static synchronized VTable getVTable(Class c) { + VTable vtable = vtables.get(c); + if (vtable == null) { + vtable = new VTable(); + if (c != Object.class) { + VTable superVtable = getVTable(c.getSuperclass()); + vtable.methods.putAll(superVtable.methods); + } + for (Method m : c.getDeclaredMethods()) { + if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) { + Method overridden = vtable.methods.put(new NameAndSig(m), m); + if (overridden != null) { + //System.out.println(m + " overrides " + overridden); + } + } + } + vtables.put(c, vtable); + } + return vtable; + } + + static Set findDeclarations(Method impl, Class c) { + Set declarations = new HashSet<>(); + NameAndSig implSig = new NameAndSig(impl); + if (c != null) { + for (Method m : c.getDeclaredMethods()) { + if (new NameAndSig(m).equals(implSig)) { + declarations.add(m); + break; + } + } + if (!c.isInterface()) { + declarations.addAll(findDeclarations(impl, c.getSuperclass())); + } + for (Class i : c.getInterfaces()) { + declarations.addAll(findDeclarations(impl, i)); + } + } + return declarations; + } + + private static void checkResolveMethod(ResolvedJavaType type, ResolvedJavaMethod decl, ResolvedJavaMethod expected) { + ResolvedJavaMethod impl = type.resolveMethod(decl); + assertEquals(expected, impl); + } + + @Test + public void resolveMethodTest() { + for (Class c : classes) { + if (!c.isPrimitive() && !c.isInterface()) { + ResolvedJavaType type = runtime.lookupJavaType(c); + VTable vtable = getVTable(c); + for (Method impl : vtable.methods.values()) { + Set decls = findDeclarations(impl, c); + for (Method decl : decls) { + ResolvedJavaMethod m = runtime.lookupJavaMethod(decl); + ResolvedJavaMethod i = runtime.lookupJavaMethod(impl); + checkResolveMethod(type, m, i); + } + } + } + } + } + + @Test + public void findUniqueConcreteMethodTest() { + // TODO + } + + public static Set getInstanceFields(Class c, boolean includeSuperclasses) { + if (c.isArray() || c.isPrimitive() || c.isInterface()) { + return Collections.emptySet(); + } + Set result = new HashSet<>(); + for (Field f : c.getDeclaredFields()) { + if (!Modifier.isStatic(f.getModifiers())) { + result.add(f); + } + } + if (includeSuperclasses && c != Object.class) { + result.addAll(getInstanceFields(c.getSuperclass(), true)); + } + return result; + } + + public static boolean containsField(ResolvedJavaField[] fields, Field f) { + for (ResolvedJavaField rf : fields) { + if (rf.getName().equals(f.getName()) && rf.getType().resolve(rf.getDeclaringClass()).isClass(f.getType())) { + assert f.getModifiers() == rf.getModifiers() : f; + return true; + } + } + return false; + } + + public static boolean containsField(Set fields, ResolvedJavaField rf) { + for (Field f : fields) { + if (f.getName().equals(rf.getName()) && rf.getType().resolve(rf.getDeclaringClass()).isClass(f.getType())) { + assert rf.getModifiers() == f.getModifiers() : rf; + return true; + } + } + return false; + } + + private static boolean isHiddenFromReflection(ResolvedJavaField f) { + if (f.getDeclaringClass().isClass(Throwable.class) && f.getName().equals("backtrace")) { + return true; + } + if (f.getDeclaringClass().isClass(ConstantPool.class) && f.getName().equals("constantPoolOop")) { + return true; + } + return false; + } + + @Test + public void getInstanceFieldsTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + for (boolean includeSuperclasses : new boolean[] {true, false}) { + Set expected = getInstanceFields(c, includeSuperclasses); + ResolvedJavaField[] actual = type.getInstanceFields(includeSuperclasses); + for (Field f : expected) { + assertTrue(containsField(actual, f)); + } + for (ResolvedJavaField rf : actual) { + if (!isHiddenFromReflection(rf)) { + assertEquals(containsField(expected, rf), !rf.isInternal()); + } + } + + // Test stability of getInstanceFields + ResolvedJavaField[] actual2 = type.getInstanceFields(includeSuperclasses); + assertArrayEquals(actual, actual2); + } + } + } + + @Test + public void getAnnotationTest() { + for (Class c : classes) { + ResolvedJavaType type = runtime.lookupJavaType(c); + for (Annotation a : c.getAnnotations()) { + assertEquals(a, type.getAnnotation(a.annotationType())); + } + } + } +} diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java Tue Nov 27 11:21:48 2012 +0100 @@ -33,7 +33,8 @@ /** * Returns the Java language modifiers for this field, as an integer. The {@link Modifier} class should be used to - * decode the modifiers. Only the flags specified in the JVM specification will be included in the returned mask. + * decode the modifiers. Only the {@linkplain Modifier#fieldModifiers() field flags} specified in the JVM + * specification will be included in the returned mask. */ int getModifiers(); diff -r 8c4b757c2eb9 -r dd81042f4eb1 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 Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Tue Nov 27 11:21:48 2012 +0100 @@ -35,7 +35,7 @@ /** * Returns the bytecodes of this method, if the method has code. The returned byte array does not contain * breakpoints or non-Java bytecodes. - * + * * @return the bytecodes of the method, or {@code null} if none is available */ byte[] getCode(); @@ -43,21 +43,21 @@ /** * Returns the size of the bytecodes of this method, if the method has code. This is equivalent to * {@link #getCode()}. {@code length} if the method has code. - * + * * @return the size of the bytecodes in bytes, or 0 if no bytecodes is available */ int getCodeSize(); /** * Returns the size of the compiled machine code of this method. - * + * * @return the size of the compiled machine code in bytes, or 0 if no compiled code exists. */ int getCompiledCodeSize(); /** * Returns an estimate how complex it is to compile this method. - * + * * @return A value >= 0, where higher means more complex. */ int getCompilationComplexity(); @@ -79,20 +79,21 @@ /** * Returns the Java language modifiers for this method, as an integer. The {@link Modifier} class should be used to - * decode the modifiers. Only the flags specified in the JVM specification will be included in the returned mask. + * decode the modifiers. Only the {@linkplain Modifier#methodModifiers() method flags} specified in the JVM + * specification will be included in the returned mask. */ int getModifiers(); /** * Checks whether this method is a class initializer. - * + * * @return {@code true} if the method is a class initializer */ boolean isClassInitializer(); /** * Checks whether this method is a constructor. - * + * * @return {@code true} if the method is a constructor */ boolean isConstructor(); @@ -100,7 +101,7 @@ /** * Checks whether this method can be statically bound (usually, that means it is final or private or static, but not * abstract). - * + * * @return {@code true} if this method can be statically bound */ boolean canBeStaticallyBound(); @@ -132,7 +133,7 @@ /** * Returns the annotation for the specified type of this method, if such an annotation is present. - * + * * @param annotationClass the Class object corresponding to the annotation type * @return this element's annotation for the specified annotation type if present on this method, else {@code null} */ @@ -141,7 +142,7 @@ /** * Returns an array of arrays that represent the annotations on the formal parameters, in declaration order, of this * method. - * + * * @see Method#getParameterAnnotations() */ Annotation[][] getParameterAnnotations(); @@ -149,7 +150,7 @@ /** * Returns an array of {@link Type} objects that represent the formal parameter types, in declaration order, of this * method. - * + * * @see Method#getGenericParameterTypes() */ Type[] getGenericParameterTypes(); diff -r 8c4b757c2eb9 -r dd81042f4eb1 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 Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Tue Nov 27 11:21:48 2012 +0100 @@ -127,8 +127,9 @@ * * @param other the type to test * @return {@code true} if this type a subtype of the specified type + * @see Class#isAssignableFrom(Class) */ - boolean isSubtypeOf(ResolvedJavaType other); + boolean isAssignableTo(ResolvedJavaType other); /** * Checks whether the specified object is an instance of this type. @@ -170,7 +171,8 @@ ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType); /** - * Attempts to get the unique concrete subclass of this type. + * Gets the unique concrete subclass of this type. + * *

* If the compiler uses the result of this method for its compilation, it must register an assumption because * dynamic class loading can invalidate the result of this method. @@ -192,14 +194,14 @@ ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method); /** - * Given a {@link ResolvedJavaMethod} a, returns a concrete {@link ResolvedJavaMethod} b that is the only possible - * unique target for a virtual call on a(). Returns {@code null} if either no such concrete method or more than one - * such method exists. Returns the method a if a is a concrete method that is not overridden. + * Given a {@link ResolvedJavaMethod} A, returns a concrete {@link ResolvedJavaMethod} B that is the only possible + * unique target for a virtual call on A(). Returns {@code null} if either no such concrete method or more than one + * such method exists. Returns the method A if A is a concrete method that is not overridden. *

* If the compiler uses the result of this method for its compilation, it must register an assumption because * dynamic class loading can invalidate the result of this method. * - * @param method the method a for which a unique concrete target is searched + * @param method the method A for which a unique concrete target is searched * @return the unique concrete target or {@code null} if no such target exists or assumptions are not supported by * this runtime */ diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Nov 27 11:21:48 2012 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.graph.FieldIntrospection.*; + import java.lang.reflect.*; import com.oracle.graal.api.code.*; @@ -70,6 +72,16 @@ return wordKind; } + /** + * Reads a word value from a given address. + */ + public static long unsafeReadWord(long address) { + if (wordKind.isLong()) { + return unsafe.getLong(address); + } + return unsafe.getInt(address); + } + protected final CompilerToVM compilerToVm; protected final VMToCompiler vmToCompiler; diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Nov 27 11:21:48 2012 +0100 @@ -63,6 +63,16 @@ public int prototypeMarkWordOffset; /** + * The offset of the _subklass field in a Klass. + */ + public int subklassOffset; + + /** + * The offset of the _next_sibling field in a Klass. + */ + public int nextSiblingOffset; + + /** * The offset of the array length word in an array object's header. */ public int arrayLengthOffset; diff -r 8c4b757c2eb9 -r dd81042f4eb1 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 Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Nov 27 11:21:48 2012 +0100 @@ -142,18 +142,12 @@ JavaMethod resolveMethod(HotSpotResolvedJavaType klass, String name, String signature); - boolean isSubtypeOf(HotSpotResolvedJavaType klass, JavaType other); - - JavaType getLeastCommonAncestor(HotSpotResolvedJavaType thisType, HotSpotResolvedJavaType otherType); - boolean isTypeInitialized(HotSpotResolvedJavaType klass); void initializeType(HotSpotResolvedJavaType klass); ResolvedJavaType getResolvedType(Class javaClass); - JavaType getUniqueConcreteSubtype(HotSpotResolvedJavaType klass); - HotSpotResolvedJavaField[] getInstanceFields(HotSpotResolvedJavaType klass); /** diff -r 8c4b757c2eb9 -r dd81042f4eb1 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 Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Nov 27 11:21:48 2012 +0100 @@ -89,15 +89,6 @@ public native JavaMethod resolveMethod(HotSpotResolvedJavaType klass, String name, String signature); @Override - public native boolean isSubtypeOf(HotSpotResolvedJavaType klass, JavaType other); - - @Override - public native JavaType getLeastCommonAncestor(HotSpotResolvedJavaType thisType, HotSpotResolvedJavaType otherType); - - @Override - public native JavaType getUniqueConcreteSubtype(HotSpotResolvedJavaType klass); - - @Override public native boolean isTypeInitialized(HotSpotResolvedJavaType klass); @Override diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotJavaType.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotJavaType.java Tue Nov 27 11:21:48 2012 +0100 @@ -41,9 +41,4 @@ public final String getName() { return name; } - - /** - * Gets the address of the C++ Klass object for this type. - */ - public abstract Constant klass(); } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Tue Nov 27 11:21:48 2012 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.util.*; @@ -141,9 +142,9 @@ return unsafe.getInt(null, metaspaceMethodData + fullOffsetInBytes); } - private long readLong(int position, int offsetInBytes) { + private long readWord(int position, int offsetInBytes) { long fullOffsetInBytes = computeFullOffset(position, offsetInBytes); - return unsafe.getLong(null, metaspaceMethodData + fullOffsetInBytes); + return unsafeReadWord(metaspaceMethodData + fullOffsetInBytes); } private static int truncateLongToInt(long value) { @@ -340,10 +341,9 @@ int entries = 0; for (int i = 0; i < typeProfileWidth; i++) { - long receiverKlass = data.readLong(position, getReceiverOffset(i)); + long receiverKlass = data.readWord(position, getReceiverOffset(i)); if (receiverKlass != 0) { types[entries] = HotSpotResolvedJavaType.fromMetaspaceKlass(receiverKlass); - long count = data.readUnsignedInt(position, getCountOffset(i)); totalCount += count; counts[entries] = count; diff -r 8c4b757c2eb9 -r dd81042f4eb1 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 Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Nov 27 11:21:48 2012 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.lang.annotation.*; import java.lang.reflect.*; @@ -199,7 +200,7 @@ ProfilingInfo info; if (GraalOptions.UseProfilingInformation && methodData == null) { - long metaspaceMethodData = unsafe.getLong(null, metaspaceMethod + HotSpotGraalRuntime.getInstance().getConfig().methodDataOffset); + long metaspaceMethodData = unsafeReadWord(metaspaceMethod + HotSpotGraalRuntime.getInstance().getConfig().methodDataOffset); if (metaspaceMethodData != 0) { methodData = new HotSpotMethodData(metaspaceMethodData); } diff -r 8c4b757c2eb9 -r dd81042f4eb1 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 Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Tue Nov 27 11:21:48 2012 +0100 @@ -23,6 +23,8 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static java.lang.reflect.Modifier.*; import java.lang.annotation.*; import java.lang.reflect.*; @@ -162,16 +164,27 @@ if (isArrayClass()) { return getComponentType().findUniqueConcreteSubtype() == getComponentType() ? this : null; } else { - ResolvedJavaType subtype = (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getUniqueConcreteSubtype(this); - assert subtype == null || !subtype.isInterface(); - return subtype; + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + HotSpotResolvedJavaType type = this; + while (isAbstract(type.getModifiers())) { + long subklass = unsafeReadWord(type.metaspaceKlass + config.subklassOffset); + if (subklass == 0 || unsafeReadWord(subklass + config.nextSiblingOffset) != 0) { + return null; + } + type = (HotSpotResolvedJavaType) fromMetaspaceKlass(subklass); + } + if (unsafeReadWord(type.metaspaceKlass + config.subklassOffset) != 0) { + return null; + } + assert !type.isInterface(); + return type; } } @Override - public ResolvedJavaType getSuperclass() { + public HotSpotResolvedJavaType getSuperclass() { Class javaSuperclass = javaMirror.getSuperclass(); - return javaSuperclass == null ? null : fromClass(javaSuperclass); + return javaSuperclass == null ? null : (HotSpotResolvedJavaType) fromClass(javaSuperclass); } @Override @@ -187,12 +200,37 @@ return interfaces; } + public HotSpotResolvedJavaType getSupertype() { + if (isArrayClass()) { + ResolvedJavaType componentType = getComponentType(); + if (javaMirror == Object[].class || componentType instanceof HotSpotTypePrimitive) { + return (HotSpotResolvedJavaType) fromClass(Object.class); + } + return (HotSpotResolvedJavaType) ((HotSpotResolvedJavaType) componentType).getSupertype().getArrayClass(); + } + if (isInterface()) { + return (HotSpotResolvedJavaType) fromClass(Object.class); + } + return getSuperclass(); + } + @Override public ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType) { if (otherType instanceof HotSpotTypePrimitive) { return null; } else { - return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().getCompilerToVM().getLeastCommonAncestor(this, (HotSpotResolvedJavaType) otherType); + HotSpotResolvedJavaType t1 = this; + HotSpotResolvedJavaType t2 = (HotSpotResolvedJavaType) otherType; + while (true) { + if (t2.isAssignableTo(t1)) { + return t1; + } + if (t1.isAssignableTo(t2)) { + return t2; + } + t1 = t1.getSupertype(); + t2 = t2.getSupertype(); + } } } @@ -271,11 +309,11 @@ } @Override - public boolean isSubtypeOf(ResolvedJavaType other) { + public boolean isAssignableTo(ResolvedJavaType other) { if (other instanceof HotSpotResolvedJavaType) { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().isSubtypeOf(this, other); + HotSpotResolvedJavaType otherType = (HotSpotResolvedJavaType) other; + return otherType.javaMirror.isAssignableFrom(javaMirror); } - // No resolved type is a subtype of an unresolved type. return false; } @@ -409,7 +447,9 @@ return this; } - @Override + /** + * Gets the address of the C++ Klass object for this type. + */ public Constant klass() { return new Constant(HotSpotGraalRuntime.getInstance().getTarget().wordKind, metaspaceKlass, this); } diff -r 8c4b757c2eb9 -r dd81042f4eb1 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 Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypePrimitive.java Tue Nov 27 11:21:48 2012 +0100 @@ -122,7 +122,10 @@ } @Override - public boolean isSubtypeOf(ResolvedJavaType other) { + public boolean isAssignableTo(ResolvedJavaType other) { + if (other instanceof HotSpotTypePrimitive) { + return other == this; + } return false; } @@ -177,11 +180,6 @@ } @Override - public Constant klass() { - throw GraalInternalError.shouldNotReachHere("HotSpotTypePrimitive.klass()"); - } - - @Override public void initialize() { } } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotTypeUnresolved.java Tue Nov 27 11:21:48 2012 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; /** @@ -88,9 +87,4 @@ public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { return (ResolvedJavaType) HotSpotGraalRuntime.getInstance().lookupType(getName(), (HotSpotResolvedJavaType) accessingClass, true); } - - @Override - public Constant klass() { - throw GraalInternalError.shouldNotReachHere("HotSpotTypeUnresolved.klass()"); - } } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Tue Nov 27 11:21:48 2012 +0100 @@ -297,7 +297,7 @@ static ConstantNode[] createHints(TypeCheckHints hints, MetaAccessProvider runtime, Graph graph) { ConstantNode[] hintHubs = new ConstantNode[hints.types.length]; for (int i = 0; i < hintHubs.length; i++) { - hintHubs[i] = ConstantNode.forConstant(((HotSpotJavaType) hints.types[i]).klass(), runtime, graph); + hintHubs[i] = ConstantNode.forConstant(((HotSpotResolvedJavaType) hints.types[i]).klass(), runtime, graph); } return hintHubs; } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/IntrinsifyArrayCopyPhase.java Tue Nov 27 11:21:48 2012 +0100 @@ -106,7 +106,7 @@ snippetMethod = objectArrayCopy; } } else if (componentKind == Kind.Object - && srcType.getComponentType().isSubtypeOf(destType.getComponentType())) { + && srcType.getComponentType().isAssignableTo(destType.getComponentType())) { snippetMethod = objectArrayCopy; } } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Nov 27 11:21:48 2012 +0100 @@ -1407,7 +1407,7 @@ if (initialized && graphBuilderConfig.getSkippedExceptionTypes() != null) { ResolvedJavaType resolvedCatchType = (ResolvedJavaType) catchType; for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) { - initialized &= !resolvedCatchType.isSubtypeOf(skippedType); + initialized &= !resolvedCatchType.isAssignableTo(skippedType); if (!initialized) { break; } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Tue Nov 27 11:21:48 2012 +0100 @@ -68,7 +68,7 @@ if (my.nonNull() && !other.nonNull()) { return this; } - if (my.type() != other.type() && my.type().isSubtypeOf(other.type())) { + if (my.type() != other.type() && my.type().isAssignableTo(other.type())) { return this; } } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue Nov 27 11:21:48 2012 +0100 @@ -72,7 +72,7 @@ if (type != null) { ResolvedJavaType objectType = object().objectStamp().type(); - if (objectType != null && objectType.isSubtypeOf(type)) { + if (objectType != null && objectType.isAssignableTo(type)) { // we don't have to check for null types here because they will also pass the checkcast. return object(); } @@ -102,7 +102,7 @@ @Override public void virtualize(VirtualizerTool tool) { VirtualObjectNode virtual = tool.getVirtualState(object()); - if (virtual != null && virtual.type().isSubtypeOf(type())) { + if (virtual != null && virtual.type().isAssignableTo(type())) { tool.replaceWithVirtual(virtual); } } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Tue Nov 27 11:21:48 2012 +0100 @@ -70,7 +70,7 @@ ResolvedJavaType stampType = stamp.type(); if (stamp.isExactType()) { - boolean subType = stampType.isSubtypeOf(type()); + boolean subType = stampType.isAssignableTo(type()); if (subType) { if (stamp.nonNull()) { @@ -87,7 +87,7 @@ return ConstantNode.forBoolean(false, graph()); } } else if (stampType != null) { - boolean subType = stampType.isSubtypeOf(type()); + boolean subType = stampType.isAssignableTo(type()); if (subType) { if (stamp.nonNull()) { @@ -135,7 +135,7 @@ public void virtualize(VirtualizerTool tool) { VirtualObjectNode virtual = tool.getVirtualState(object()); if (virtual != null) { - tool.replaceWithValue(ConstantNode.forBoolean(virtual.type().isSubtypeOf(type()), graph())); + tool.replaceWithValue(ConstantNode.forBoolean(virtual.type().isAssignableTo(type()), graph())); } } } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Tue Nov 27 11:21:48 2012 +0100 @@ -98,7 +98,7 @@ if (stamp.type() != null) { int validKeys = 0; for (int i = 0; i < keyCount(); i++) { - if (keys[i].isSubtypeOf(stamp.type())) { + if (keys[i].isAssignableTo(stamp.type())) { validKeys++; } } @@ -113,7 +113,7 @@ double totalProbability = 0; int current = 0; for (int i = 0; i < keyCount() + 1; i++) { - if (i == keyCount() || keys[i].isSubtypeOf(stamp.type())) { + if (i == keyCount() || keys[i].isAssignableTo(stamp.type())) { int index = newSuccessors.indexOf(keySuccessor(i)); if (index == -1) { index = newSuccessors.size(); diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/ObjectStamp.java Tue Nov 27 11:21:48 2012 +0100 @@ -78,7 +78,7 @@ return false; } else if (other.nonNull || nonNull) { // One of the two values cannot be null. - return !other.type.isInterface() && !type.isInterface() && !other.type.isSubtypeOf(type) && !type.isSubtypeOf(other.type); + return !other.type.isInterface() && !type.isInterface() && !other.type.isAssignableTo(type) && !type.isAssignableTo(other.type); } return false; } @@ -139,7 +139,7 @@ joinType = type; } else { // both types are != null - if (other.type.isSubtypeOf(type)) { + if (other.type.isAssignableTo(type)) { joinType = other.type; } else { joinType = type; diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Tue Nov 27 11:21:48 2012 +0100 @@ -240,9 +240,9 @@ return a; } else if (a == b) { return a; - } else if (a.isSubtypeOf(b)) { + } else if (a.isAssignableTo(b)) { return a; - } else if (b.isSubtypeOf(a)) { + } else if (b.isAssignableTo(a)) { return b; } else { return a; @@ -326,7 +326,7 @@ } else if (node instanceof CheckCastNode) { CheckCastNode checkCast = (CheckCastNode) node; ResolvedJavaType type = state.getNodeType(checkCast.object()); - if (type != null && type.isSubtypeOf(checkCast.type())) { + if (type != null && type.isAssignableTo(checkCast.type())) { PiNode piNode; boolean nonNull = state.knownNotNull.contains(checkCast.object()); piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type))); @@ -351,7 +351,7 @@ replaceWith = ConstantNode.forBoolean(false, graph); } else if (state.knownNotNull.contains(object)) { ResolvedJavaType type = state.getNodeType(object); - if (type != null && type.isSubtypeOf(instanceOf.type())) { + if (type != null && type.isAssignableTo(instanceOf.type())) { replaceWith = ConstantNode.forBoolean(true, graph); } } diff -r 8c4b757c2eb9 -r dd81042f4eb1 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Nov 27 11:18:34 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Nov 27 11:21:48 2012 +0100 @@ -610,7 +610,7 @@ ObjectStamp receiverStamp = callTarget.receiver().objectStamp(); ResolvedJavaType receiverType = receiverStamp.type(); if (receiverStamp.isExactType()) { - assert receiverType.isSubtypeOf(targetMethod.getDeclaringClass()) : receiverType + " subtype of " + targetMethod.getDeclaringClass() + " for " + targetMethod; + assert receiverType.isAssignableTo(targetMethod.getDeclaringClass()) : receiverType + " subtype of " + targetMethod.getDeclaringClass() + " for " + targetMethod; ResolvedJavaMethod resolved = receiverType.resolveMethod(targetMethod); if (checkTargetConditions(invoke, resolved, optimisticOpts)) { double weight = callback == null ? 0 : callback.inliningWeight(parent, resolved, invoke); @@ -623,7 +623,7 @@ if (receiverStamp.type() != null) { // the invoke target might be more specific than the holder (happens after inlining: locals lose their declared type...) // TODO (lstadler) fix this - if (receiverType != null && receiverType.isSubtypeOf(holder)) { + if (receiverType != null && receiverType.isAssignableTo(holder)) { holder = receiverType; } } diff -r 8c4b757c2eb9 -r dd81042f4eb1 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Nov 27 11:18:34 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Nov 27 11:21:48 2012 +0100 @@ -504,31 +504,6 @@ return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); C2V_END -C2V_VMENTRY(jboolean, isSubtypeOf, (JNIEnv *, jobject, jobject klass, jobject jother)) - oop other = JNIHandles::resolve(jother); - assert(other->is_a(HotSpotResolvedJavaType::klass()), "resolved HotSpot type expected"); - assert(JNIHandles::resolve(klass) != NULL, ""); - Klass* thisKlass = java_lang_Class::as_Klass(HotSpotResolvedJavaType::javaMirror(klass)); - Klass* otherKlass = java_lang_Class::as_Klass(HotSpotResolvedJavaType::javaMirror(other)); - if (thisKlass->oop_is_instance()) { - return InstanceKlass::cast(thisKlass)->is_subtype_of(otherKlass); - } else if (thisKlass->oop_is_array()) { - return ArrayKlass::cast(thisKlass)->is_subtype_of(otherKlass); - } else { - fatal("unexpected class type"); - return false; - } -C2V_END - -C2V_VMENTRY(jobject, getLeastCommonAncestor, (JNIEnv *, jobject, jobject this_type, jobject other_type)) - - Klass* this_klass = java_lang_Class::as_Klass(HotSpotResolvedJavaType::javaMirror(this_type)); - Klass* other_klass = java_lang_Class::as_Klass(HotSpotResolvedJavaType::javaMirror(other_type)); - Klass* lca = this_klass->LCA(other_klass); - - return JNIHandles::make_local(GraalCompiler::get_JavaType(lca, THREAD)()); -C2V_END - C2V_VMENTRY(jlong, getPrototypeMarkWord, (JNIEnv *, jobject, jobject klass)) KlassHandle klass_handle(java_lang_Class::as_Klass(HotSpotResolvedJavaType::javaMirror(klass))); if (klass_handle->oop_is_array()) { @@ -538,15 +513,6 @@ } C2V_END -C2V_VMENTRY(jobject, getUniqueConcreteSubtype, (JNIEnv *, jobject, jobject klass)) - KlassHandle klass_handle(java_lang_Class::as_Klass(HotSpotResolvedJavaType::javaMirror(klass))); - Klass *up_cast = klass_handle->up_cast_abstract(); - if (!up_cast->is_interface() && up_cast->subklass() == NULL) { - return JNIHandles::make_local(GraalCompiler::get_JavaType(up_cast, THREAD)()); - } - return NULL; -C2V_END - C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass)) Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedJavaType::javaMirror(hotspot_klass)); assert(klass != NULL, "method must not be called for primitive types"); @@ -646,6 +612,8 @@ set_int(env, config, "superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); set_int(env, config, "secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); set_int(env, config, "secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); + set_int(env, config, "subklassOffset", in_bytes(Klass::subklass_offset())); + set_int(env, config, "nextSiblingOffset", in_bytes(Klass::next_sibling_offset())); set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); set_int(env, config, "klassStateOffset", in_bytes(InstanceKlass::init_state_offset())); set_int(env, config, "klassStateFullyInitialized", (int)InstanceKlass::fully_initialized); @@ -962,9 +930,6 @@ {CC"lookupReferencedTypeInPool", CC"("HS_RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, {CC"lookupFieldInPool", CC"("HS_RESOLVED_TYPE"IB)"FIELD, FN_PTR(lookupFieldInPool)}, {CC"resolveMethod", CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(resolveMethod)}, - {CC"isSubtypeOf", CC"("HS_RESOLVED_TYPE TYPE")Z", FN_PTR(isSubtypeOf)}, - {CC"getLeastCommonAncestor", CC"("HS_RESOLVED_TYPE HS_RESOLVED_TYPE")"TYPE, FN_PTR(getLeastCommonAncestor)}, - {CC"getUniqueConcreteSubtype", CC"("HS_RESOLVED_TYPE")"TYPE, FN_PTR(getUniqueConcreteSubtype)}, {CC"getPrototypeMarkWord", CC"("HS_RESOLVED_TYPE")J", FN_PTR(getPrototypeMarkWord)}, {CC"getInstanceFields", CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD, FN_PTR(getInstanceFields)}, {CC"isTypeInitialized", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(isTypeInitialized)},