changeset 13823:6dd8b95a7fbb

fixed HotSpotResolvedJavaField.getModifiers() to mask out FIELD_INTERNAL_FLAG
author Doug Simon <doug.simon@oracle.com>
date Thu, 30 Jan 2014 14:16:19 +0100
parents 35fc64972250
children ccba891bde48
files graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedObjectTypeTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java
diffstat 4 files changed, 124 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedJavaFieldTest.java	Thu Jan 30 14:16:19 2014 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.test;
+
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*;
+import static java.lang.reflect.Modifier.*;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.hotspot.meta.*;
+
+/**
+ * Tests {@link HotSpotResolvedJavaField} functionality.
+ */
+public class HotSpotResolvedJavaFieldTest {
+
+    private static final Class[] classesWithInternalFields = {Class.class, ClassLoader.class};
+
+    /**
+     * Tests that {@link HotSpotResolvedJavaField#getModifiers()} only includes the modifiers
+     * returned by {@link Field#getModifiers()}. Namely, it must not include
+     * {@code HotSpotResolvedJavaField#FIELD_INTERNAL_FLAG}.
+     */
+    @Test
+    public void testModifiersForInternal() {
+        for (Class c : classesWithInternalFields) {
+            ResolvedJavaType type = HotSpotResolvedObjectType.fromClass(c);
+            for (ResolvedJavaField field : type.getInstanceFields(false)) {
+                if (field.isInternal()) {
+                    Assert.assertEquals(0, ~getReflectionFieldModifiers() & field.getModifiers());
+                }
+            }
+        }
+    }
+
+    /**
+     * Tests that
+     * {@link HotSpotResolvedObjectType#createField(String, JavaType, long, int, boolean)} always
+     * returns the same object for an internal field.
+     */
+    @Test
+    public void testCachingForInternalFields() {
+        for (Class c : classesWithInternalFields) {
+            HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c);
+            for (ResolvedJavaField field : type.getInstanceFields(false)) {
+                if (field.isInternal()) {
+                    HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field;
+                    ResolvedJavaField actual = type.createField(expected.getName(), expected.getType(), expected.offset(), expected.getModifiers(), expected.isInternal());
+                    Assert.assertEquals(expected, actual);
+                }
+            }
+        }
+    }
+
+    @Test
+    public void testIsInObject() {
+        for (Field f : String.class.getDeclaredFields()) {
+            HotSpotResolvedJavaField rf = (HotSpotResolvedJavaField) runtime().getHostProviders().getMetaAccess().lookupJavaField(f);
+            Assert.assertEquals(rf.toString(), rf.isInObject("a string"), !isStatic(rf.getModifiers()));
+        }
+    }
+}
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedObjectTypeTest.java	Thu Jan 30 13:21:15 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotResolvedObjectTypeTest.java	Thu Jan 30 14:16:19 2014 +0100
@@ -24,13 +24,12 @@
 
 import org.junit.*;
 
-import com.oracle.graal.compiler.test.*;
 import com.oracle.graal.hotspot.meta.*;
 
 /**
  * Tests {@link HotSpotResolvedObjectType} functionality.
  */
-public class HotSpotResolvedObjectTypeTest extends GraalCompilerTest {
+public class HotSpotResolvedObjectTypeTest {
 
     @Test
     public void testGetSourceFileName() throws Throwable {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Thu Jan 30 13:21:15 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java	Thu Jan 30 14:16:19 2014 +0100
@@ -24,7 +24,9 @@
 
 import static com.oracle.graal.api.meta.MetaUtil.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
+import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectType.*;
 import static com.oracle.graal.phases.GraalOptions.*;
+import static java.lang.reflect.Modifier.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
@@ -53,11 +55,17 @@
     private final String name;
     private final JavaType type;
     private final int offset;
-    private final int modifiers;
     private Constant constant;
 
+    /**
+     * The {@linkplain HotSpotResolvedObjectType#getReflectionFieldModifiers() reflection} modifiers
+     * for this field plus the {@link #FIELD_INTERNAL_FLAG} if it applies.
+     */
+    private final int modifiersWithInternal;
+
     public HotSpotResolvedJavaField(HotSpotResolvedObjectType holder, String name, JavaType type, long offset, int modifiers, boolean internal) {
         assert (modifiers & FIELD_INTERNAL_FLAG) == 0;
+        assert (modifiers & ~getReflectionFieldModifiers()) == 0;
         this.holder = holder;
         this.name = name;
         this.type = type;
@@ -65,20 +73,20 @@
         assert offset == (int) offset : "offset larger than int";
         this.offset = (int) offset;
         if (internal) {
-            this.modifiers = modifiers | FIELD_INTERNAL_FLAG;
+            this.modifiersWithInternal = modifiers | FIELD_INTERNAL_FLAG;
         } else {
-            this.modifiers = modifiers;
+            this.modifiersWithInternal = modifiers;
         }
     }
 
     @Override
     public int getModifiers() {
-        return modifiers;
+        return modifiersWithInternal & getReflectionFieldModifiers();
     }
 
     @Override
     public boolean isInternal() {
-        return (modifiers & FIELD_INTERNAL_FLAG) != 0;
+        return (modifiersWithInternal & FIELD_INTERNAL_FLAG) != 0;
     }
 
     /**
@@ -180,7 +188,7 @@
         assert !ImmutableCode.getValue() || isCalledForSnippets() : receiver;
 
         if (receiver == null) {
-            assert Modifier.isStatic(modifiers);
+            assert isStatic(modifiersWithInternal);
             if (constant == null) {
                 if (holder.isInitialized() && !holder.getName().equals(SystemClassName) && isEmbeddable()) {
                     if (Modifier.isFinal(getModifiers())) {
@@ -194,7 +202,7 @@
              * for non-static final fields, we must assume that they are only initialized if they
              * have a non-default value.
              */
-            assert !Modifier.isStatic(modifiers);
+            assert !isStatic(modifiersWithInternal);
             Object object = receiver.asObject();
 
             // Canonicalization may attempt to process an unsafe read before
@@ -226,21 +234,27 @@
 
     /**
      * Determines if a given object contains this field.
+     * 
+     * @return true iff this is a non-static field and its declaring class is assignable from
+     *         {@code object}'s class
      */
     public boolean isInObject(Object object) {
+        if (isStatic(modifiersWithInternal)) {
+            return false;
+        }
         return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectType.fromClass(object.getClass()));
     }
 
     @Override
     public Constant readValue(Constant receiver) {
         if (receiver == null) {
-            assert Modifier.isStatic(modifiers);
+            assert isStatic(modifiersWithInternal);
             if (holder.isInitialized()) {
                 return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), holder.mirror(), offset, getKind() == Kind.Object);
             }
             return null;
         } else {
-            assert !Modifier.isStatic(modifiers);
+            assert !isStatic(modifiersWithInternal);
             Object object = receiver.asObject();
             assert object != null && isInObject(object);
             return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), object, offset, getKind() == Kind.Object);
@@ -296,11 +310,7 @@
 
     @Override
     public boolean isSynthetic() {
-        Field javaField = toJava();
-        if (javaField != null) {
-            return javaField.isSynthetic();
-        }
-        return false;
+        return (runtime().getConfig().syntheticFlag & modifiersWithInternal) != 0;
     }
 
     /**
@@ -323,6 +333,9 @@
     }
 
     private Field toJava() {
+        if (isInternal()) {
+            return null;
+        }
         try {
             return holder.mirror().getDeclaredField(name);
         } catch (NoSuchFieldException e) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Jan 30 13:21:15 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java	Thu Jan 30 14:16:19 2014 +0100
@@ -418,16 +418,19 @@
         return method;
     }
 
+    /**
+     * 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 ResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags, boolean internal) {
         ResolvedJavaField result = null;
 
-        /*
-         * Filter flags to be only those return by Field.getModifiers() to get a canonical id value.
-         * Strangely, Field.getModifiers() uses JVM_RECOGNIZED_FIELD_MODIFIERS in jvm.h instead of
-         * Modifier.fieldModifiers() to mask out HotSpot internal flags.
-         */
-        int reflectionFieldModifiers = runtime().getConfig().recognizedFieldModifiers;
-        int flags = rawFlags & reflectionFieldModifiers;
+        int flags = rawFlags & getReflectionFieldModifiers();
 
         long id = offset + ((long) flags << 32);