changeset 18465:f0a8b72315c1

Move ResolvedJavaField#read[Constant]Value and getMethodHandleAccess() to ConstantReflectionProvider
author Andreas Woess <andreas.woess@jku.at>
date Wed, 19 Nov 2014 17:00:12 +0100
parents e6b6463c9c06
children 2d2fcdbae37b
files CHANGELOG.md graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaField.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantReflectionProvider.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java
diffstat 21 files changed, 284 insertions(+), 270 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Wed Nov 19 16:06:49 2014 +0100
+++ b/CHANGELOG.md	Wed Nov 19 17:00:12 2014 +0100
@@ -4,6 +4,7 @@
 ### Graal
 * Changed name suite specification from `mx/projects.py` to `mx/suite.py`.
 * Changed semantics (and signature) of `ResolvedJavaType#resolveMethod()` (old behavior available via `resolveConcreteMethod()`).
+* Moved `ResolvedJavaField#read[Constant]Value` and `getMethodHandleAccess()` to `ConstantReflectionProvider`.
 * ...
 
 ### Truffle
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaField.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaField.java	Wed Nov 19 17:00:12 2014 +0100
@@ -78,7 +78,7 @@
             if (isStatic(field.getModifiers())) {
                 try {
                     Object expected = field.get(null);
-                    Object actual = snippetReflection.asBoxedValue(e.getValue().readConstantValue(null));
+                    Object actual = snippetReflection.asBoxedValue(constantReflection.readConstantFieldValue(e.getValue(), null));
                     assertEquals(expected, actual);
                 } catch (IllegalArgumentException | IllegalAccessException e1) {
                 }
@@ -86,7 +86,7 @@
                 try {
                     Object receiver = field.getDeclaringClass().newInstance();
                     Object expected = field.get(receiver);
-                    Object actual = snippetReflection.asBoxedValue(e.getValue().readConstantValue(snippetReflection.forObject(receiver)));
+                    Object actual = snippetReflection.asBoxedValue(constantReflection.readConstantFieldValue(e.getValue(), snippetReflection.forObject(receiver)));
                     assertEquals(expected, actual);
                 } catch (InstantiationException | IllegalArgumentException | IllegalAccessException e1) {
                 }
@@ -95,13 +95,13 @@
 
         ResolvedJavaField field = metaAccess.lookupJavaField(getClass().getDeclaredField("stringField"));
         for (Object receiver : new Object[]{this, null, new String()}) {
-            JavaConstant value = field.readConstantValue(snippetReflection.forObject(receiver));
+            JavaConstant value = constantReflection.readConstantFieldValue(field, snippetReflection.forObject(receiver));
             assertNull(value);
         }
 
         ResolvedJavaField constField = metaAccess.lookupJavaField(getClass().getDeclaredField("constantStringField"));
         for (Object receiver : new Object[]{this, null, new String()}) {
-            JavaConstant value = constField.readConstantValue(snippetReflection.forObject(receiver));
+            JavaConstant value = constantReflection.readConstantFieldValue(constField, snippetReflection.forObject(receiver));
             if (value != null) {
                 Object expected = "constantField";
                 assertTrue(snippetReflection.asObject(value) == expected);
@@ -117,7 +117,7 @@
             if (isStatic(field.getModifiers())) {
                 try {
                     Object expected = field.get(null);
-                    Object actual = snippetReflection.asBoxedValue(e.getValue().readValue(null));
+                    Object actual = snippetReflection.asBoxedValue(constantReflection.readFieldValue(e.getValue(), null));
                     assertEquals(expected, actual);
                 } catch (IllegalArgumentException | IllegalAccessException e1) {
                 }
@@ -131,7 +131,7 @@
             ResolvedJavaField rf = metaAccess.lookupJavaField(f);
             Object receiver = isStatic(f.getModifiers()) ? null : testString;
             Object expected = f.get(receiver);
-            Object actual = snippetReflection.asBoxedValue(rf.readValue(receiver == null ? null : snippetReflection.forObject(receiver)));
+            Object actual = snippetReflection.asBoxedValue(constantReflection.readFieldValue(rf, receiver == null ? null : snippetReflection.forObject(receiver)));
             assertEquals(expected, actual);
         }
     }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantReflectionProvider.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ConstantReflectionProvider.java	Wed Nov 19 17:00:12 2014 +0100
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.api.meta;
 
+import java.lang.invoke.*;
+
 /**
  * Reflection operations on values represented as {@linkplain JavaConstant constants}. All methods
  * in this interface require the VM to access the actual object encapsulated in {@link Kind#Object
@@ -54,6 +56,31 @@
     JavaConstant readArrayElement(JavaConstant array, int index);
 
     /**
+     * Gets the constant value of this field. Note that a {@code static final} field may not be
+     * considered constant if its declaring class is not yet initialized or if it is a well known
+     * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}).
+     *
+     * @param receiver object from which this field's value is to be read. This value is ignored if
+     *            this field is static.
+     * @return the constant value of this field or {@code null} if this field is not considered
+     *         constant by the runtime
+     */
+    JavaConstant readConstantFieldValue(JavaField field, JavaConstant receiver);
+
+    /**
+     * Gets the current value of this field for a given object, if available. There is no guarantee
+     * that the same value will be returned by this method for a field unless the field is
+     * considered to be {@linkplain #readConstantFieldValue(JavaField, JavaConstant) constant} by
+     * the runtime.
+     *
+     * @param receiver object from which this field's value is to be read. This value is ignored if
+     *            this field is static.
+     * @return the value of this field or {@code null} if the value is not available (e.g., because
+     *         the field holder is not yet initialized).
+     */
+    JavaConstant readFieldValue(JavaField field, JavaConstant receiver);
+
+    /**
      * Reads a value of this kind using a base address and a displacement. No bounds checking or
      * type checking is performed. Returns {@code null} if the value is not available at this point.
      *
@@ -112,4 +139,9 @@
      * constant does not encapsulate a class, or if the type is not available at this point.
      */
     ResolvedJavaType asJavaType(JavaConstant constant);
+
+    /**
+     * Gets access to the internals of {@link MethodHandle}.
+     */
+    MethodHandleAccessProvider getMethodHandleAccess();
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Wed Nov 19 17:00:12 2014 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api.meta;
 
-import java.lang.invoke.*;
 import java.lang.reflect.*;
 
 /**
@@ -79,11 +78,6 @@
     long getMemorySize(JavaConstant constant);
 
     /**
-     * Gets access to the internals of {@link MethodHandle}.
-     */
-    MethodHandleAccessProvider getMethodHandleAccess();
-
-    /**
      * Parses a <a
      * href="http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3">method
      * descriptor</a> into a {@link Signature}. The behavior of this method is undefined if the
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java	Wed Nov 19 17:00:12 2014 +0100
@@ -83,7 +83,7 @@
                     ResolvedJavaField[] instanceFields = type.getInstanceFields(true);
                     for (ResolvedJavaField f : instanceFields) {
                         if (f.getKind() == Kind.Object) {
-                            JavaConstant value = f.readValue(c);
+                            JavaConstant value = constantReflection.readFieldValue(f, c);
                             pushConstant(marked, stack, value);
                         }
                     }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Wed Nov 19 17:00:12 2014 +0100
@@ -51,30 +51,6 @@
     boolean isSynthetic();
 
     /**
-     * Gets the constant value of this field. Note that a {@code static final} field may not be
-     * considered constant if its declaring class is not yet initialized or if it is a well known
-     * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}).
-     *
-     * @param receiver object from which this field's value is to be read. This value is ignored if
-     *            this field is static.
-     * @return the constant value of this field or {@code null} if this field is not considered
-     *         constant by the runtime
-     */
-    JavaConstant readConstantValue(JavaConstant receiver);
-
-    /**
-     * Gets the current value of this field for a given object, if available. There is no guarantee
-     * that the same value will be returned by this method for a field unless the field is
-     * considered to be {@linkplain #readConstantValue(JavaConstant) constant} by the runtime.
-     *
-     * @param receiver object from which this field's value is to be read. This value is ignored if
-     *            this field is static.
-     * @return the value of this field or {@code null} if the value is not available (e.g., because
-     *         the field holder is not yet initialized).
-     */
-    JavaConstant readValue(JavaConstant receiver);
-
-    /**
      * Returns the {@link ResolvedJavaType} object representing the class or interface that declares
      * this field.
      */
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Wed Nov 19 17:00:12 2014 +0100
@@ -98,7 +98,7 @@
              * the VM replicates them for every signature that they are actually used for.
              * Therefore, we cannot use the usual annotation-driven mechanism to define the
              */
-            if (MethodHandleNode.lookupMethodHandleIntrinsic(method, providers.getMetaAccess().getMethodHandleAccess()) != null) {
+            if (MethodHandleNode.lookupMethodHandleIntrinsic(method, providers.getConstantReflection().getMethodHandleAccess()) != null) {
                 return MethodHandleNode.class;
             }
         }
@@ -119,8 +119,8 @@
         @Override
         protected void afterParsing(StructuredGraph graph) {
             MetaAccessProvider metaAccess = replacements.providers.getMetaAccess();
-            new WordTypeVerificationPhase(metaAccess, replacements.snippetReflection, replacements.target.wordKind).apply(graph);
-            new HotSpotWordTypeRewriterPhase(metaAccess, replacements.snippetReflection, replacements.target.wordKind).apply(graph);
+            new WordTypeVerificationPhase(metaAccess, replacements.snippetReflection, replacements.providers.getConstantReflection(), replacements.target.wordKind).apply(graph);
+            new HotSpotWordTypeRewriterPhase(metaAccess, replacements.snippetReflection, replacements.providers.getConstantReflection(), replacements.target.wordKind).apply(graph);
         }
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotConstantReflectionProvider.java	Wed Nov 19 17:00:12 2014 +0100
@@ -22,24 +22,39 @@
  */
 package com.oracle.graal.hotspot.meta;
 
+import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.compiler.common.UnsafeAccess.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.reflect.*;
+import java.util.*;
 
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
+import com.oracle.graal.options.*;
+import com.oracle.graal.replacements.*;
+import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing;
+import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
+import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 
 /**
  * HotSpot implementation of {@link ConstantReflectionProvider}.
  */
 public class HotSpotConstantReflectionProvider implements ConstantReflectionProvider {
+    private static final String SystemClassName = "Ljava/lang/System;";
 
     protected final HotSpotGraalRuntime runtime;
+    protected final HotSpotMethodHandleAccessProvider methodHandleAccess;
 
     public HotSpotConstantReflectionProvider(HotSpotGraalRuntime runtime) {
         this.runtime = runtime;
+        this.methodHandleAccess = new HotSpotMethodHandleAccessProvider(this);
+    }
+
+    public MethodHandleAccessProvider getMethodHandleAccess() {
+        return methodHandleAccess;
     }
 
     @Override
@@ -251,4 +266,195 @@
         }
         return null;
     }
+
+    /**
+     * {@inheritDoc}
+     * <p>
+     * The {@code value} field in {@link OptionValue} is considered constant if the type of
+     * {@code receiver} is (assignable to) {@link StableOptionValue}.
+     */
+    public JavaConstant readConstantFieldValue(JavaField field, JavaConstant receiver) {
+        assert !ImmutableCode.getValue() || isCalledForSnippets() : receiver;
+        HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
+
+        if (receiver == null) {
+            assert hotspotField.isStatic();
+            if (hotspotField.isFinal()) {
+                ResolvedJavaType holder = hotspotField.getDeclaringClass();
+                if (holder.isInitialized() && !holder.getName().equals(SystemClassName) && isEmbeddable(hotspotField)) {
+                    return readFieldValue(field, receiver);
+                }
+            }
+        } else {
+            /*
+             * for non-static final fields, we must assume that they are only initialized if they
+             * have a non-default value.
+             */
+            assert !hotspotField.isStatic();
+            Object object = receiver.isNull() ? null : ((HotSpotObjectConstantImpl) receiver).object();
+
+            // Canonicalization may attempt to process an unsafe read before
+            // processing a guard (e.g. a null check or a type check) for this read
+            // so we need to check the object being read
+            if (object != null) {
+                if (hotspotField.isFinal()) {
+                    if (hotspotField.isInObject(object)) {
+                        JavaConstant value = readFieldValue(field, receiver);
+                        if (!value.isDefaultForKind() || assumeNonStaticFinalDefaultFieldsAsFinal(object.getClass())) {
+                            return value;
+                        }
+                    }
+                } else if (hotspotField.isStable()) {
+                    if (hotspotField.isInObject(object)) {
+                        JavaConstant value = readFieldValue(field, receiver);
+                        if (assumeDefaultStableFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) {
+                            return value;
+                        }
+                    }
+                } else {
+                    Class<?> clazz = object.getClass();
+                    if (StableOptionValue.class.isAssignableFrom(clazz)) {
+                        if (hotspotField.isInObject(object)) {
+                            assert hotspotField.getName().equals("value") : "Unexpected field in " + StableOptionValue.class.getName() + " hierarchy:" + this;
+                            StableOptionValue<?> option = (StableOptionValue<?>) object;
+                            return HotSpotObjectConstantImpl.forObject(option.getValue());
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    public JavaConstant readFieldValue(JavaField field, JavaConstant receiver) {
+        HotSpotResolvedJavaField hotspotField = (HotSpotResolvedJavaField) field;
+
+        if (receiver == null) {
+            assert hotspotField.isStatic();
+            HotSpotResolvedJavaType holder = (HotSpotResolvedJavaType) hotspotField.getDeclaringClass();
+            if (holder.isInitialized()) {
+                return readUnsafeConstant(hotspotField.getKind(), HotSpotObjectConstantImpl.forObject(holder.mirror()), hotspotField.offset());
+            }
+            return null;
+        } else {
+            assert !hotspotField.isStatic();
+            assert receiver.isNonNull() && hotspotField.isInObject(((HotSpotObjectConstantImpl) receiver).object());
+            return readUnsafeConstant(hotspotField.getKind(), receiver, hotspotField.offset());
+        }
+    }
+
+    /**
+     * Compares two {@link StackTraceElement}s for equality, ignoring differences in
+     * {@linkplain StackTraceElement#getLineNumber() line number}.
+     */
+    private static boolean equalsIgnoringLine(StackTraceElement left, StackTraceElement right) {
+        return left.getClassName().equals(right.getClassName()) && left.getMethodName().equals(right.getMethodName()) && left.getFileName().equals(right.getFileName());
+    }
+
+    /**
+     * If the compiler is configured for AOT mode,
+     * {@link #readConstantFieldValue(JavaField, JavaConstant)} should be only called for snippets
+     * or replacements.
+     */
+    private static boolean isCalledForSnippets() {
+        MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
+        ResolvedJavaMethod makeGraphMethod = null;
+        ResolvedJavaMethod initMethod = null;
+        try {
+            Class<?> rjm = ResolvedJavaMethod.class;
+            makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, rjm, SnippetInliningPolicy.class, FrameStateProcessing.class));
+            initMethod = metaAccess.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class));
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new GraalInternalError(e);
+        }
+        StackTraceElement makeGraphSTE = makeGraphMethod.asStackTraceElement(0);
+        StackTraceElement initSTE = initMethod.asStackTraceElement(0);
+
+        StackTraceElement[] stackTrace = new Exception().getStackTrace();
+        for (StackTraceElement element : stackTrace) {
+            // Ignoring line numbers should not weaken this check too much while at
+            // the same time making it more robust against source code changes
+            if (equalsIgnoringLine(makeGraphSTE, element) || equalsIgnoringLine(initSTE, element)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static boolean assumeNonStaticFinalDefaultFieldsAsFinal(Class<?> clazz) {
+        if (TrustFinalDefaultFields.getValue()) {
+            return true;
+        }
+        return clazz == SnippetCounter.class || clazz == NodeClass.class;
+    }
+
+    /**
+     * Usually {@link Stable} fields are not considered constant if the value is the
+     * {@link JavaConstant#isDefaultForKind default value}. For some special classes we want to
+     * override this behavior.
+     */
+    private static boolean assumeDefaultStableFieldsAsFinal(Class<?> clazz) {
+        // HotSpotVMConfig has a lot of zero-value fields which we know are stable and want to be
+        // considered as constants.
+        if (clazz == HotSpotVMConfig.class) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * in AOT mode, some fields should never be embedded even for snippets/replacements.
+     */
+    private static boolean isEmbeddable(HotSpotResolvedJavaField field) {
+        return Embeddable.test(field);
+    }
+
+    /**
+     * Separate out the static initialization to eliminate cycles between clinit and other locks
+     * that could lead to deadlock. Static code that doesn't call back into type or field machinery
+     * is probably ok but anything else should be made lazy.
+     */
+    static class Embeddable {
+
+        /**
+         * @return Return true if it's ok to embed the value of {@code field}.
+         */
+        public static boolean test(HotSpotResolvedJavaField field) {
+            return !ImmutableCode.getValue() || !fields.contains(field);
+        }
+
+        private static final List<ResolvedJavaField> fields = new ArrayList<>();
+        static {
+            try {
+                MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
+                fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE")));
+                fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE")));
+
+                Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0];
+                assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache")));
+
+                Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0];
+                assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache")));
+
+                Class<?> shortCacheClass = Short.class.getDeclaredClasses()[0];
+                assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache")));
+
+                Class<?> integerCacheClass = Integer.class.getDeclaredClasses()[0];
+                assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache")));
+
+                Class<?> longCacheClass = Long.class.getDeclaredClasses()[0];
+                assert "java.lang.Long$LongCache".equals(longCacheClass.getName());
+                fields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache")));
+
+                fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK")));
+                fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL")));
+            } catch (SecurityException | NoSuchFieldException e) {
+                throw new GraalInternalError(e);
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java	Wed Nov 19 17:00:12 2014 +0100
@@ -40,15 +40,9 @@
 public class HotSpotMetaAccessProvider implements MetaAccessProvider {
 
     protected final HotSpotGraalRuntime runtime;
-    protected final HotSpotMethodHandleAccessProvider methodHandleAccess;
 
     public HotSpotMetaAccessProvider(HotSpotGraalRuntime runtime) {
         this.runtime = runtime;
-        methodHandleAccess = new HotSpotMethodHandleAccessProvider();
-    }
-
-    public MethodHandleAccessProvider getMethodHandleAccess() {
-        return methodHandleAccess;
     }
 
     public HotSpotResolvedJavaType lookupJavaType(Class<?> clazz) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java	Wed Nov 19 17:00:12 2014 +0100
@@ -32,6 +32,12 @@
 
 public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProvider {
 
+    private final ConstantReflectionProvider constantReflection;
+
+    public HotSpotMethodHandleAccessProvider(ConstantReflectionProvider constantReflection) {
+        this.constantReflection = constantReflection;
+    }
+
     /**
      * Lazy initialization to break class initialization cycle. Field and method lookup is only
      * possible after the {@link HotSpotGraalRuntime} is fully initialized.
@@ -115,7 +121,7 @@
         }
 
         /* Load non-public field: LambdaForm MethodHandle.form */
-        JavaConstant lambdaForm = LazyInitialization.methodHandleFormField.readValue(methodHandle);
+        JavaConstant lambdaForm = constantReflection.readFieldValue(LazyInitialization.methodHandleFormField, methodHandle);
         if (lambdaForm.isNull()) {
             return null;
         }
@@ -126,7 +132,7 @@
             memberName = LazyInitialization.lambdaFormCompileToBytecodeMethod.invoke(lambdaForm, new JavaConstant[0]);
         } else {
             /* Load non-public field: MemberName LambdaForm.vmentry */
-            memberName = LazyInitialization.lambdaFormVmentryField.readValue(lambdaForm);
+            memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
         }
         return getTargetMethod(memberName);
     }
@@ -139,13 +145,13 @@
     /**
      * Returns the {@link ResolvedJavaMethod} for the vmtarget of a java.lang.invoke.MemberName.
      */
-    private static ResolvedJavaMethod getTargetMethod(JavaConstant memberName) {
+    private ResolvedJavaMethod getTargetMethod(JavaConstant memberName) {
         if (memberName.isNull()) {
             return null;
         }
 
         /* Load injected field: JVM_Method* MemberName.vmtarget */
-        JavaConstant vmtarget = LazyInitialization.memberNameVmtargetField.readValue(memberName);
+        JavaConstant vmtarget = constantReflection.readFieldValue(LazyInitialization.memberNameVmtargetField, memberName);
         /* Create a method from the vmtarget method pointer. */
         return HotSpotResolvedJavaMethodImpl.fromMetaspace(vmtarget.asLong());
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaFieldImpl.java	Wed Nov 19 17:00:12 2014 +0100
@@ -22,23 +22,14 @@
  */
 package com.oracle.graal.hotspot.meta;
 
-import static com.oracle.graal.compiler.common.GraalOptions.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotResolvedObjectTypeImpl.*;
 
 import java.lang.annotation.*;
 import java.lang.reflect.*;
-import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
-import com.oracle.graal.options.*;
-import com.oracle.graal.replacements.*;
-import com.oracle.graal.replacements.ReplacementsImpl.FrameStateProcessing;
-import com.oracle.graal.replacements.Snippet.SnippetInliningPolicy;
-import com.oracle.graal.replacements.SnippetTemplate.Arguments;
 
 /**
  * Represents a field in a HotSpot type.
@@ -94,159 +85,6 @@
     }
 
     /**
-     * Compares two {@link StackTraceElement}s for equality, ignoring differences in
-     * {@linkplain StackTraceElement#getLineNumber() line number}.
-     */
-    private static boolean equalsIgnoringLine(StackTraceElement left, StackTraceElement right) {
-        return left.getClassName().equals(right.getClassName()) && left.getMethodName().equals(right.getMethodName()) && left.getFileName().equals(right.getFileName());
-    }
-
-    /**
-     * If the compiler is configured for AOT mode, {@link #readConstantValue(JavaConstant)} should
-     * be only called for snippets or replacements.
-     */
-    private static boolean isCalledForSnippets() {
-        MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
-        ResolvedJavaMethod makeGraphMethod = null;
-        ResolvedJavaMethod initMethod = null;
-        try {
-            Class<?> rjm = ResolvedJavaMethod.class;
-            makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, rjm, SnippetInliningPolicy.class, FrameStateProcessing.class));
-            initMethod = metaAccess.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class));
-        } catch (NoSuchMethodException | SecurityException e) {
-            throw new GraalInternalError(e);
-        }
-        StackTraceElement makeGraphSTE = makeGraphMethod.asStackTraceElement(0);
-        StackTraceElement initSTE = initMethod.asStackTraceElement(0);
-
-        StackTraceElement[] stackTrace = new Exception().getStackTrace();
-        for (StackTraceElement element : stackTrace) {
-            // Ignoring line numbers should not weaken this check too much while at
-            // the same time making it more robust against source code changes
-            if (equalsIgnoringLine(makeGraphSTE, element) || equalsIgnoringLine(initSTE, element)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Separate out the static initialization to eliminate cycles between clinit and other locks
-     * that could lead to deadlock. Static code that doesn't call back into type or field machinery
-     * is probably ok but anything else should be made lazy.
-     */
-    static class Embeddable {
-
-        /**
-         * @return Return true if it's ok to embed the value of {@code field}.
-         */
-        public static boolean test(HotSpotResolvedJavaField field) {
-            return !ImmutableCode.getValue() || !fields.contains(field);
-        }
-
-        private static final List<ResolvedJavaField> fields = new ArrayList<>();
-        static {
-            try {
-                MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess();
-                fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE")));
-                fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE")));
-
-                Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0];
-                assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName());
-                fields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache")));
-
-                Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0];
-                assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName());
-                fields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache")));
-
-                Class<?> shortCacheClass = Short.class.getDeclaredClasses()[0];
-                assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName());
-                fields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache")));
-
-                Class<?> integerCacheClass = Integer.class.getDeclaredClasses()[0];
-                assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName());
-                fields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache")));
-
-                Class<?> longCacheClass = Long.class.getDeclaredClasses()[0];
-                assert "java.lang.Long$LongCache".equals(longCacheClass.getName());
-                fields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache")));
-
-                fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK")));
-                fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL")));
-            } catch (SecurityException | NoSuchFieldException e) {
-                throw new GraalInternalError(e);
-            }
-        }
-    }
-
-    /**
-     * in AOT mode, some fields should never be embedded even for snippets/replacements.
-     */
-    private boolean isEmbeddable() {
-        return Embeddable.test(this);
-    }
-
-    private static final String SystemClassName = "Ljava/lang/System;";
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * The {@code value} field in {@link OptionValue} is considered constant if the type of
-     * {@code receiver} is (assignable to) {@link StableOptionValue}.
-     */
-    @Override
-    public JavaConstant readConstantValue(JavaConstant receiver) {
-        assert !ImmutableCode.getValue() || isCalledForSnippets() : receiver;
-
-        if (receiver == null) {
-            assert isStatic();
-            if (isFinal()) {
-                if (holder.isInitialized() && !holder.getName().equals(SystemClassName) && isEmbeddable()) {
-                    return readValue(receiver);
-                }
-            }
-        } else {
-            /*
-             * for non-static final fields, we must assume that they are only initialized if they
-             * have a non-default value.
-             */
-            assert !isStatic();
-            Object object = receiver.isNull() ? null : ((HotSpotObjectConstantImpl) receiver).object();
-
-            // Canonicalization may attempt to process an unsafe read before
-            // processing a guard (e.g. a null check or a type check) for this read
-            // so we need to check the object being read
-            if (object != null) {
-                if (isFinal()) {
-                    if (isInObject(object)) {
-                        JavaConstant value = readValue(receiver);
-                        if (!value.isDefaultForKind() || assumeNonStaticFinalDefaultFieldsAsFinal(object.getClass())) {
-                            return value;
-                        }
-                    }
-                } else if (isStable()) {
-                    if (isInObject(object)) {
-                        JavaConstant value = readValue(receiver);
-                        if (assumeDefaultStableFieldsAsFinal(object.getClass()) || !value.isDefaultForKind()) {
-                            return value;
-                        }
-                    }
-                } else {
-                    Class<?> clazz = object.getClass();
-                    if (StableOptionValue.class.isAssignableFrom(clazz)) {
-                        if (isInObject(object)) {
-                            assert getName().equals("value") : "Unexpected field in " + StableOptionValue.class.getName() + " hierarchy:" + this;
-                            StableOptionValue<?> option = (StableOptionValue<?>) object;
-                            return HotSpotObjectConstantImpl.forObject(option.getValue());
-                        }
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
      * Determines if a given object contains this field.
      *
      * @return true iff this is a non-static field and its declaring class is assignable from
@@ -260,42 +98,6 @@
     }
 
     @Override
-    public JavaConstant readValue(JavaConstant receiver) {
-        if (receiver == null) {
-            assert isStatic();
-            if (holder.isInitialized()) {
-                return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), HotSpotObjectConstantImpl.forObject(holder.mirror()), offset);
-            }
-            return null;
-        } else {
-            assert !isStatic();
-            assert receiver.isNonNull() && isInObject(((HotSpotObjectConstantImpl) receiver).object());
-            return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver, offset);
-        }
-    }
-
-    private static boolean assumeNonStaticFinalDefaultFieldsAsFinal(Class<?> clazz) {
-        if (TrustFinalDefaultFields.getValue()) {
-            return true;
-        }
-        return clazz == SnippetCounter.class || clazz == NodeClass.class;
-    }
-
-    /**
-     * Usually {@link Stable} fields are not considered constant if the value is the
-     * {@link JavaConstant#isDefaultForKind default value}. For some special classes we want to
-     * override this behavior.
-     */
-    private static boolean assumeDefaultStableFieldsAsFinal(Class<?> clazz) {
-        // HotSpotVMConfig has a lot of zero-value fields which we know are stable and want to be
-        // considered as constants.
-        if (clazz == HotSpotVMConfig.class) {
-            return true;
-        }
-        return false;
-    }
-
-    @Override
     public HotSpotResolvedObjectTypeImpl getDeclaringClass() {
         return holder;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nfi/NativeCallStubGraphBuilder.java	Wed Nov 19 17:00:12 2014 +0100
@@ -91,7 +91,7 @@
 
             ReturnNode returnNode = g.add(ReturnNode.create(boxedResult));
             callNode.setNext(returnNode);
-            (new HotSpotWordTypeRewriterPhase(providers.getMetaAccess(), providers.getSnippetReflection(), Kind.Long)).apply(g);
+            (new HotSpotWordTypeRewriterPhase(providers.getMetaAccess(), providers.getSnippetReflection(), providers.getConstantReflection(), Kind.Long)).apply(g);
             return g;
         } catch (NoSuchMethodException e) {
             throw GraalInternalError.shouldNotReachHere("Call Stub method not found");
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java	Wed Nov 19 17:00:12 2014 +0100
@@ -82,7 +82,7 @@
     @Override
     public void simplify(SimplifierTool tool) {
         InvokeNode invoke;
-        IntrinsicMethod intrinsicMethod = lookupMethodHandleIntrinsic(targetMethod, tool.getMetaAccess().getMethodHandleAccess());
+        IntrinsicMethod intrinsicMethod = lookupMethodHandleIntrinsic(targetMethod, tool.getConstantReflection().getMethodHandleAccess());
         switch (intrinsicMethod) {
             case INVOKE_BASIC:
                 invoke = getInvokeBasicTarget(tool, intrinsicMethod);
@@ -131,7 +131,7 @@
     protected InvokeNode getInvokeBasicTarget(SimplifierTool tool, IntrinsicMethod intrinsicMethod) {
         ValueNode methodHandleNode = getReceiver();
         if (methodHandleNode.isConstant()) {
-            return getTargetInvokeNode(tool.getMetaAccess().getMethodHandleAccess().resolveInvokeBasicTarget(methodHandleNode.asJavaConstant(), false), intrinsicMethod);
+            return getTargetInvokeNode(tool.getConstantReflection().getMethodHandleAccess().resolveInvokeBasicTarget(methodHandleNode.asJavaConstant(), false), intrinsicMethod);
         }
         return null;
     }
@@ -147,7 +147,7 @@
     protected InvokeNode getLinkToTarget(SimplifierTool tool, IntrinsicMethod intrinsicMethod) {
         ValueNode memberNameNode = getMemberName();
         if (memberNameNode.isConstant()) {
-            return getTargetInvokeNode(tool.getMetaAccess().getMethodHandleAccess().resolveLinkToTarget(memberNameNode.asJavaConstant()), intrinsicMethod);
+            return getTargetInvokeNode(tool.getConstantReflection().getMethodHandleAccess().resolveLinkToTarget(memberNameNode.asJavaConstant()), intrinsicMethod);
         }
         return null;
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java	Wed Nov 19 17:00:12 2014 +0100
@@ -223,7 +223,7 @@
 
         @Override
         public void rewriteWordTypes(SnippetReflectionProvider snippetReflection) {
-            new HotSpotWordTypeRewriterPhase(providers.getMetaAccess(), snippetReflection, providers.getCodeCache().getTarget().wordKind).apply(graph);
+            new HotSpotWordTypeRewriterPhase(providers.getMetaAccess(), snippetReflection, providers.getConstantReflection(), providers.getCodeCache().getTarget().wordKind).apply(graph);
         }
     }
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/word/HotSpotWordTypeRewriterPhase.java	Wed Nov 19 17:00:12 2014 +0100
@@ -43,8 +43,8 @@
     private final ResolvedJavaType klassPointerType;
     private final ResolvedJavaType methodPointerType;
 
-    public HotSpotWordTypeRewriterPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, Kind wordKind) {
-        super(metaAccess, snippetReflection, wordKind);
+    public HotSpotWordTypeRewriterPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ConstantReflectionProvider constantReflection, Kind wordKind) {
+        super(metaAccess, snippetReflection, constantReflection, wordKind);
         this.klassPointerType = metaAccess.lookupJavaType(KlassPointer.class);
         this.methodPointerType = metaAccess.lookupJavaType(MethodPointer.class);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java	Wed Nov 19 17:00:12 2014 +0100
@@ -71,12 +71,13 @@
             return null;
         }
         MetaAccessProvider metaAccess = tool.getMetaAccess();
+        ConstantReflectionProvider constantReflection = tool.getConstantReflection();
         if (tool.canonicalizeReads() && metaAccess != null) {
-            ConstantNode constant = asConstant(metaAccess, forObject);
+            ConstantNode constant = asConstant(metaAccess, constantReflection, forObject);
             if (constant != null) {
                 return constant;
             }
-            PhiNode phi = asPhi(metaAccess, forObject);
+            PhiNode phi = asPhi(metaAccess, constantReflection, forObject);
             if (phi != null) {
                 return phi;
             }
@@ -90,12 +91,12 @@
     /**
      * Gets a constant value for this load if possible.
      */
-    public ConstantNode asConstant(MetaAccessProvider metaAccess, ValueNode forObject) {
+    public ConstantNode asConstant(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode forObject) {
         JavaConstant constant = null;
         if (isStatic()) {
-            constant = field().readConstantValue(null);
+            constant = constantReflection.readConstantFieldValue(field(), null);
         } else if (forObject.isConstant() && !forObject.isNullConstant()) {
-            constant = field().readConstantValue(forObject.asJavaConstant());
+            constant = constantReflection.readConstantFieldValue(field(), forObject.asJavaConstant());
         }
         if (constant != null) {
             return ConstantNode.forConstant(constant, metaAccess);
@@ -103,12 +104,12 @@
         return null;
     }
 
-    private PhiNode asPhi(MetaAccessProvider metaAccess, ValueNode forObject) {
+    private PhiNode asPhi(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode forObject) {
         if (!isStatic() && field.isFinal() && forObject instanceof ValuePhiNode && ((ValuePhiNode) forObject).values().filter(isNotA(ConstantNode.class)).isEmpty()) {
             PhiNode phi = (PhiNode) forObject;
             JavaConstant[] constants = new JavaConstant[phi.valueCount()];
             for (int i = 0; i < phi.valueCount(); i++) {
-                JavaConstant constantValue = field().readConstantValue(phi.valueAt(i).asJavaConstant());
+                JavaConstant constantValue = constantReflection.readConstantFieldValue(field(), phi.valueAt(i).asJavaConstant());
                 if (constantValue == null) {
                     return null;
                 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java	Wed Nov 19 17:00:12 2014 +0100
@@ -182,7 +182,7 @@
      * Rewrite all word types in the graph.
      */
     public void rewriteWordTypes(SnippetReflectionProvider snippetReflection) {
-        new WordTypeRewriterPhase(providers.getMetaAccess(), snippetReflection, providers.getCodeCache().getTarget().wordKind).apply(graph);
+        new WordTypeRewriterPhase(providers.getMetaAccess(), snippetReflection, providers.getConstantReflection(), providers.getCodeCache().getTarget().wordKind).apply(graph);
     }
 
     /**
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Wed Nov 19 17:00:12 2014 +0100
@@ -591,8 +591,8 @@
 
         protected void afterParsing(StructuredGraph graph) {
             MetaAccessProvider metaAccess = replacements.providers.getMetaAccess();
-            new WordTypeVerificationPhase(metaAccess, replacements.snippetReflection, replacements.target.wordKind).apply(graph);
-            new WordTypeRewriterPhase(metaAccess, replacements.snippetReflection, replacements.target.wordKind).apply(graph);
+            new WordTypeVerificationPhase(metaAccess, replacements.snippetReflection, replacements.providers.getConstantReflection(), replacements.target.wordKind).apply(graph);
+            new WordTypeRewriterPhase(metaAccess, replacements.snippetReflection, replacements.providers.getConstantReflection(), replacements.target.wordKind).apply(graph);
         }
 
         protected Object beforeInline(@SuppressWarnings("unused") MethodCallTargetNode callTarget, @SuppressWarnings("unused") StructuredGraph callee) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluatorCanonicalizer.java	Wed Nov 19 17:00:12 2014 +0100
@@ -58,7 +58,7 @@
             JavaType fieldType = field.getType();
             if (field.isFinal() || field.getAnnotation(CompilationFinal.class) != null ||
                             (fieldType.getKind() == Kind.Object && (field.getAnnotation(Child.class) != null || field.getAnnotation(Children.class) != null))) {
-                JavaConstant constant = field.readValue(loadFieldNode.object().asJavaConstant());
+                JavaConstant constant = constantReflection.readFieldValue(field, loadFieldNode.object().asJavaConstant());
                 assert verifyFieldValue(field, constant);
                 if (constant.isNonNull() && fieldType.getKind() == Kind.Object && fieldType.getComponentType() != null &&
                                 (field.getAnnotation(CompilationFinal.class) != null || field.getAnnotation(Children.class) != null)) {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Nov 19 17:00:12 2014 +0100
@@ -54,15 +54,17 @@
 
     protected final MetaAccessProvider metaAccess;
     protected final SnippetReflectionProvider snippetReflection;
+    protected final ConstantReflectionProvider constantReflection;
     protected final ResolvedJavaType wordBaseType;
     protected final ResolvedJavaType wordImplType;
     protected final ResolvedJavaType objectAccessType;
     protected final ResolvedJavaType barrieredAccessType;
     protected final Kind wordKind;
 
-    public WordTypeRewriterPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, Kind wordKind) {
+    public WordTypeRewriterPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ConstantReflectionProvider constantReflection, Kind wordKind) {
         this.metaAccess = metaAccess;
         this.snippetReflection = snippetReflection;
+        this.constantReflection = constantReflection;
         this.wordKind = wordKind;
         this.wordBaseType = metaAccess.lookupJavaType(WordBase.class);
         this.wordImplType = metaAccess.lookupJavaType(Word.class);
@@ -134,7 +136,7 @@
      * Fold constant field reads, e.g. enum constants.
      */
     protected void rewriteLoadField(StructuredGraph graph, LoadFieldNode node) {
-        ConstantNode constant = node.asConstant(metaAccess, node.object());
+        ConstantNode constant = node.asConstant(metaAccess, constantReflection, node.object());
         if (constant != null) {
             node.replaceAtUsages(graph.unique(constant));
             graph.removeFixed(node);
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Nov 19 16:06:49 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java	Wed Nov 19 17:00:12 2014 +0100
@@ -44,8 +44,8 @@
 
     private final WordTypeRewriterPhase wordAccess;
 
-    public WordTypeVerificationPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, Kind wordKind) {
-        this.wordAccess = new WordTypeRewriterPhase(metaAccess, snippetReflection, wordKind);
+    public WordTypeVerificationPhase(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ConstantReflectionProvider constantReflection, Kind wordKind) {
+        this.wordAccess = new WordTypeRewriterPhase(metaAccess, snippetReflection, constantReflection, wordKind);
     }
 
     @Override