changeset 22011:4c9d4fe1cbd8

Add ModifiersProvider.isSynthetic, isVarArgs and isBridge. getModifiers now returns the JVM modifiers (not masked by Modifier.methodModifiers() for example)
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Thu, 18 Jun 2015 17:51:05 +0200
parents 78f2cb84bb41
children 53b4acee50f1
files graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedJavaFieldImpl.java jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedJavaMethodImpl.java jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/MetaUtil.java jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ModifiersProvider.java jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaMethod.java jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestMetaAccessProvider.java jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaMethod.java jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaType.java jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TypeUniverse.java
diffstat 11 files changed, 148 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Thu Jun 18 17:51:05 2015 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.hotspot.test;
 
-import static com.oracle.jvmci.hotspot.HotSpotResolvedObjectTypeImpl.*;
-
 import java.lang.reflect.*;
 
 import org.junit.*;
@@ -49,7 +47,7 @@
             HotSpotResolvedObjectType type = HotSpotResolvedObjectTypeImpl.fromObjectClass(c);
             for (ResolvedJavaField field : type.getInstanceFields(false)) {
                 if (field.isInternal()) {
-                    Assert.assertEquals(0, ~getReflectionFieldModifiers() & field.getModifiers());
+                    Assert.assertEquals(0, ~ModifiersProvider.jvmFieldModifiers() & field.getModifiers());
                 }
             }
         }
--- a/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedJavaFieldImpl.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedJavaFieldImpl.java	Thu Jun 18 17:51:05 2015 +0200
@@ -24,7 +24,6 @@
 
 import static com.oracle.jvmci.hotspot.HotSpotJVMCIRuntime.*;
 import static com.oracle.jvmci.hotspot.HotSpotResolvedJavaFieldImpl.Options.*;
-import static com.oracle.jvmci.hotspot.HotSpotResolvedObjectTypeImpl.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -126,7 +125,7 @@
 
     @Override
     public int getModifiers() {
-        return modifiers & getReflectionFieldModifiers();
+        return modifiers & ModifiersProvider.jvmFieldModifiers();
     }
 
     @Override
--- a/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedJavaMethodImpl.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedJavaMethodImpl.java	Thu Jun 18 17:51:05 2015 +0200
@@ -183,7 +183,7 @@
 
     @Override
     public int getModifiers() {
-        return getAllModifiers() & Modifier.methodModifiers();
+        return getAllModifiers() & ModifiersProvider.jvmMethodModifiers();
     }
 
     @Override
@@ -474,12 +474,6 @@
         return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass);
     }
 
-    @Override
-    public boolean isSynthetic() {
-        int modifiers = getAllModifiers();
-        return (runtime().getConfig().syntheticFlag & modifiers) != 0;
-    }
-
     public boolean isDefault() {
         if (isConstructor()) {
             return false;
--- a/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotResolvedObjectTypeImpl.java	Thu Jun 18 17:51:05 2015 +0200
@@ -118,7 +118,11 @@
 
     @Override
     public int getModifiers() {
-        return mirror().getModifiers();
+        if (isArray()) {
+            return (getElementalType().getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)) | Modifier.FINAL | Modifier.ABSTRACT;
+        } else {
+            return getAccessFlags() & ModifiersProvider.jvmClassModifiers();
+        }
     }
 
     public int getAccessFlags() {
@@ -473,19 +477,10 @@
         return result;
     }
 
-    /**
-     * Gets the mask used to filter out HotSpot internal flags for fields when a {@link Field}
-     * object is created. This is the value of {@code JVM_RECOGNIZED_FIELD_MODIFIERS} in
-     * {@code jvm.h}, <b>not</b> {@link Modifier#fieldModifiers()}.
-     */
-    public static int getReflectionFieldModifiers() {
-        return runtime().getConfig().recognizedFieldModifiers;
-    }
-
     public synchronized HotSpotResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags) {
         HotSpotResolvedJavaField result = null;
 
-        final int flags = rawFlags & getReflectionFieldModifiers();
+        final int flags = rawFlags & ModifiersProvider.jvmFieldModifiers();
 
         final long id = offset + ((long) flags << 32);
 
--- a/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/MetaUtil.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/MetaUtil.java	Thu Jun 18 17:51:05 2015 +0200
@@ -23,6 +23,7 @@
 package com.oracle.jvmci.meta;
 
 import java.io.*;
+import java.lang.reflect.*;
 import java.util.*;
 
 /**
@@ -354,4 +355,17 @@
         }
         return obj.getClass().getName() + "@" + System.identityHashCode(obj);
     }
+
+    /**
+     * Used to lookup constants from {@link Modifier} that are not public (VARARGS, SYNTHETIC etc.).
+     */
+    static int getNonPublicModifierStaticField(String name) {
+        try {
+            Field field = Modifier.class.getDeclaredField(name);
+            field.setAccessible(true);
+            return field.getInt(null);
+        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
+            throw new InternalError(e);
+        }
+    }
 }
--- a/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ModifiersProvider.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ModifiersProvider.java	Thu Jun 18 17:51:05 2015 +0200
@@ -31,9 +31,17 @@
  * language {@linkplain #getModifiers() modifiers}.
  */
 public interface ModifiersProvider {
+    int BRIDGE = MetaUtil.getNonPublicModifierStaticField("BRIDGE");
+    int VARARGS = MetaUtil.getNonPublicModifierStaticField("VARARGS");
+    int SYNTHETIC = MetaUtil.getNonPublicModifierStaticField("SYNTHETIC");
+    int ANNOTATION = MetaUtil.getNonPublicModifierStaticField("ANNOTATION");
+    int ENUM = MetaUtil.getNonPublicModifierStaticField("ENUM");
+    int MANDATED = MetaUtil.getNonPublicModifierStaticField("MANDATED");
 
     /**
-     * Returns the Java language modifiers for this element.
+     * Returns the Java Virtual Machine modifiers for this element. Note that this can differ from
+     * standard Java Reflection modifiers. For example at the JVM level, classes (
+     * {@link ResolvedJavaType}) can not be private or protected.
      */
     int getModifiers();
 
@@ -137,4 +145,17 @@
     default boolean isConcrete() {
         return !isAbstract();
     }
+
+    static int jvmClassModifiers() {
+        // no SUPER
+        return PUBLIC | FINAL | INTERFACE | ABSTRACT | ANNOTATION | ENUM | SYNTHETIC;
+    }
+
+    static int jvmMethodModifiers() {
+        return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | SYNCHRONIZED | BRIDGE | VARARGS | NATIVE | ABSTRACT | STRICT | SYNTHETIC;
+    }
+
+    static int jvmFieldModifiers() {
+        return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | ENUM | SYNTHETIC;
+    }
 }
--- a/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaMethod.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.meta/src/com/oracle/jvmci/meta/ResolvedJavaMethod.java	Thu Jun 18 17:51:05 2015 +0200
@@ -23,6 +23,7 @@
 package com.oracle.jvmci.meta;
 
 import java.lang.annotation.*;
+import java.lang.invoke.*;
 import java.lang.reflect.*;
 
 /**
@@ -80,7 +81,31 @@
      * Determines if this method is a synthetic method as defined by the Java Language
      * Specification.
      */
-    boolean isSynthetic();
+    default boolean isSynthetic() {
+        return (SYNTHETIC & getModifiers()) == SYNTHETIC;
+    }
+
+    /**
+     * Checks that the method is a <a
+     * href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">varargs</a>
+     * method.
+     *
+     * @return whether the method is a varargs method
+     */
+    default boolean isVarArgs() {
+        return (VARARGS & getModifiers()) == VARARGS;
+    }
+
+    /**
+     * Checks that the method is a <a
+     * href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">bridge</a>
+     * method.
+     *
+     * @return whether the method is a bridge method
+     */
+    default boolean isBridge() {
+        return (BRIDGE & getModifiers()) == BRIDGE;
+    }
 
     /**
      * Returns {@code true} if this method is a default method; returns {@code false} otherwise.
--- a/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestMetaAccessProvider.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestMetaAccessProvider.java	Thu Jun 18 17:51:05 2015 +0200
@@ -40,13 +40,12 @@
     public void lookupJavaTypeTest() {
         for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
-            assertNotNull(type);
-            assertEquals(c.getModifiers(), type.getModifiers());
-            assertEquals(type.getName(), toInternalName(c.getName()));
-            assertEquals(type.getName(), toInternalName(type.toJavaName()));
-            assertEquals(c.getName(), type.toClassName());
+            assertNotNull(c.toString(), type);
+            assertEquals(c.toString(), type.getName(), toInternalName(c.getName()));
+            assertEquals(c.toString(), type.getName(), toInternalName(type.toJavaName()));
+            assertEquals(c.toString(), c.getName(), type.toClassName());
             if (!type.isArray()) {
-                assertEquals(c.getName(), type.toJavaName());
+                assertEquals(c.toString(), c.getName(), type.toJavaName());
             }
         }
     }
@@ -57,9 +56,6 @@
             for (Method reflect : c.getDeclaredMethods()) {
                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(reflect);
                 assertNotNull(method);
-                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().equals(metaAccess.lookupJavaType(reflect.getDeclaringClass())));
             }
         }
@@ -71,9 +67,6 @@
             for (Field reflect : c.getDeclaredFields()) {
                 ResolvedJavaField field = metaAccess.lookupJavaField(reflect);
                 assertNotNull(field);
-                int expected = reflect.getModifiers();
-                int actual = field.getModifiers();
-                assertEquals(String.format("%s: 0x%x != 0x%x", reflect, expected, actual), expected, actual);
                 assertTrue(field.getDeclaringClass().equals(metaAccess.lookupJavaType(reflect.getDeclaringClass())));
             }
         }
--- a/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaMethod.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaMethod.java	Thu Jun 18 17:51:05 2015 +0200
@@ -22,9 +22,6 @@
  */
 package com.oracle.jvmci.runtime.test;
 
-import com.oracle.jvmci.meta.ExceptionHandler;
-import com.oracle.jvmci.meta.ResolvedJavaMethod;
-import com.oracle.jvmci.meta.ConstantPool;
 import static org.junit.Assert.*;
 
 import java.lang.annotation.*;
@@ -33,6 +30,8 @@
 
 import org.junit.*;
 
+import com.oracle.jvmci.meta.*;
+
 /**
  * Tests for {@link ResolvedJavaMethod}.
  */
@@ -81,9 +80,15 @@
     public void getModifiersTest() {
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
             ResolvedJavaMethod m = e.getValue();
-            int expected = e.getKey().getModifiers() & Modifier.methodModifiers();
+            int expected = e.getKey().getModifiers();
             int actual = m.getModifiers();
-            assertEquals(expected, actual);
+            assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            int expected = e.getKey().getModifiers();
+            int actual = m.getModifiers();
+            assertEquals(String.format("%s: 0x%x != 0x%x", m, expected, actual), expected, actual);
         }
     }
 
@@ -128,6 +133,30 @@
     }
 
     @Test
+    public void isBridgeTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isBridge(), m.isBridge());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(false, m.isBridge());
+        }
+    }
+
+    @Test
+    public void isVarArgsTest() {
+        for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
+        }
+        for (Map.Entry<Constructor<?>, ResolvedJavaMethod> e : constructors.entrySet()) {
+            ResolvedJavaMethod m = e.getValue();
+            assertEquals(e.getKey().isVarArgs(), m.isVarArgs());
+        }
+    }
+
+    @Test
     public void isSynchronizedTest() {
         for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) {
             ResolvedJavaMethod m = e.getValue();
--- a/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaType.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TestResolvedJavaType.java	Thu Jun 18 17:51:05 2015 +0200
@@ -96,9 +96,19 @@
     public void getModifiersTest() {
         for (Class<?> c : classes) {
             ResolvedJavaType type = metaAccess.lookupJavaType(c);
-            int expected = c.getModifiers();
-            int actual = type.getModifiers();
-            assertEquals(expected, actual);
+            int expected = c.getModifiers() & ModifiersProvider.jvmClassModifiers();
+            int actual = type.getModifiers() & ModifiersProvider.jvmClassModifiers();
+            Class<?> elementalType = c;
+            while (elementalType.isArray()) {
+                elementalType = elementalType.getComponentType();
+            }
+            if (elementalType.isMemberClass()) {
+                // member class get their modifiers from the inner-class attribute in the JVM and
+                // from the classfile header in jvmci
+                expected &= ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
+                actual &= ~(Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
+            }
+            assertEquals(String.format("%s: 0x%x != 0x%x", type, expected, actual), expected, actual);
         }
     }
 
--- a/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TypeUniverse.java	Wed Jun 17 15:34:39 2015 +0200
+++ b/jvmci/com.oracle.jvmci.runtime.test/src/com/oracle/jvmci/runtime/test/TypeUniverse.java	Thu Jun 18 17:51:05 2015 +0200
@@ -55,6 +55,26 @@
 
     private static List<ConstantValue> constants;
 
+    public class InnerClass {
+
+    }
+
+    public static class InnerStaticClass {
+
+    }
+
+    public static final class InnerStaticFinalClass {
+
+    }
+
+    private class PrivateInnerClass {
+
+    }
+
+    protected class ProtectedInnerClass {
+
+    }
+
     static {
         Unsafe theUnsafe = null;
         try {
@@ -71,10 +91,11 @@
         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, boolean[].class,
-                        byte[].class, short[].class, char[].class, int[].class, float[].class, long[].class, double[].class, Object[].class, Class[].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, TrustedInterface.class};
+                        byte[].class, short[].class, char[].class, int[].class, float[].class, long[].class, double[].class, Object[].class, Class[].class, List[].class, boolean[][].class,
+                        byte[][].class, short[][].class, char[][].class, int[][].class, float[][].class, long[][].class, double[][].class, Object[][].class, Class[][].class, List[][].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, TrustedInterface.class, InnerClass.class,
+                        InnerStaticClass.class, InnerStaticFinalClass.class, PrivateInnerClass.class, ProtectedInnerClass.class};
         for (Class<?> c : initialClasses) {
             addClass(c);
         }