changeset 18533:25a21e1794ec

modified SnippetReflectionProvider to support both VM-side and compiler-side constants in a compilation replay context
author Doug Simon <doug.simon@oracle.com>
date Wed, 26 Nov 2014 17:14:49 +0100
parents 8a2e6bc4384c
children fa981f5bb53a a2ec2beb3f08
files graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestConstantReflectionProvider.java graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaField.java graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java
diffstat 15 files changed, 212 insertions(+), 138 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestConstantReflectionProvider.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestConstantReflectionProvider.java	Wed Nov 26 17:14:49 2014 +0100
@@ -54,12 +54,12 @@
     public void readArrayLengthTest() {
         for (JavaConstant c : constants) {
             Integer actual = constantReflection.readArrayLength(c);
-            if (c.getKind() != Kind.Object || c.isNull() || !snippetReflection.asObject(c).getClass().isArray()) {
+            if (c.getKind() != Kind.Object || c.isNull() || !snippetReflection.asObject(Object.class, c).getClass().isArray()) {
                 assertNull(actual);
             } else {
                 assertNotNull(actual);
                 int actualInt = actual;
-                assertEquals(Array.getLength(snippetReflection.asObject(c)), actualInt);
+                assertEquals(Array.getLength(snippetReflection.asObject(Object.class, c)), actualInt);
             }
         }
     }
@@ -74,10 +74,10 @@
             }
         }
 
-        assertEquals(Long.valueOf(42), snippetReflection.asObject(constantReflection.boxPrimitive(JavaConstant.forLong(42))));
-        assertEquals(Integer.valueOf(666), snippetReflection.asObject(constantReflection.boxPrimitive(JavaConstant.forInt(666))));
-        assertEquals(Byte.valueOf((byte) 123), snippetReflection.asObject(constantReflection.boxPrimitive(JavaConstant.forByte((byte) 123))));
-        assertSame(Boolean.TRUE, snippetReflection.asObject(constantReflection.boxPrimitive(JavaConstant.forBoolean(true))));
+        assertEquals(Long.valueOf(42), snippetReflection.asObject(Long.class, constantReflection.boxPrimitive(JavaConstant.forLong(42))));
+        assertEquals(Integer.valueOf(666), snippetReflection.asObject(Integer.class, constantReflection.boxPrimitive(JavaConstant.forInt(666))));
+        assertEquals(Byte.valueOf((byte) 123), snippetReflection.asObject(Byte.class, constantReflection.boxPrimitive(JavaConstant.forByte((byte) 123))));
+        assertSame(Boolean.TRUE, snippetReflection.asObject(Boolean.class, constantReflection.boxPrimitive(JavaConstant.forBoolean(true))));
 
         assertNull(constantReflection.boxPrimitive(JavaConstant.NULL_POINTER));
         assertNull(constantReflection.boxPrimitive(snippetReflection.forObject("abc")));
@@ -100,19 +100,4 @@
         assertNull(constantReflection.unboxPrimitive(JavaConstant.NULL_POINTER));
         assertNull(constantReflection.unboxPrimitive(snippetReflection.forObject("abc")));
     }
-
-    @Test
-    public void testAsJavaType() {
-        for (JavaConstant c : constants) {
-            ResolvedJavaType type = constantReflection.asJavaType(c);
-
-            Object o = snippetReflection.asBoxedValue(c);
-            if (o instanceof Class) {
-                assertEquals(metaAccess.lookupJavaType((Class<?>) o), type);
-            } else {
-                assertNull(type);
-            }
-        }
-
-    }
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Wed Nov 26 17:14:49 2014 +0100
@@ -81,7 +81,7 @@
     public void lookupJavaTypeConstantTest() {
         for (JavaConstant c : constants) {
             if (c.getKind() == Kind.Object && !c.isNull()) {
-                Object o = snippetReflection.asObject(c);
+                Object o = snippetReflection.asObject(Object.class, c);
                 ResolvedJavaType type = metaAccess.lookupJavaType(c);
                 assertNotNull(type);
                 assertTrue(type.equals(metaAccess.lookupJavaType(o.getClass())));
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaField.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaField.java	Wed Nov 26 17:14:49 2014 +0100
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.api.meta.test;
 
-import static java.lang.reflect.Modifier.*;
 import static org.junit.Assert.*;
 
 import java.lang.annotation.*;
@@ -73,26 +72,6 @@
 
     @Test
     public void readConstantValueTest() throws NoSuchFieldException {
-        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
-            Field field = e.getKey();
-            if (isStatic(field.getModifiers())) {
-                try {
-                    Object expected = field.get(null);
-                    Object actual = snippetReflection.asBoxedValue(constantReflection.readConstantFieldValue(e.getValue(), null));
-                    assertEquals(expected, actual);
-                } catch (IllegalArgumentException | IllegalAccessException e1) {
-                }
-            } else {
-                try {
-                    Object receiver = field.getDeclaringClass().newInstance();
-                    Object expected = field.get(receiver);
-                    Object actual = snippetReflection.asBoxedValue(constantReflection.readConstantFieldValue(e.getValue(), snippetReflection.forObject(receiver)));
-                    assertEquals(expected, actual);
-                } catch (InstantiationException | IllegalArgumentException | IllegalAccessException e1) {
-                }
-            }
-        }
-
         ResolvedJavaField field = metaAccess.lookupJavaField(getClass().getDeclaredField("stringField"));
         for (Object receiver : new Object[]{this, null, new String()}) {
             JavaConstant value = constantReflection.readConstantFieldValue(field, snippetReflection.forObject(receiver));
@@ -104,38 +83,11 @@
             JavaConstant value = constantReflection.readConstantFieldValue(constField, snippetReflection.forObject(receiver));
             if (value != null) {
                 Object expected = "constantField";
-                assertTrue(snippetReflection.asObject(value) == expected);
+                assertTrue(snippetReflection.asObject(Object.class, value) == expected);
             }
         }
     }
 
-    @Test
-    public void readValueTest() throws IllegalArgumentException, IllegalAccessException {
-        for (Map.Entry<Field, ResolvedJavaField> e : fields.entrySet()) {
-            Field field = e.getKey();
-            field.setAccessible(true);
-            if (isStatic(field.getModifiers())) {
-                try {
-                    Object expected = field.get(null);
-                    Object actual = snippetReflection.asBoxedValue(constantReflection.readFieldValue(e.getValue(), null));
-                    assertEquals(expected, actual);
-                } catch (IllegalArgumentException | IllegalAccessException e1) {
-                }
-            }
-        }
-
-        String testString = "a test string";
-        testString.hashCode(); // create hash
-        for (Field f : String.class.getDeclaredFields()) {
-            f.setAccessible(true);
-            ResolvedJavaField rf = metaAccess.lookupJavaField(f);
-            Object receiver = isStatic(f.getModifiers()) ? null : testString;
-            Object expected = f.get(receiver);
-            Object actual = snippetReflection.asBoxedValue(constantReflection.readFieldValue(rf, receiver == null ? null : snippetReflection.forObject(receiver)));
-            assertEquals(expected, actual);
-        }
-    }
-
     String stringField = "field";
     final String constantStringField = "constantField";
 
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Wed Nov 26 17:14:49 2014 +0100
@@ -124,7 +124,7 @@
     public void isInstanceTest() {
         for (JavaConstant c : constants) {
             if (c.getKind() == Kind.Object && !c.isNull()) {
-                Object o = snippetReflection.asObject(c);
+                Object o = snippetReflection.asObject(Object.class, c);
                 Class<? extends Object> cls = o.getClass();
                 while (cls != null) {
                     ResolvedJavaType type = metaAccess.lookupJavaType(cls);
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java	Wed Nov 26 17:14:49 2014 +0100
@@ -22,6 +22,9 @@
  */
 package com.oracle.graal.api.replacements;
 
+import java.lang.reflect.*;
+import java.util.*;
+
 import com.oracle.graal.api.meta.*;
 
 /**
@@ -42,13 +45,31 @@
     JavaConstant forObject(Object object);
 
     /**
-     * Returns the object reference the given constant represents. The constant must have kind
-     * {@link Kind#Object}.
+     * Gets the object reference a given constant represents if it is of a given type. The constant
+     * must have kind {@link Kind#Object}.
      *
-     * @param constant the to access
-     * @return the object value of the constant
+     * @param type the expected type of the object represented by {@code constant}. If the object is
+     *            required to be of this type, then wrap the call to this method in
+     *            {@link Objects#requireNonNull(Object)}.
+     * @param constant an object constant
+     * @return the object value represented by {@code constant} cast to {@code type} if it is an
+     *         {@link Class#isInstance(Object) instance of} {@code type} otherwise {@code null}
      */
-    Object asObject(JavaConstant constant);
+    <T> T asObject(Class<T> type, JavaConstant constant);
+
+    /**
+     * Gets the object reference a given constant represents if it is of a given type. The constant
+     * must have kind {@link Kind#Object}.
+     *
+     * @param type the expected type of the object represented by {@code constant}. If the object is
+     *            required to be of this type, then wrap the call to this method in
+     *            {@link Objects#requireNonNull(Object)}.
+     * @param constant an object constant
+     * @return the object value represented by {@code constant} if it is an
+     *         {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
+     *         {@code null}
+     */
+    Object asObject(ResolvedJavaType type, JavaConstant constant);
 
     /**
      * Creates a boxed constant for the given kind from an Object. The object needs to be of the
@@ -61,12 +82,74 @@
     JavaConstant forBoxed(Kind kind, Object value);
 
     /**
-     * Returns the value of this constant as a boxed Java value.
+     * Resolves a parameter or return type involved in snippet code to a {@link Class}.
+     */
+    static Class<?> resolveClassForSnippet(JavaType type) throws ClassNotFoundException {
+        try {
+            return Class.forName(type.toClassName());
+        } catch (ClassNotFoundException e) {
+            // Support for -XX:-UseGraalClassLoader
+            return Class.forName(type.toClassName(), false, ClassLoader.getSystemClassLoader());
+        }
+    }
+
+    /**
+     * Invokes a given method via {@link Method#invoke(Object, Object...)}.
+     */
+    default Object invoke(ResolvedJavaMethod method, Object receiver, Object... args) {
+        try {
+            JavaType[] parameterTypes = method.toParameterTypes();
+            Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
+            for (int i = 0; i < parameterClasses.length; ++i) {
+                JavaType type = parameterTypes[i];
+                if (type.getKind() != Kind.Object) {
+                    parameterClasses[i] = type.getKind().toJavaClass();
+                } else {
+                    parameterClasses[i] = resolveClassForSnippet(parameterTypes[i]);
+                }
+            }
+
+            Class<?> c = resolveClassForSnippet(method.getDeclaringClass());
+            Method javaMethod = c.getDeclaredMethod(method.getName(), parameterClasses);
+            javaMethod.setAccessible(true);
+            return javaMethod.invoke(receiver, args);
+        } catch (IllegalAccessException | InvocationTargetException | ClassNotFoundException | NoSuchMethodException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
+
+    /**
+     * 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 constant the constant to box
-     * @return the value of the constant
+     * @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
      */
-    Object asBoxedValue(JavaConstant constant);
+    default Object readConstantFieldValue(JavaField field, Object receiver) {
+        try {
+            Class<?> c = resolveClassForSnippet(field.getDeclaringClass());
+            Field javaField = c.getDeclaredField(field.getName());
+            javaField.setAccessible(true);
+            return javaField.get(receiver);
+        } catch (IllegalAccessException | ClassNotFoundException | NoSuchFieldException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
+
+    /**
+     * Creates a new array with a given type as the component type and the specified length. This
+     * method is similar to {@link Array#newInstance(Class, int)}.
+     */
+    default Object newArray(ResolvedJavaType componentType, int length) {
+        try {
+            return Array.newInstance(resolveClassForSnippet(componentType), length);
+        } catch (ClassNotFoundException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
 
     /**
      * Gets the value to bind to a parameter in a {@link SubstitutionGuard} constructor.
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Wed Nov 26 17:14:49 2014 +0100
@@ -56,7 +56,7 @@
         new DeadCodeEliminationPhase().apply(graph);
 
         for (ConstantNode node : ConstantNode.getConstantNodes(graph)) {
-            if (node.getKind() == Kind.Object && " ".equals(getSnippetReflection().asObject(node.asJavaConstant()))) {
+            if (node.getKind() == Kind.Object && " ".equals(getSnippetReflection().asObject(String.class, node.asJavaConstant()))) {
                 node.replace(graph, ConstantNode.forConstant(getSnippetReflection().forObject("-"), getMetaAccess(), graph));
             }
         }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstant.java	Wed Nov 26 17:14:49 2014 +0100
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.meta;
 
 import java.lang.invoke.*;
+import java.util.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
@@ -101,4 +102,28 @@
      * Determines if this constant represents an {@linkplain String#intern() interned} string.
      */
     boolean isInternedString();
+
+    /**
+     * Gets the object represented by this constant represents if it is of a given type.
+     *
+     * @param type the expected type of the object represented by this constant. If the object is
+     *            required to be of this type, then wrap the call to this method in
+     *            {@link Objects#requireNonNull(Object)}.
+     * @return the object value represented by this constant if it is an
+     *         {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
+     *         {@code null}
+     */
+    <T> T asObject(Class<T> type);
+
+    /**
+     * Gets the object represented by this constant represents if it is of a given type.
+     *
+     * @param type the expected type of the object represented by this constant. If the object is
+     *            required to be of this type, then wrap the call to this method in
+     *            {@link Objects#requireNonNull(Object)}.
+     * @return the object value represented by this constant if it is an
+     *         {@link ResolvedJavaType#isInstance(JavaConstant) instance of} {@code type} otherwise
+     *         {@code null}
+     */
+    Object asObject(ResolvedJavaType type);
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotObjectConstantImpl.java	Wed Nov 26 17:14:49 2014 +0100
@@ -205,6 +205,20 @@
         return false;
     }
 
+    public <T> T asObject(Class<T> type) {
+        if (type.isInstance(object)) {
+            return type.cast(object);
+        }
+        return null;
+    }
+
+    public Object asObject(ResolvedJavaType type) {
+        if (type.isInstance(this)) {
+            return object;
+        }
+        return null;
+    }
+
     @Override
     public boolean isNull() {
         return false;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java	Wed Nov 26 17:14:49 2014 +0100
@@ -40,8 +40,15 @@
     }
 
     @Override
-    public Object asObject(JavaConstant constant) {
-        return ((HotSpotObjectConstantImpl) constant).object();
+    public Object asObject(ResolvedJavaType type, JavaConstant constant) {
+        HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant;
+        return hsConstant.asObject(type);
+    }
+
+    @Override
+    public <T> T asObject(Class<T> type, JavaConstant constant) {
+        HotSpotObjectConstant hsConstant = (HotSpotObjectConstant) constant;
+        return hsConstant.asObject(type);
     }
 
     @Override
@@ -49,11 +56,6 @@
         return HotSpotObjectConstantImpl.forBoxedValue(kind, value);
     }
 
-    @Override
-    public Object asBoxedValue(JavaConstant constant) {
-        return HotSpotObjectConstantImpl.asBoxedValue(constant);
-    }
-
     public Object getSubstitutionGuardParameter(Class<?> type) {
         if (type.isInstance(runtime)) {
             return runtime;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java	Wed Nov 26 17:14:49 2014 +0100
@@ -86,7 +86,7 @@
             ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass);
 
             // Prepare the arguments for the reflective factory method call on the node class.
-            JavaConstant[] nodeFactoryArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false);
+            Object[] nodeFactoryArguments = prepareArguments(methodCallTargetNode, parameterTypes, target, false);
             if (nodeFactoryArguments == null) {
                 return false;
             }
@@ -105,7 +105,7 @@
             ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass);
 
             // Prepare the arguments for the reflective method call
-            JavaConstant[] arguments = prepareArguments(methodCallTargetNode, parameterTypes, target, true);
+            JavaConstant[] arguments = (JavaConstant[]) prepareArguments(methodCallTargetNode, parameterTypes, target, true);
             if (arguments == null) {
                 return false;
             }
@@ -156,9 +156,9 @@
      * @return the arguments for the reflective invocation or null if an argument of {@code invoke}
      *         that is expected to be constant isn't
      */
-    private JavaConstant[] prepareArguments(MethodCallTargetNode methodCallTargetNode, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
+    private Object[] prepareArguments(MethodCallTargetNode methodCallTargetNode, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) {
         NodeInputList<ValueNode> arguments = methodCallTargetNode.arguments();
-        JavaConstant[] reflectionCallArguments = new JavaConstant[arguments.size()];
+        Object[] reflectionCallArguments = folding ? new JavaConstant[arguments.size()] : new Object[arguments.size()];
         for (int i = 0; i < reflectionCallArguments.length; ++i) {
             int parameterIndex = i;
             if (!methodCallTargetNode.isStatic()) {
@@ -173,24 +173,34 @@
                 Constant constant = constantNode.asConstant();
                 ResolvedJavaType type = providers.getConstantReflection().asJavaType(constant);
                 if (type != null) {
-                    reflectionCallArguments[i] = snippetReflection.forObject(type);
+                    reflectionCallArguments[i] = type;
                     parameterTypes[i] = providers.getMetaAccess().lookupJavaType(ResolvedJavaType.class);
                 } else {
                     JavaConstant javaConstant = (JavaConstant) constant;
                     if (parameterTypes[i].getKind() == Kind.Boolean) {
-                        reflectionCallArguments[i] = snippetReflection.forObject(Boolean.valueOf(javaConstant.asInt() != 0));
+                        reflectionCallArguments[i] = Boolean.valueOf(javaConstant.asInt() != 0);
                     } else if (parameterTypes[i].getKind() == Kind.Byte) {
-                        reflectionCallArguments[i] = snippetReflection.forObject(Byte.valueOf((byte) javaConstant.asInt()));
+                        reflectionCallArguments[i] = Byte.valueOf((byte) javaConstant.asInt());
                     } else if (parameterTypes[i].getKind() == Kind.Short) {
-                        reflectionCallArguments[i] = snippetReflection.forObject(Short.valueOf((short) javaConstant.asInt()));
+                        reflectionCallArguments[i] = Short.valueOf((short) javaConstant.asInt());
                     } else if (parameterTypes[i].getKind() == Kind.Char) {
-                        reflectionCallArguments[i] = snippetReflection.forObject(Character.valueOf((char) javaConstant.asInt()));
+                        reflectionCallArguments[i] = Character.valueOf((char) javaConstant.asInt());
+                    } else if (parameterTypes[i].getKind() == Kind.Object) {
+                        if (!folding) {
+                            reflectionCallArguments[i] = snippetReflection.asObject(parameterTypes[i], javaConstant);
+                        } else {
+                            reflectionCallArguments[i] = javaConstant;
+                        }
                     } else {
-                        reflectionCallArguments[i] = javaConstant;
+                        reflectionCallArguments[i] = javaConstant.asBoxedPrimitive();
                     }
                 }
+                if (folding && reflectionCallArguments[i] != constant) {
+                    assert !(reflectionCallArguments[i] instanceof JavaConstant);
+                    reflectionCallArguments[i] = snippetReflection.forObject(reflectionCallArguments[i]);
+                }
             } else {
-                reflectionCallArguments[i] = snippetReflection.forObject(argument);
+                reflectionCallArguments[i] = argument;
                 parameterTypes[i] = providers.getMetaAccess().lookupJavaType(ValueNode.class);
             }
         }
@@ -210,13 +220,13 @@
     }
 
     protected Node createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType,
-                    JavaConstant[] nodeFactoryArguments) {
+                    Object[] nodeFactoryArguments) {
         ResolvedJavaMethod factory = null;
-        JavaConstant[] arguments = null;
+        Object[] arguments = null;
 
         for (ResolvedJavaMethod m : nodeClass.getDeclaredMethods()) {
             if (m.getName().equals("create") && !m.isSynthetic()) {
-                JavaConstant[] match = match(graph, invokeStamp, m, parameterTypes, nodeFactoryArguments);
+                Object[] match = match(graph, invokeStamp, m, parameterTypes, nodeFactoryArguments);
 
                 if (match != null) {
                     if (factory == null) {
@@ -234,7 +244,7 @@
         }
 
         try {
-            ValueNode intrinsicNode = (ValueNode) snippetReflection.asObject(invokeFactory(factory, arguments));
+            ValueNode intrinsicNode = (ValueNode) snippetReflection.invoke(factory, null, arguments);
 
             if (setStampFromReturnType) {
                 intrinsicNode.setStamp(invokeStamp);
@@ -245,10 +255,6 @@
         }
     }
 
-    protected JavaConstant invokeFactory(ResolvedJavaMethod factory, JavaConstant[] arguments) {
-        return factory.invoke(null, arguments);
-    }
-
     private static String sigString(ResolvedJavaType[] types) {
         StringBuilder sb = new StringBuilder("(");
         for (int i = 0; i < types.length; i++) {
@@ -260,39 +266,41 @@
         return sb.append(")").toString();
     }
 
-    private static boolean containsInjected(ResolvedJavaMethod c, int start, int end) {
-        for (int i = start; i < end; i++) {
+    private static boolean checkNoMoreInjected(ResolvedJavaMethod c, int start) {
+        int count = c.getSignature().getParameterCount(false);
+        for (int i = start; i < count; i++) {
             if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) {
-                return true;
+                throw new GraalInternalError("Injected parameter %d of type %s must precede all non-injected parameters of %s", i,
+                                c.getSignature().getParameterType(i, c.getDeclaringClass()).toJavaName(false), c.format("%H.%n(%p)"));
             }
         }
-        return false;
+        return true;
     }
 
-    private JavaConstant[] match(StructuredGraph graph, Stamp invokeStamp, ResolvedJavaMethod m, ResolvedJavaType[] parameterTypes, JavaConstant[] nodeFactoryArguments) {
-        JavaConstant[] arguments = null;
-        JavaConstant[] injected = null;
+    private Object[] match(StructuredGraph graph, Stamp invokeStamp, ResolvedJavaMethod m, ResolvedJavaType[] parameterTypes, Object[] nodeFactoryArguments) {
+        Object[] arguments = null;
+        Object[] injected = null;
 
         ResolvedJavaType[] signature = resolveJavaTypes(m.getSignature().toParameterTypes(null), m.getDeclaringClass());
         MetaAccessProvider metaAccess = providers.getMetaAccess();
         for (int i = 0; i < signature.length; i++) {
             if (m.getParameterAnnotation(InjectedNodeParameter.class, i) != null) {
-                injected = injected == null ? new JavaConstant[1] : Arrays.copyOf(injected, injected.length + 1);
+                injected = injected == null ? new Object[1] : Arrays.copyOf(injected, injected.length + 1);
                 Object injectedParameter = snippetReflection.getInjectedNodeIntrinsicParameter(signature[i]);
                 if (injectedParameter != null) {
-                    injected[injected.length - 1] = snippetReflection.forObject(injectedParameter);
+                    injected[injected.length - 1] = injectedParameter;
                 } else if (signature[i].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) {
-                    injected[injected.length - 1] = snippetReflection.forObject(metaAccess);
+                    injected[injected.length - 1] = metaAccess;
                 } else if (signature[i].equals(metaAccess.lookupJavaType(StructuredGraph.class))) {
-                    injected[injected.length - 1] = snippetReflection.forObject(graph);
+                    injected[injected.length - 1] = graph;
                 } else if (signature[i].equals(metaAccess.lookupJavaType(ForeignCallsProvider.class))) {
-                    injected[injected.length - 1] = snippetReflection.forObject(providers.getForeignCalls());
+                    injected[injected.length - 1] = providers.getForeignCalls();
                 } else if (signature[i].equals(metaAccess.lookupJavaType(SnippetReflectionProvider.class))) {
-                    injected[injected.length - 1] = snippetReflection.forObject(snippetReflection);
+                    injected[injected.length - 1] = snippetReflection;
                 } else if (signature[i].isAssignableFrom(metaAccess.lookupJavaType(Stamp.class))) {
-                    injected[injected.length - 1] = snippetReflection.forObject(invokeStamp);
+                    injected[injected.length - 1] = invokeStamp;
                 } else if (signature[i].isAssignableFrom(metaAccess.lookupJavaType(StampProvider.class))) {
-                    injected[injected.length - 1] = snippetReflection.forObject(providers.getStampProvider());
+                    injected[injected.length - 1] = providers.getStampProvider();
                 } else {
                     throw new GraalInternalError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), m.format("%H.%n(%p)"));
                 }
@@ -301,7 +309,7 @@
                     // Chop injected arguments from signature
                     signature = Arrays.copyOfRange(signature, i, signature.length);
                 }
-                assert !containsInjected(m, i, signature.length);
+                assert checkNoMoreInjected(m, i);
                 break;
             }
         }
@@ -330,18 +338,22 @@
                 }
             }
             arguments = Arrays.copyOf(nodeFactoryArguments, fixedArgs + 1);
-            arguments[fixedArgs] = componentType.newArray(nodeFactoryArguments.length - fixedArgs);
+            arguments[fixedArgs] = snippetReflection.newArray(componentType, nodeFactoryArguments.length - fixedArgs);
 
-            Object varargs = snippetReflection.asObject(arguments[fixedArgs]);
+            Object varargs = arguments[fixedArgs];
             for (int i = fixedArgs; i < nodeFactoryArguments.length; i++) {
-                Array.set(varargs, i - fixedArgs, snippetReflection.asBoxedValue(nodeFactoryArguments[i]));
+                if (componentType.isPrimitive()) {
+                    Array.set(varargs, i - fixedArgs, nodeFactoryArguments[i]);
+                } else {
+                    ((Object[]) varargs)[i - fixedArgs] = nodeFactoryArguments[i];
+                }
             }
         } else {
             return null;
         }
 
         if (injected != null) {
-            JavaConstant[] copy = new JavaConstant[injected.length + arguments.length];
+            Object[] copy = new Object[injected.length + arguments.length];
             System.arraycopy(injected, 0, copy, 0, injected.length);
             System.arraycopy(arguments, 0, copy, injected.length, arguments.length);
             arguments = copy;
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Wed Nov 26 17:14:49 2014 +0100
@@ -433,7 +433,7 @@
         }
 
         JavaConstant constantCallNode = node.asJavaConstant();
-        Object value = snippetReflection.asObject(constantCallNode);
+        Object value = snippetReflection.asObject(Object.class, constantCallNode);
 
         if (!(value instanceof OptimizedDirectCallNode)) {
             // might be an indirect call.
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java	Wed Nov 26 17:14:49 2014 +0100
@@ -69,7 +69,7 @@
         if (tool.assumptions() != null && assumption.isConstant()) {
             JavaConstant c = assumption.asJavaConstant();
             assert c.getKind() == Kind.Object;
-            Object object = getSnippetReflection().asObject(c);
+            Object object = getSnippetReflection().asObject(Object.class, c);
             OptimizedAssumption assumptionObject = (OptimizedAssumption) object;
             StructuredGraph graph = graph();
             if (assumptionObject.isValid()) {
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java	Wed Nov 26 17:14:49 2014 +0100
@@ -87,7 +87,7 @@
 
     private FrameDescriptor getConstantFrameDescriptor() {
         assert descriptor.isConstant() && !descriptor.isNullConstant();
-        return (FrameDescriptor) getSnippetReflection().asObject(descriptor.asJavaConstant());
+        return getSnippetReflection().asObject(FrameDescriptor.class, descriptor.asJavaConstant());
     }
 
     private int getFrameSize() {
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/SnippetLocationNode.java	Wed Nov 26 17:14:49 2014 +0100
@@ -85,7 +85,7 @@
     @Override
     public Kind getValueKind() {
         if (valueKind.isConstant()) {
-            return (Kind) snippetReflection.asObject(valueKind.asJavaConstant());
+            return snippetReflection.asObject(Kind.class, valueKind.asJavaConstant());
         }
         throw new GraalInternalError("Cannot access kind yet because it is not constant: " + valueKind);
     }
@@ -93,7 +93,8 @@
     @Override
     public LocationIdentity getLocationIdentity() {
         if (locationIdentity.isConstant()) {
-            return (LocationIdentity) snippetReflection.asObject(locationIdentity.asJavaConstant());
+            LocationIdentity identity = snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant());
+            return identity;
         }
         // We do not know our actual location identity yet, so be conservative.
         return ANY_LOCATION;
@@ -102,8 +103,8 @@
     @Override
     public Node canonical(CanonicalizerTool tool) {
         if (valueKind.isConstant() && locationIdentity.isConstant() && displacement.isConstant() && (indexScaling == null || indexScaling.isConstant())) {
-            Kind constKind = (Kind) snippetReflection.asObject(valueKind.asJavaConstant());
-            LocationIdentity constLocation = (LocationIdentity) snippetReflection.asObject(locationIdentity.asJavaConstant());
+            Kind constKind = snippetReflection.asObject(Kind.class, valueKind.asJavaConstant());
+            LocationIdentity constLocation = snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant());
             long constDisplacement = displacement.asJavaConstant().asLong();
             int constIndexScaling = indexScaling == null ? 0 : indexScaling.asJavaConstant().asInt();
 
--- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Nov 26 14:03:13 2014 +0100
+++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java	Wed Nov 26 17:14:49 2014 +0100
@@ -96,7 +96,7 @@
             if (node.isConstant()) {
                 ConstantNode oldConstant = (ConstantNode) node;
                 assert oldConstant.asJavaConstant().getKind() == Kind.Object;
-                WordBase value = (WordBase) snippetReflection.asObject(oldConstant.asJavaConstant());
+                WordBase value = snippetReflection.asObject(WordBase.class, oldConstant.asJavaConstant());
                 ConstantNode newConstant = ConstantNode.forIntegerKind(wordKind, value.rawValue(), node.graph());
                 graph.replaceFloating(oldConstant, newConstant);
 
@@ -241,7 +241,7 @@
                 assert arguments.size() == 3;
                 Kind readKind = asKind(callTargetNode.returnType());
                 LocationNode location = makeLocation(graph, arguments.get(1), readKind, ANY_LOCATION);
-                BarrierType barrierType = (BarrierType) snippetReflection.asObject(arguments.get(2).asJavaConstant());
+                BarrierType barrierType = snippetReflection.asObject(BarrierType.class, arguments.get(2).asJavaConstant());
                 replace(invoke, readOp(graph, arguments.get(0), invoke, location, barrierType, true));
                 break;
             }
@@ -381,7 +381,7 @@
 
     protected LocationNode makeLocation(StructuredGraph graph, ValueNode offset, Kind readKind, ValueNode locationIdentity) {
         if (locationIdentity.isConstant()) {
-            return makeLocation(graph, offset, readKind, (LocationIdentity) snippetReflection.asObject(locationIdentity.asJavaConstant()));
+            return makeLocation(graph, offset, readKind, snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant()));
         }
         return SnippetLocationNode.create(snippetReflection, locationIdentity, ConstantNode.forConstant(snippetReflection.forObject(readKind), metaAccess, graph), ConstantNode.forLong(0, graph),
                         fromSigned(graph, offset), ConstantNode.forInt(1, graph), graph);