changeset 20874:d2ce468854b4

Merge.
author Doug Simon <doug.simon@oracle.com>
date Thu, 09 Apr 2015 17:04:05 +0200
parents 891e3e7024b8 (diff) 220ecaa0cc9b (current diff)
children c9a8c62c60fc
files graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java
diffstat 57 files changed, 1136 insertions(+), 1079 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Thu Apr 09 17:04:05 2015 +0200
@@ -73,7 +73,7 @@
 /**
  * This class implements the AMD64 specific portion of the LIR generator.
  */
-public abstract class AMD64LIRGenerator extends LIRGenerator {
+public abstract class AMD64LIRGenerator extends LIRGenerator implements AMD64ArithmeticLIRGenerator {
 
     private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(Kind.Int));
 
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Thu Apr 09 17:04:05 2015 +0200
@@ -44,6 +44,7 @@
 import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegReg;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.MulHighOp;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp;
+import com.oracle.graal.lir.sparc.SPARCArithmetic.SPARCLMulccOp;
 import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary2Op;
 import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp;
 import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp;
@@ -467,34 +468,6 @@
     }
 
     @Override
-    public Value emitMathLog(Value input, boolean base10) {
-        Variable result = newVariable(LIRKind.derive(input));
-        append(new SPARCMathIntrinsicOp(LOG, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathCos(Value input) {
-        Variable result = newVariable(LIRKind.derive(input));
-        append(new SPARCMathIntrinsicOp(COS, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathSin(Value input) {
-        Variable result = newVariable(LIRKind.derive(input));
-        append(new SPARCMathIntrinsicOp(SIN, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
-    public Value emitMathTan(Value input) {
-        Variable result = newVariable(LIRKind.derive(input));
-        append(new SPARCMathIntrinsicOp(TAN, result, asAllocatable(input)));
-        return result;
-    }
-
-    @Override
     public Variable emitByteSwap(Value input) {
         Variable result = newVariable(LIRKind.derive(input));
         append(new SPARCByteSwapOp(this, result, input));
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Apr 09 17:04:05 2015 +0200
@@ -49,7 +49,8 @@
 import com.oracle.graal.debug.Debug.Scope;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graphbuilderconf.*;
-import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver;
 import com.oracle.graal.java.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.phases.*;
@@ -123,15 +124,6 @@
         return true;
     }
 
-    private static boolean substitutionsInstalled;
-
-    private void installSubstitutions() {
-        if (!substitutionsInstalled) {
-            this.providers.getReplacements().registerSubstitutions(GraalCompilerTest.class, GraalCompilerTestSubstitutions.class);
-            substitutionsInstalled = true;
-        }
-    }
-
     protected static void breakpoint() {
     }
 
@@ -180,7 +172,6 @@
         this.providers = getBackend().getProviders();
         this.suites = new DerivedOptionValue<>(this::createSuites);
         this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites);
-        installSubstitutions();
     }
 
     /**
@@ -201,7 +192,6 @@
         this.providers = backend.getProviders();
         this.suites = new DerivedOptionValue<>(this::createSuites);
         this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites);
-        installSubstitutions();
     }
 
     @BeforeClass
@@ -855,6 +845,13 @@
     }
 
     protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
+        InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins();
+        invocationPlugins.register(new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
+                b.add(new BreakpointNode());
+                return true;
+            }
+        }, GraalCompilerTest.class, "breakpoint");
         return conf;
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTestSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.compiler.test;
-
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.nodes.*;
-
-@ClassSubstitution(GraalCompilerTest.class)
-class GraalCompilerTestSubstitutions {
-
-    @MethodSubstitution
-    public static void breakpoint() {
-        BreakpointNode.breakpoint();
-    }
-}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Thu Apr 09 17:04:05 2015 +0200
@@ -44,6 +44,14 @@
 
     private final Providers providers;
 
+    public static final ForeignCallDescriptor ARITHMETIC_SIN = new ForeignCallDescriptor("arithmeticSin", double.class, double.class);
+    public static final ForeignCallDescriptor ARITHMETIC_COS = new ForeignCallDescriptor("arithmeticCos", double.class, double.class);
+    public static final ForeignCallDescriptor ARITHMETIC_TAN = new ForeignCallDescriptor("arithmeticTan", double.class, double.class);
+    public static final ForeignCallDescriptor ARITHMETIC_EXP = new ForeignCallDescriptor("arithmeticExp", double.class, double.class);
+    public static final ForeignCallDescriptor ARITHMETIC_LOG = new ForeignCallDescriptor("arithmeticLog", double.class, double.class);
+    public static final ForeignCallDescriptor ARITHMETIC_LOG10 = new ForeignCallDescriptor("arithmeticLog10", double.class, double.class);
+    public static final ForeignCallDescriptor ARITHMETIC_POW = new ForeignCallDescriptor("arithmeticPow", double.class, double.class, double.class);
+
     protected Backend(Providers providers) {
         this.providers = providers;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ForeignCallPlugin.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graphbuilderconf;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+
+/**
+ * {@link InvocationPlugin} for converting a method call directly to a foreign call.
+ */
+public final class ForeignCallPlugin implements InvocationPlugin {
+    private final ForeignCallsProvider foreignCalls;
+    private final ForeignCallDescriptor descriptor;
+
+    public ForeignCallPlugin(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor) {
+        this.foreignCalls = foreignCalls;
+        this.descriptor = descriptor;
+    }
+
+    public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode[] args) {
+        b.addPush(new ForeignCallNode(foreignCalls, descriptor, args));
+        return true;
+    }
+}
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java	Thu Apr 09 17:04:05 2015 +0200
@@ -28,7 +28,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
 import com.oracle.graal.nodes.*;
@@ -168,6 +167,16 @@
      */
     void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args);
 
+    /**
+     * Intrinsifies an invocation of a given method by inlining the bytecodes of a given
+     * substitution method.
+     *
+     * @param targetMethod the method being intrinsified
+     * @param substitute the intrinsic implementation
+     * @param args the arguments with which to inline the invocation
+     */
+    void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args);
+
     StampProvider getStampProvider();
 
     MetaAccessProvider getMetaAccess();
@@ -178,8 +187,6 @@
 
     ConstantReflectionProvider getConstantReflection();
 
-    SnippetReflectionProvider getSnippetReflection();
-
     /**
      * Gets the graph being constructed.
      */
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java	Thu Apr 09 17:04:05 2015 +0200
@@ -97,60 +97,57 @@
         return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4, arg5);
     }
 
-    default ResolvedJavaMethod getSubstitute() {
-        return null;
-    }
-
     /**
-     * Executes a given plugin against a set of invocation arguments by dispatching to the
-     * {@code apply(...)} method that matches the number of arguments or to
-     * {@link #applyPolymorphic} if {@code plugin} is {@linkplain #isSignaturePolymorphic()
-     * signature polymorphic}.
+     * Executes this plugin against a set of invocation arguments.
      *
-     * @param targetMethod the method for which plugin is being applied
+     * The default implementation in {@link InvocationPlugin} dispatches to the {@code apply(...)}
+     * method that matches the number of arguments or to {@link #applyPolymorphic} if {@code plugin}
+     * is {@linkplain #isSignaturePolymorphic() signature polymorphic}.
+     *
+     * @param targetMethod the method for which this plugin is being applied
      * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static
      * @param argsIncludingReceiver all arguments to the invocation include the receiver in position
      *            0 if {@code targetMethod} is not static
-     * @return {@code true} if the plugin handled the invocation of {@code targetMethod}
+     * @return {@code true} if this plugin handled the invocation of {@code targetMethod}
      *         {@code false} if the graph builder should process the invoke further (e.g., by
      *         inlining it or creating an {@link Invoke} node). A plugin that does not handle an
      *         invocation must not modify the graph being constructed.
      */
-    static boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin plugin, Receiver receiver, ValueNode[] argsIncludingReceiver) {
-        if (plugin.isSignaturePolymorphic()) {
-            return plugin.applyPolymorphic(b, targetMethod, receiver, argsIncludingReceiver);
+    default boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode[] argsIncludingReceiver) {
+        if (isSignaturePolymorphic()) {
+            return applyPolymorphic(b, targetMethod, receiver, argsIncludingReceiver);
         } else if (receiver != null) {
             assert !targetMethod.isStatic();
             assert argsIncludingReceiver.length > 0;
             if (argsIncludingReceiver.length == 1) {
-                return plugin.apply(b, targetMethod, receiver);
+                return apply(b, targetMethod, receiver);
             } else if (argsIncludingReceiver.length == 2) {
-                return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1]);
+                return apply(b, targetMethod, receiver, argsIncludingReceiver[1]);
             } else if (argsIncludingReceiver.length == 3) {
-                return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2]);
+                return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2]);
             } else if (argsIncludingReceiver.length == 4) {
-                return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]);
+                return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]);
             } else if (argsIncludingReceiver.length == 5) {
-                return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]);
+                return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]);
             } else {
-                return plugin.defaultHandler(b, targetMethod, receiver, argsIncludingReceiver);
+                return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver);
             }
         } else {
             assert targetMethod.isStatic();
             if (argsIncludingReceiver.length == 0) {
-                return plugin.apply(b, targetMethod, null);
+                return apply(b, targetMethod, null);
             } else if (argsIncludingReceiver.length == 1) {
-                return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0]);
+                return apply(b, targetMethod, null, argsIncludingReceiver[0]);
             } else if (argsIncludingReceiver.length == 2) {
-                return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1]);
+                return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1]);
             } else if (argsIncludingReceiver.length == 3) {
-                return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2]);
+                return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2]);
             } else if (argsIncludingReceiver.length == 4) {
-                return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]);
+                return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]);
             } else if (argsIncludingReceiver.length == 5) {
-                return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]);
+                return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]);
             } else {
-                return plugin.defaultHandler(b, targetMethod, receiver, argsIncludingReceiver);
+                return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver);
             }
 
         }
--- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java	Thu Apr 09 17:04:05 2015 +0200
@@ -181,6 +181,18 @@
         public void register5(String name, Class<?> arg1, Class<?> arg2, Class<?> arg3, Class<?> arg4, Class<?> arg5, InvocationPlugin plugin) {
             plugins.register(plugin, declaringClass, name, arg1, arg2, arg3, arg4, arg5);
         }
+
+        /**
+         * Registers a plugin that implements a method based on the bytecode of a substitute method.
+         *
+         * @param substituteDeclaringClass the class declaring the substitute method
+         * @param name the name of both the original and substitute method
+         * @param argumentTypes the parameter types of the substitute
+         */
+        public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, Class<?>... argumentTypes) {
+            MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(substituteDeclaringClass, name, argumentTypes);
+            plugins.register(plugin, declaringClass, name, argumentTypes);
+        }
     }
 
     static final class MethodInfo {
@@ -201,6 +213,7 @@
             if (!isStatic) {
                 argumentTypes[0] = declaringClass;
             }
+            assert resolveJava() != null;
         }
 
         @Override
@@ -221,16 +234,20 @@
         }
 
         ResolvedJavaMethod resolve(MetaAccessProvider metaAccess) {
+            return metaAccess.lookupJavaMethod(resolveJava());
+        }
+
+        Executable resolveJava() {
             try {
-                ResolvedJavaMethod method;
+                Executable res;
                 Class<?>[] parameterTypes = isStatic ? argumentTypes : Arrays.copyOfRange(argumentTypes, 1, argumentTypes.length);
                 if (name.equals("<init>")) {
-                    method = metaAccess.lookupJavaMethod(declaringClass.getDeclaredConstructor(parameterTypes));
+                    res = declaringClass.getDeclaredConstructor(parameterTypes);
                 } else {
-                    method = metaAccess.lookupJavaMethod(declaringClass.getDeclaredMethod(name, parameterTypes));
+                    res = declaringClass.getDeclaredMethod(name, parameterTypes);
                 }
-                assert method.isStatic() == isStatic;
-                return method;
+                assert Modifier.isStatic(res.getModifiers()) == isStatic;
+                return res;
             } catch (NoSuchMethodException | SecurityException e) {
                 throw new GraalInternalError(e);
             }
@@ -409,6 +426,14 @@
                 assert !p.registrations.contains(method) : "a plugin is already registered for " + method;
                 p = p.parent;
             }
+            if (plugin instanceof ForeignCallPlugin) {
+                return true;
+            }
+            if (plugin instanceof MethodSubstitutionPlugin) {
+                MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin;
+                msplugin.getJavaSubstitute();
+                return true;
+            }
             int arguments = method.isStatic ? method.argumentTypes.length : method.argumentTypes.length - 1;
             assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method);
             for (Method m : plugin.getClass().getDeclaredMethods()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.graphbuilderconf;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.stream.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver;
+import com.oracle.graal.nodes.*;
+
+/**
+ * An {@link InvocationPlugin} for a method where the implementation of the method is provided by a
+ * {@linkplain #getSubstitute(MetaAccessProvider) substitute} method. A substitute method must be
+ * static even if the substituted method is not.
+ */
+public final class MethodSubstitutionPlugin implements InvocationPlugin {
+
+    private ResolvedJavaMethod cachedSubstitute;
+    private final Class<?> declaringClass;
+    private final String name;
+    private final Class<?>[] parameters;
+    private final boolean originalIsStatic;
+
+    /**
+     * Creates a method substitution plugin.
+     *
+     * @param declaringClass the class in which the substitute method is declared
+     * @param name the name of the substitute method
+     * @param parameters the parameter types of the substitute method. If the original method is not
+     *            static, then {@code parameters[0]} must be the {@link Class} value denoting
+     *            {@link Receiver}
+     */
+    public MethodSubstitutionPlugin(Class<?> declaringClass, String name, Class<?>... parameters) {
+        this.declaringClass = declaringClass;
+        this.name = name;
+        this.parameters = parameters;
+        this.originalIsStatic = parameters.length == 0 || parameters[0] != Receiver.class;
+    }
+
+    /**
+     * Gets the substitute method, resolving it first if necessary.
+     */
+    public ResolvedJavaMethod getSubstitute(MetaAccessProvider metaAccess) {
+        if (cachedSubstitute == null) {
+            cachedSubstitute = metaAccess.lookupJavaMethod(getJavaSubstitute());
+        }
+        return cachedSubstitute;
+    }
+
+    /**
+     * Gets the reflection API version of the substitution method.
+     */
+    Method getJavaSubstitute() throws GraalInternalError {
+        Method substituteMethod = lookupSubstitute();
+        int modifiers = substituteMethod.getModifiers();
+        if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
+            throw new GraalInternalError("Substitution method must not be abstract or native: " + substituteMethod);
+        }
+        if (!Modifier.isStatic(modifiers)) {
+            throw new GraalInternalError("Substitution method must be static: " + substituteMethod);
+        }
+        return substituteMethod;
+    }
+
+    /**
+     * Determines if a given method is the substitute method of this plugin.
+     */
+    private boolean isSubstitute(Method m) {
+        if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) {
+            if (parameters.length == m.getParameterCount()) {
+                Class<?>[] mparams = m.getParameterTypes();
+                int start = 0;
+                if (!originalIsStatic) {
+                    start = 1;
+                    if (!mparams[0].isAssignableFrom(parameters[0])) {
+                        return false;
+                    }
+                }
+                for (int i = start; i < mparams.length; i++) {
+                    if (mparams[i] != parameters[i]) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Gets the substitute method of this plugin.
+     */
+    private Method lookupSubstitute() {
+        for (Method m : declaringClass.getDeclaredMethods()) {
+            if (isSubstitute(m)) {
+                return m;
+            }
+        }
+        throw new GraalInternalError("No method found in %s compatible with the signature (%s)", declaringClass.getName(), Arrays.asList(parameters).stream().map(c -> c.getSimpleName()).collect(
+                        Collectors.joining(",")));
+    }
+
+    /**
+     * Resolves a name to a class.
+     *
+     * @param className the name of the class to resolve
+     * @param optional if true, resolution failure returns null
+     * @return the resolved class or null if resolution fails and {@code optional} is true
+     */
+    public static Class<?> resolveClass(String className, boolean optional) {
+        try {
+            // Need to use launcher class path to handle classes
+            // that are not on the boot class path
+            ClassLoader cl = Launcher.getLauncher().getClassLoader();
+            return Class.forName(className, false, cl);
+        } catch (ClassNotFoundException e) {
+            if (optional) {
+                return null;
+            }
+            throw new GraalInternalError("Could not resolve type " + className);
+        }
+    }
+
+    @Override
+    public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode[] argsIncludingReceiver) {
+        ResolvedJavaMethod subst = getSubstitute(b.getMetaAccess());
+        if (receiver != null) {
+            receiver.get();
+        }
+        b.intrinsify(targetMethod, subst, argsIncludingReceiver);
+        return true;
+    }
+
+    public StackTraceElement getApplySourceLocation(MetaAccessProvider metaAccess) {
+        Class<?> c = getClass();
+        for (Method m : c.getDeclaredMethods()) {
+            if (m.getName().equals("execute")) {
+                return metaAccess.lookupJavaMethod(m).asStackTraceElement(0);
+            }
+        }
+        throw new GraalInternalError("could not find method named \"execute\" in " + c.getName());
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Thu Apr 09 17:04:05 2015 +0200
@@ -36,6 +36,7 @@
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.phases.util.*;
+import com.oracle.graal.replacements.amd64.*;
 
 @ServiceProvider(HotSpotBackendFactory.class)
 public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
@@ -187,7 +188,9 @@
     protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider runtime, TargetDescription target, HotSpotConstantReflectionProvider constantReflection,
                     HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements,
                     HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) {
-        return HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch);
+        Plugins plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements);
+        AMD64GraphBuilderPlugins.register(plugins, foreignCalls, (AMD64) target.arch);
+        return plugins;
     }
 
     protected AMD64HotSpotBackend createBackend(HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java	Thu Apr 09 17:04:05 2015 +0200
@@ -33,6 +33,7 @@
 import com.oracle.graal.hotspot.word.*;
 import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.util.*;
+import com.oracle.graal.replacements.sparc.*;
 import com.oracle.graal.sparc.*;
 import com.oracle.graal.sparc.SPARC.CPUFeature;
 
@@ -68,7 +69,7 @@
         HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), target);
         HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime);
         HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordKind);
-        Plugins plugins = createGraphBuilderPlugins(runtime, target, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes);
+        Plugins plugins = createGraphBuilderPlugins(runtime, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes);
         replacements.setGraphBuilderPlugins(plugins);
         HotSpotSuitesProvider suites = createSuites(runtime, plugins);
         HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection,
@@ -77,10 +78,12 @@
         return createBackend(runtime, providers);
     }
 
-    protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider runtime, TargetDescription target, HotSpotMetaAccessProvider metaAccess,
-                    HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, HotSpotStampProvider stampProvider,
-                    HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
-        return HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch);
+    protected Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection,
+                    HotSpotForeignCallsProvider foreignCalls, HotSpotStampProvider stampProvider, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements,
+                    HotSpotWordTypes wordTypes) {
+        Plugins plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements);
+        SPARCGraphBuilderPlugins.register(plugins, foreignCalls);
+        return plugins;
     }
 
     protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime, Plugins plugins) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java	Thu Apr 09 17:04:05 2015 +0200
@@ -22,6 +22,8 @@
  */
 package com.oracle.graal.hotspot.test;
 
+import static com.oracle.graal.java.AbstractBytecodeParser.IntrinsicContext.*;
+
 import java.io.*;
 import java.lang.reflect.*;
 import java.security.*;
@@ -125,13 +127,13 @@
             Method method = lookup(className, methodName);
             if (method != null) {
                 ResolvedJavaMethod installedCodeOwner = getMetaAccess().lookupJavaMethod(method);
-                StructuredGraph subst = getReplacements().getSubstitution(installedCodeOwner, true);
+                StructuredGraph subst = getReplacements().getSubstitution(installedCodeOwner);
                 ResolvedJavaMethod substMethod = subst == null ? null : subst.method();
                 if (substMethod != null) {
                     StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES);
                     Plugins plugins = new Plugins(((HotSpotProviders) getProviders()).getGraphBuilderPlugins());
                     GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
-                    IntrinsicContext initialReplacementContext = new IntrinsicContext(installedCodeOwner, substMethod, null, -2);
+                    IntrinsicContext initialReplacementContext = new IntrinsicContext(installedCodeOwner, substMethod, null, ROOT_COMPILATION_BCI);
                     new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getConstantReflection(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph);
                     Assert.assertNotNull(getCode(installedCodeOwner, graph, true));
                     atLeastOneCompiled = true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Thu Apr 09 17:04:05 2015 +0200
@@ -1444,6 +1444,9 @@
     @HotSpotVMValue(expression = "SharedRuntime::dsin", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticSinAddress;
     @HotSpotVMValue(expression = "SharedRuntime::dcos", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticCosAddress;
     @HotSpotVMValue(expression = "SharedRuntime::dtan", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticTanAddress;
+    @HotSpotVMValue(expression = "SharedRuntime::dexp", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticExpAddress;
+    @HotSpotVMValue(expression = "SharedRuntime::dlog", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticLogAddress;
+    @HotSpotVMValue(expression = "SharedRuntime::dlog10", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticLog10Address;
     @HotSpotVMValue(expression = "SharedRuntime::dpow", get = HotSpotVMValue.Type.ADDRESS) @Stable public long arithmeticPowAddress;
 
     @HotSpotVMValue(expression = "(jint) GraalCounterSize") @Stable public int graalCountersSize;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu Apr 09 17:04:05 2015 +0200
@@ -23,6 +23,7 @@
 package com.oracle.graal.hotspot.meta;
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
+import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
 
 import java.lang.invoke.*;
 
@@ -31,9 +32,8 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graphbuilderconf.*;
 import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
-import com.oracle.graal.graphbuilderconf.*;
 import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver;
 import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration;
 import com.oracle.graal.hotspot.*;
@@ -65,7 +65,7 @@
      * @param stampProvider
      */
     public static Plugins create(HotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection,
-                    SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements, Architecture arch) {
+                    SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements) {
         InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess, constantReflection.getMethodHandleAccess());
 
         Plugins plugins = new Plugins(invocationPlugins);
@@ -85,7 +85,8 @@
         registerCallSitePlugins(invocationPlugins);
         registerReflectionPlugins(invocationPlugins);
         registerStableOptionPlugins(invocationPlugins);
-        StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, arch, invocationPlugins, !config.useHeapProfiler);
+        registerAESPlugins(invocationPlugins, config);
+        StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, invocationPlugins, !config.useHeapProfiler);
 
         return plugins;
     }
@@ -99,6 +100,7 @@
                 return true;
             }
         });
+        r.registerMethodSubstitution(ObjectSubstitutions.class, "hashCode", Receiver.class);
     }
 
     private static void registerClassPlugins(InvocationPlugins plugins) {
@@ -162,21 +164,11 @@
 
     private static void registerSystemPlugins(InvocationPlugins plugins, ForeignCallsProvider foreignCalls) {
         Registration r = new Registration(plugins, System.class);
-        r.register0("currentTimeMillis", new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
-                b.addPush(Kind.Long, new ForeignCallNode(foreignCalls, SystemSubstitutions.JAVA_TIME_MILLIS, StampFactory.forKind(Kind.Long)));
-                return true;
-            }
-        });
-        r.register0("nanoTime", new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
-                b.addPush(Kind.Long, new ForeignCallNode(foreignCalls, SystemSubstitutions.JAVA_TIME_NANOS, StampFactory.forKind(Kind.Long)));
-                return true;
-            }
-        });
+        r.register0("currentTimeMillis", new ForeignCallPlugin(foreignCalls, JAVA_TIME_MILLIS));
+        r.register0("nanoTime", new ForeignCallPlugin(foreignCalls, JAVA_TIME_NANOS));
         r.register1("identityHashCode", Object.class, new InvocationPlugin() {
             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) {
-                b.addPush(new SystemIdentityHashCodeNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), object));
+                b.addPush(new IdentityHashCodeNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), object));
                 return true;
             }
         });
@@ -218,4 +210,25 @@
             }
         });
     }
+
+    private static void registerAESPlugins(InvocationPlugins plugins, HotSpotVMConfig config) {
+        if (config.useAESIntrinsics) {
+            assert config.aescryptEncryptBlockStub != 0L;
+            assert config.aescryptDecryptBlockStub != 0L;
+            assert config.cipherBlockChainingEncryptAESCryptStub != 0L;
+            assert config.cipherBlockChainingDecryptAESCryptStub != 0L;
+            Class<?> c = MethodSubstitutionPlugin.resolveClass("com.sun.crypto.provider.CipherBlockChaining", true);
+            if (c != null) {
+                Registration r = new Registration(plugins, c);
+                r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, "encrypt", Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class);
+                r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, "decrypt", Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class);
+            }
+            c = MethodSubstitutionPlugin.resolveClass("com.sun.crypto.provider.AESCrypt", true);
+            if (c != null) {
+                Registration r = new Registration(plugins, c);
+                r.registerMethodSubstitution(AESCryptSubstitutions.class, "encryptBlock", Receiver.class, byte[].class, int.class, byte[].class, int.class);
+                r.registerMethodSubstitution(AESCryptSubstitutions.class, "decryptBlock", Receiver.class, byte[].class, int.class, byte[].class, int.class);
+            }
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java	Thu Apr 09 17:04:05 2015 +0200
@@ -44,7 +44,6 @@
 import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*;
 import static com.oracle.graal.nodes.java.ForeignCallDescriptors.*;
 import static com.oracle.graal.replacements.Log.*;
-import static com.oracle.graal.replacements.MathSubstitutionsX86.*;
 
 import java.util.*;
 
@@ -150,6 +149,9 @@
         registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_EXP, c.arithmeticExpAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_LOG, c.arithmeticLogAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
+        registerForeignCall(ARITHMETIC_LOG10, c.arithmeticLog10Address, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(ARITHMETIC_POW, c.arithmeticPowAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
         registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any());
 
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java	Thu Apr 09 17:04:05 2015 +0200
@@ -61,19 +61,6 @@
                 return;
             }
         }
-        if (!config.useCountLeadingZerosInstruction) {
-            if (name.equals("numberOfLeadingZeros")) {
-                assert declaringClass.equals(Integer.class) || declaringClass.equals(Long.class);
-                return;
-            }
-        }
-        if (!config.useCountTrailingZerosInstruction) {
-            if (name.equals("numberOfTrailingZeros")) {
-                assert declaringClass.equals(Integer.class);
-                return;
-            }
-        }
-
         if (config.useHeapProfiler) {
             if (plugin instanceof BoxPlugin) {
                 // The heap profiler wants to see all allocations related to boxing
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -28,11 +28,9 @@
 import sun.misc.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
@@ -41,27 +39,8 @@
 /**
  * Substitutions for {@code com.sun.crypto.provider.AESCrypt} methods.
  */
-@ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt", optional = true, defaultGuard = AESCryptSubstitutions.Guard.class)
 public class AESCryptSubstitutions {
 
-    public static class Guard implements SubstitutionGuard {
-        private HotSpotVMConfig config;
-
-        public Guard(HotSpotVMConfig config) {
-            this.config = config;
-        }
-
-        public boolean execute() {
-            if (config.useAESIntrinsics) {
-                assert config.aescryptEncryptBlockStub != 0L;
-                assert config.aescryptDecryptBlockStub != 0L;
-                assert config.cipherBlockChainingEncryptAESCryptStub != 0L;
-                assert config.cipherBlockChainingDecryptAESCryptStub != 0L;
-            }
-            return config.useAESIntrinsics;
-        }
-    }
-
     static final long kOffset;
     static final Class<?> AESCryptClass;
 
@@ -77,12 +56,10 @@
         }
     }
 
-    @MethodSubstitution(isStatic = false)
     static void encryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) {
         crypt(rcvr, in, inOffset, out, outOffset, true);
     }
 
-    @MethodSubstitution(isStatic = false)
     static void decryptBlock(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset) {
         crypt(rcvr, in, inOffset, out, outOffset, false);
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -39,7 +39,6 @@
 /**
  * Substitutions for {@code com.sun.crypto.provider.CipherBlockChaining} methods.
  */
-@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining", optional = true, defaultGuard = AESCryptSubstitutions.Guard.class)
 public class CipherBlockChainingSubstitutions {
 
     private static final long embeddedCipherOffset;
@@ -67,7 +66,6 @@
         return AESCryptSubstitutions.AESCryptClass;
     }
 
-    @MethodSubstitution(isStatic = false)
     static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
         Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
         Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, Kind.Object, LocationIdentity.any());
@@ -80,7 +78,6 @@
         }
     }
 
-    @MethodSubstitution(isStatic = false)
     static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) {
         Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass);
         Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, Kind.Object, LocationIdentity.any());
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -22,7 +22,6 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import java.lang.reflect.*;
 import java.util.zip.*;
 
 import sun.misc.*;
@@ -39,22 +38,8 @@
 @ServiceProvider(ReplacementsProvider.class)
 public class HotSpotSubstitutions implements ReplacementsProvider {
 
-    static class NamedType implements Type {
-        private final String name;
-
-        public NamedType(String name) {
-            this.name = name;
-        }
-
-        @Override
-        public String toString() {
-            return name;
-        }
-    }
-
     @Override
     public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) {
-        replacements.registerSubstitutions(Object.class, ObjectSubstitutions.class);
         replacements.registerSubstitutions(System.class, SystemSubstitutions.class);
         replacements.registerSubstitutions(Thread.class, ThreadSubstitutions.class);
         replacements.registerSubstitutions(Unsafe.class, UnsafeSubstitutions.class);
@@ -62,7 +47,5 @@
         replacements.registerSubstitutions(CRC32.class, CRC32Substitutions.class);
         replacements.registerSubstitutions(Reflection.class, ReflectionSubstitutions.class);
         replacements.registerSubstitutions(CompilerToVMImpl.class, CompilerToVMImplSubstitutions.class);
-        replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.AESCrypt"), AESCryptSubstitutions.class);
-        replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.CipherBlockChaining"), CipherBlockChainingSubstitutions.class);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/IdentityHashCodeNode.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.hotspot.replacements;
+
+import static com.oracle.graal.compiler.common.GraalOptions.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.meta.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
+import com.oracle.graal.replacements.nodes.*;
+
+@NodeInfo
+public final class IdentityHashCodeNode extends PureFunctionMacroNode {
+
+    public static final NodeClass<IdentityHashCodeNode> TYPE = NodeClass.create(IdentityHashCodeNode.class);
+
+    public IdentityHashCodeNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode object) {
+        super(TYPE, invokeKind, targetMethod, bci, returnType, object);
+    }
+
+    @Override
+    protected JavaConstant evaluate(JavaConstant param, MetaAccessProvider metaAccess) {
+        if (ImmutableCode.getValue() || param.isNull()) {
+            return null;
+        }
+        HotSpotObjectConstant c = (HotSpotObjectConstant) param;
+        return JavaConstant.forInt(c.getIdentityHashCode());
+    }
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -24,30 +24,12 @@
 
 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*;
 
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.hotspot.word.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.java.*;
-
 /**
  * Substitutions for {@link java.lang.Object} methods.
  */
-@ClassSubstitution(java.lang.Object.class)
 public class ObjectSubstitutions {
 
-    @MethodSubstitution(isStatic = false, forced = true)
-    public static Class<?> getClass(final Object thisObj) {
-        KlassPointer hub = loadHub(GuardingPiNode.guardingNonNull(thisObj));
-        return HubGetClassNode.readClass(hub);
-    }
-
-    @MethodSubstitution(isStatic = false)
     public static int hashCode(final Object thisObj) {
         return computeHashCode(thisObj);
     }
-
-    @MethodSubstitution(value = "<init>", isStatic = false, forced = true)
-    public static void init(Object thisObj) {
-        RegisterFinalizerNode.register(thisObj);
-    }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.hotspot.replacements;
-
-import static com.oracle.graal.compiler.common.GraalOptions.*;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.hotspot.meta.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
-import com.oracle.graal.replacements.nodes.*;
-
-@NodeInfo
-public final class SystemIdentityHashCodeNode extends PureFunctionMacroNode {
-
-    public static final NodeClass<SystemIdentityHashCodeNode> TYPE = NodeClass.create(SystemIdentityHashCodeNode.class);
-
-    public SystemIdentityHashCodeNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode object) {
-        super(TYPE, invokeKind, targetMethod, bci, returnType, object);
-    }
-
-    @Override
-    protected JavaConstant evaluate(JavaConstant param, MetaAccessProvider metaAccess) {
-        if (ImmutableCode.getValue() || param.isNull()) {
-            return null;
-        }
-        HotSpotObjectConstant c = (HotSpotObjectConstant) param;
-        return JavaConstant.forInt(c.getIdentityHashCode());
-    }
-}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Thu Apr 09 17:04:05 2015 +0200
@@ -37,7 +37,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.bytecode.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
@@ -79,7 +78,7 @@
 
     @Override
     protected void run(StructuredGraph graph, HighTierContext context) {
-        new Instance(context.getMetaAccess(), context.getStampProvider(), null, context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations(), null).run(graph);
+        new Instance(context.getMetaAccess(), context.getStampProvider(), context.getConstantReflection(), graphBuilderConfig, context.getOptimisticOptimizations(), null).run(graph);
     }
 
     public GraphBuilderConfiguration getGraphBuilderConfig() {
@@ -99,26 +98,19 @@
         private final OptimisticOptimizations optimisticOpts;
         private final StampProvider stampProvider;
         private final ConstantReflectionProvider constantReflection;
-        private final SnippetReflectionProvider snippetReflectionProvider;
 
-        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, SnippetReflectionProvider snippetReflectionProvider, ConstantReflectionProvider constantReflection,
-                        GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, ReplacementContext initialReplacementContext) {
+        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig,
+                        OptimisticOptimizations optimisticOpts, ReplacementContext initialReplacementContext) {
             this.graphBuilderConfig = graphBuilderConfig;
             this.optimisticOpts = optimisticOpts;
             this.metaAccess = metaAccess;
             this.stampProvider = stampProvider;
             this.constantReflection = constantReflection;
-            this.snippetReflectionProvider = snippetReflectionProvider;
             this.initialReplacementContext = initialReplacementContext;
 
             assert metaAccess != null;
         }
 
-        public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig,
-                        OptimisticOptimizations optimisticOpts, ReplacementContext initialReplacementContext) {
-            this(metaAccess, stampProvider, null, constantReflection, graphBuilderConfig, optimisticOpts, initialReplacementContext);
-        }
-
         @Override
         protected void run(@SuppressWarnings("hiding") StructuredGraph graph) {
             ResolvedJavaMethod method = graph.method();
@@ -1136,15 +1128,17 @@
                         return;
                     }
 
-                    if (tryInvocationPlugin(args, targetMethod, resultType)) {
-                        if (TraceParserPlugins.getValue()) {
-                            traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
+                    if (invokeKind.isDirect()) {
+                        if (tryInvocationPlugin(args, targetMethod, resultType)) {
+                            if (TraceParserPlugins.getValue()) {
+                                traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)"));
+                            }
+                            return;
                         }
-                        return;
-                    }
 
-                    if (tryInline(args, targetMethod, invokeKind, returnType)) {
-                        return;
+                        if (tryInline(args, targetMethod, returnType)) {
+                            return;
+                        }
                     }
                 } finally {
                     currentInvokeReturnType = null;
@@ -1243,7 +1237,7 @@
                     }
 
                     InvocationPluginAssertions assertions = assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null;
-                    if (InvocationPlugin.execute(this, targetMethod, plugin, invocationPluginReceiver.init(targetMethod, args), args)) {
+                    if (plugin.execute(this, targetMethod, invocationPluginReceiver.init(targetMethod, args), args)) {
                         assert assertions.check(true);
                         return true;
                     }
@@ -1257,22 +1251,26 @@
                 return plugin != null && plugin.apply(this, targetMethod, args);
             }
 
-            private boolean tryInline(ValueNode[] args, ResolvedJavaMethod targetMethod, InvokeKind invokeKind, JavaType returnType) {
+            private boolean tryInline(ValueNode[] args, ResolvedJavaMethod targetMethod, JavaType returnType) {
                 InlineInvokePlugin plugin = graphBuilderConfig.getPlugins().getInlineInvokePlugin();
                 boolean canBeInlined = parsingReplacement() || targetMethod.canBeInlined();
-                if (plugin == null || !invokeKind.isDirect() || !canBeInlined) {
+                if (plugin == null || !canBeInlined) {
                     return false;
                 }
                 InlineInfo inlineInfo = plugin.getInlineInfo(this, targetMethod, args, returnType);
                 if (inlineInfo != null) {
-                    return inline(plugin, targetMethod, inlineInfo, args);
+                    return inline(plugin, targetMethod, inlineInfo.methodToInline, inlineInfo.isReplacement, inlineInfo.isIntrinsic, args);
                 }
                 return false;
             }
 
-            public boolean inline(InlineInvokePlugin plugin, ResolvedJavaMethod targetMethod, InlineInfo inlineInfo, ValueNode[] args) {
+            public void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args) {
+                boolean res = inline(null, targetMethod, substitute, true, true, args);
+                assert res : "failed to inline " + substitute;
+            }
+
+            private boolean inline(InlineInvokePlugin plugin, ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, boolean isReplacement, boolean isIntrinsic, ValueNode[] args) {
                 int bci = bci();
-                ResolvedJavaMethod inlinedMethod = inlineInfo.methodToInline;
                 if (TraceInlineDuringParsing.getValue() || TraceParserPlugins.getValue()) {
                     if (targetMethod.equals(inlinedMethod)) {
                         traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)"));
@@ -1308,9 +1306,9 @@
                         }
                     }
                 } else {
-                    if (context == null && inlineInfo.isReplacement) {
+                    if (context == null && isReplacement) {
                         assert !inlinedMethod.equals(targetMethod);
-                        if (inlineInfo.isIntrinsic) {
+                        if (isIntrinsic) {
                             context = new IntrinsicContext(targetMethod, inlinedMethod, args, bci);
                         } else {
                             context = new ReplacementContext(targetMethod, inlinedMethod);
@@ -2365,10 +2363,6 @@
                 return constantReflection;
             }
 
-            public SnippetReflectionProvider getSnippetReflection() {
-                return snippetReflectionProvider;
-            }
-
             /**
              * Gets the graph being processed by this builder.
              */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_hashCode02.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ */
+package com.oracle.graal.jtt.lang;
+
+import java.time.*;
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.jtt.*;
+
+public final class Object_hashCode02 extends JTTTest {
+
+    public static final Object obj1 = new Object();
+    public static final Object obj2 = DayOfWeek.FRIDAY;
+    public static final Object obj3 = new HashMap<>();
+
+    public static int test(int a) {
+        if (a == 1) {
+            return obj1.hashCode();
+        }
+        if (a == 2) {
+            return obj2.hashCode();
+        }
+        return obj3.hashCode();
+    }
+
+    @Test
+    public void run0() throws Throwable {
+        runTest("test", 1);
+    }
+
+    @Test
+    public void run1() throws Throwable {
+        runTest("test", 2);
+    }
+
+    @Test
+    public void run2() throws Throwable {
+        runTest("test", 3);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArithmeticLIRGenerator.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.lir.amd64;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * This interface can be used to generate AMD64 LIR for arithmetic operations.
+ */
+public interface AMD64ArithmeticLIRGenerator {
+
+    Value emitMathLog(Value input, boolean base10);
+
+    Value emitMathCos(Value input);
+
+    Value emitMathSin(Value input);
+
+    Value emitMathTan(Value input);
+}
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java	Thu Apr 09 17:04:05 2015 +0200
@@ -35,11 +35,6 @@
 
     public enum IntrinsicOpcode {
         SQRT,
-        SIN,
-        COS,
-        TAN,
-        LOG,
-        LOG10,
         ABS
     }
 
@@ -83,11 +78,6 @@
                         GraalInternalError.shouldNotReachHere();
                 }
                 break;
-            case LOG:
-            case LOG10:
-            case SIN:
-            case COS:
-            case TAN:
             default:
                 throw GraalInternalError.shouldNotReachHere();
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java	Thu Apr 09 17:04:05 2015 +0200
@@ -87,12 +87,4 @@
     Value emitMathAbs(Value input);
 
     Value emitMathSqrt(Value input);
-
-    Value emitMathLog(Value input, boolean base10);
-
-    Value emitMathCos(Value input);
-
-    Value emitMathSin(Value input);
-
-    Value emitMathTan(Value input);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java	Thu Apr 09 17:04:05 2015 +0200
@@ -51,7 +51,7 @@
     public static final NodeClass<BreakpointNode> TYPE = NodeClass.create(BreakpointNode.class);
     @Input NodeInputList<ValueNode> arguments;
 
-    public BreakpointNode(ValueNode[] arguments) {
+    public BreakpointNode(ValueNode... arguments) {
         super(TYPE, StampFactory.forVoid());
         this.arguments = new NodeInputList<>(this, arguments);
     }
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java	Thu Apr 09 17:04:05 2015 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 /**
- * Count the number of leading zeros.
+ * Count the number of leading zeros using the {@code lzcntq} or {@code lzcntl} instructions.
  */
 @NodeInfo
 public final class AMD64CountLeadingZerosNode extends UnaryNode implements LIRLowerable {
@@ -57,36 +57,23 @@
         return updateStamp(StampFactory.forInteger(Kind.Int, min, max));
     }
 
-    @Override
-    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
-        if (forValue.isConstant()) {
-            JavaConstant c = forValue.asJavaConstant();
-            if (forValue.getKind() == Kind.Int) {
+    public static ValueNode tryFold(ValueNode value) {
+        if (value.isConstant()) {
+            JavaConstant c = value.asJavaConstant();
+            if (value.getKind() == Kind.Int) {
                 return ConstantNode.forInt(Integer.numberOfLeadingZeros(c.asInt()));
             } else {
                 return ConstantNode.forInt(Long.numberOfLeadingZeros(c.asLong()));
             }
         }
-        return this;
+        return null;
     }
 
-    /**
-     * Raw intrinsic for lzcntq instruction.
-     *
-     * @param v
-     * @return number of trailing zeros
-     */
-    @NodeIntrinsic
-    public static native int count(long v);
-
-    /**
-     * Raw intrinsic for lzcntl instruction.
-     *
-     * @param v
-     * @return number of trailing zeros
-     */
-    @NodeIntrinsic
-    public static native int count(int v);
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        ValueNode folded = tryFold(forValue);
+        return folded != null ? folded : this;
+    }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java	Thu Apr 09 17:04:05 2015 +0200
@@ -33,7 +33,7 @@
 import com.oracle.graal.nodes.spi.*;
 
 /**
- * Count the number of trailing zeros.
+ * Count the number of trailing zeros using the {@code tzcntq} or {@code tzcntl} instructions.
  */
 @NodeInfo
 public final class AMD64CountTrailingZerosNode extends UnaryNode implements LIRLowerable {
@@ -53,36 +53,23 @@
         return updateStamp(StampFactory.forInteger(Kind.Int, min, max));
     }
 
-    @Override
-    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
-        if (forValue.isConstant()) {
-            JavaConstant c = forValue.asJavaConstant();
-            if (forValue.getKind() == Kind.Int) {
+    public static ValueNode tryFold(ValueNode value) {
+        if (value.isConstant()) {
+            JavaConstant c = value.asJavaConstant();
+            if (value.getKind() == Kind.Int) {
                 return ConstantNode.forInt(Integer.numberOfTrailingZeros(c.asInt()));
             } else {
                 return ConstantNode.forInt(Long.numberOfTrailingZeros(c.asLong()));
             }
         }
-        return this;
+        return null;
     }
 
-    /**
-     * Raw intrinsic for tzcntq instruction.
-     *
-     * @param v
-     * @return number of trailing zeros
-     */
-    @NodeIntrinsic
-    public static native int count(long v);
-
-    /**
-     * Raw intrinsic for tzcntl instruction.
-     *
-     * @param v
-     * @return number of trailing zeros
-     */
-    @NodeIntrinsic
-    public static native int count(int v);
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        ValueNode folded = tryFold(forValue);
+        return folded != null ? folded : this;
+    }
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.amd64;
+
+import static com.oracle.graal.compiler.target.Backend.*;
+import static com.oracle.graal.replacements.amd64.AMD64MathIntrinsicNode.Operation.*;
+import sun.misc.*;
+
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver;
+import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.java.*;
+import com.oracle.graal.replacements.*;
+
+public class AMD64GraphBuilderPlugins {
+
+    public static void register(Plugins plugins, ForeignCallsProvider foreignCalls, AMD64 arch) {
+        InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
+        registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, Kind.Int, arch);
+        registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, Kind.Long, arch);
+        registerUnsafePlugins(invocationPlugins);
+        registerMathPlugins(invocationPlugins, foreignCalls);
+    }
+
+    private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class<?> substituteDeclaringClass, Kind kind, AMD64 arch) {
+        Class<?> declaringClass = kind.toBoxedJavaClass();
+        Class<?> type = kind.toJavaClass();
+        Registration r = new Registration(plugins, declaringClass);
+        if (arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction)) {
+            r.register1("numberOfLeadingZeros", type, new InvocationPlugin() {
+                public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
+                    ValueNode folded = AMD64CountLeadingZerosNode.tryFold(value);
+                    if (folded != null) {
+                        b.addPush(folded);
+                    } else {
+                        b.addPush(new AMD64CountLeadingZerosNode(value));
+                    }
+                    return true;
+                }
+            });
+        } else {
+            r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type);
+        }
+        if (arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction)) {
+            r.register1("numberOfTrailingZeros", type, new InvocationPlugin() {
+                public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
+                    ValueNode folded = AMD64CountTrailingZerosNode.tryFold(value);
+                    if (folded != null) {
+                        b.addPush(folded);
+                    } else {
+                        b.addPush(new AMD64CountTrailingZerosNode(value));
+                    }
+                    return true;
+                }
+            });
+        } else {
+            r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type);
+        }
+    }
+
+    private static void registerMathPlugins(InvocationPlugins plugins, ForeignCallsProvider foreignCalls) {
+        Registration r = new Registration(plugins, Math.class);
+        r.register1("log", Double.TYPE, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
+                b.push(Kind.Double, b.recursiveAppend(AMD64MathIntrinsicNode.create(value, LOG)));
+                return true;
+            }
+        });
+        r.register1("log10", Double.TYPE, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
+                b.push(Kind.Double, b.recursiveAppend(AMD64MathIntrinsicNode.create(value, LOG10)));
+                return true;
+            }
+        });
+        r.registerMethodSubstitution(AMD64MathSubstitutions.class, "sin", double.class);
+        r.registerMethodSubstitution(AMD64MathSubstitutions.class, "cos", double.class);
+        r.registerMethodSubstitution(AMD64MathSubstitutions.class, "tan", double.class);
+        r.registerMethodSubstitution(AMD64MathSubstitutions.class, "pow", double.class, double.class);
+        r.register1("exp", Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_EXP));
+    }
+
+    private static void registerUnsafePlugins(InvocationPlugins plugins) {
+        Registration r = new Registration(plugins, Unsafe.class);
+
+        for (Kind kind : new Kind[]{Kind.Int, Kind.Long, Kind.Object}) {
+            Class<?> javaClass = kind == Kind.Object ? Object.class : kind.toJavaClass();
+
+            r.register4("getAndSet" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() {
+                public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode value) {
+                    // Emits a null-check for the otherwise unused receiver
+                    unsafe.get();
+                    b.addPush(kind.getStackKind(), new AtomicReadAndWriteNode(object, offset, value, kind, LocationIdentity.any()));
+                    return true;
+                }
+            });
+            if (kind != Kind.Object) {
+                r.register4("getAndAdd" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() {
+                    public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode delta) {
+                        // Emits a null-check for the otherwise unused receiver
+                        unsafe.get();
+                        b.addPush(kind.getStackKind(), new AtomicReadAndAddNode(object, offset, delta, LocationIdentity.any()));
+                        return true;
+                    }
+                });
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Guards.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.graal.replacements.amd64;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.amd64.*;
-
-public class AMD64Guards {
-    public static class CountLeadingZerosSupported implements SubstitutionGuard {
-        private AMD64 arch;
-
-        public CountLeadingZerosSupported(Architecture arch) {
-            this.arch = (AMD64) arch;
-        }
-
-        public boolean execute() {
-            return arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction);
-        }
-    }
-
-    public static class CountTrailingZerosSupported implements SubstitutionGuard {
-        private AMD64 arch;
-
-        public CountTrailingZerosSupported(Architecture arch) {
-            this.arch = (AMD64) arch;
-        }
-
-        public boolean execute() {
-            return arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction);
-        }
-    }
-}
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64IntegerSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.graal.replacements.amd64;
-
-import com.oracle.graal.api.replacements.*;
-
-@ClassSubstitution(Integer.class)
-public class AMD64IntegerSubstitutions {
-
-    @MethodSubstitution(guard = AMD64Guards.CountLeadingZerosSupported.class)
-    public static int numberOfLeadingZeros(int i) {
-        return AMD64CountLeadingZerosNode.count(i);
-    }
-
-    @MethodSubstitution(guard = AMD64Guards.CountTrailingZerosSupported.class)
-    public static int numberOfTrailingZeros(int i) {
-        return AMD64CountTrailingZerosNode.count(i);
-    }
-}
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64LongSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.graal.replacements.amd64;
-
-import com.oracle.graal.api.replacements.*;
-
-@ClassSubstitution(Long.class)
-public class AMD64LongSubstitutions {
-
-    @MethodSubstitution(guard = AMD64Guards.CountLeadingZerosSupported.class)
-    public static int numberOfLeadingZeros(long i) {
-        return AMD64CountLeadingZerosNode.count(i);
-    }
-
-    @MethodSubstitution(guard = AMD64Guards.CountTrailingZerosSupported.class)
-    public static int numberOfTrailingZeros(long i) {
-        return AMD64CountTrailingZerosNode.count(i);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathIntrinsicNode.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.amd64;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.lir.amd64.*;
+import com.oracle.graal.lir.gen.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo
+public final class AMD64MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable {
+
+    public static final NodeClass<AMD64MathIntrinsicNode> TYPE = NodeClass.create(AMD64MathIntrinsicNode.class);
+    protected final Operation operation;
+
+    public enum Operation {
+        LOG,
+        LOG10,
+        SIN,
+        COS,
+        TAN
+    }
+
+    public Operation operation() {
+        return operation;
+    }
+
+    public static ValueNode create(ValueNode value, Operation op) {
+        ValueNode c = tryConstantFold(value, op);
+        if (c != null) {
+            return c;
+        }
+        return new AMD64MathIntrinsicNode(value, op);
+    }
+
+    protected static ValueNode tryConstantFold(ValueNode value, Operation op) {
+        if (value.isConstant()) {
+            double ret = doCompute(value.asJavaConstant().asDouble(), op);
+            return ConstantNode.forDouble(ret);
+        }
+        return null;
+    }
+
+    protected AMD64MathIntrinsicNode(ValueNode value, Operation op) {
+        super(TYPE, StampFactory.forKind(Kind.Double), value);
+        assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64;
+        this.operation = op;
+    }
+
+    @Override
+    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator lirGen) {
+        AMD64ArithmeticLIRGenerator gen = (AMD64ArithmeticLIRGenerator) lirGen;
+        Value input = builder.operand(getValue());
+        Value result;
+        switch (operation()) {
+            case LOG:
+                result = gen.emitMathLog(input, false);
+                break;
+            case LOG10:
+                result = gen.emitMathLog(input, true);
+                break;
+            case SIN:
+                result = gen.emitMathSin(input);
+                break;
+            case COS:
+                result = gen.emitMathCos(input);
+                break;
+            case TAN:
+                result = gen.emitMathTan(input);
+                break;
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        builder.setResult(this, result);
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
+        ValueNode c = tryConstantFold(forValue, operation());
+        if (c != null) {
+            return c;
+        }
+        return this;
+    }
+
+    @NodeIntrinsic
+    public static native double compute(double value, @ConstantNodeParameter Operation op);
+
+    private static double doCompute(double value, Operation op) {
+        switch (op) {
+            case LOG:
+                return Math.log(value);
+            case LOG10:
+                return Math.log10(value);
+            case SIN:
+                return Math.sin(value);
+            case COS:
+                return Math.cos(value);
+            case TAN:
+                return Math.tan(value);
+            default:
+                throw new GraalInternalError("unknown op %s", op);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.amd64;
+
+import static com.oracle.graal.compiler.target.Backend.*;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.Node.ConstantNodeParameter;
+import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.replacements.amd64.AMD64MathIntrinsicNode.Operation;
+
+/**
+ * Substitutions for some {@link java.lang.Math} methods that leverage AMD64 instructions for
+ * selected input values.
+ */
+public class AMD64MathSubstitutions {
+
+    private static final double PI_4 = Math.PI / 4;
+
+    /**
+     * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp).
+     */
+    public static double pow(double x, double y) {
+        // If the second argument is positive or negative zero, then the result is 1.0.
+        if (y == 0.0D) {
+            return 1;
+        }
+
+        // If the second argument is 1.0, then the result is the same as the first argument.
+        if (y == 1.0D) {
+            return x;
+        }
+
+        // If the second argument is NaN, then the result is NaN.
+        if (Double.isNaN(y)) {
+            return Double.NaN;
+        }
+
+        // If the first argument is NaN and the second argument is nonzero, then the result is NaN.
+        if (Double.isNaN(x) && y != 0.0D) {
+            return Double.NaN;
+        }
+
+        // x**-1 = 1/x
+        if (y == -1.0D) {
+            return 1 / x;
+        }
+
+        // x**2 = x*x
+        if (y == 2.0D) {
+            return x * x;
+        }
+
+        // x**0.5 = sqrt(x)
+        if (y == 0.5D && x >= 0.0D) {
+            return Math.sqrt(x);
+        }
+        return callDouble2(ARITHMETIC_POW, x, y);
+    }
+
+    // NOTE on snippets below:
+    // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the
+    // exact result, but x87 trigonometric FPU instructions are only that
+    // accurate within [-pi/4, pi/4]. Examine the passed value and provide
+    // a slow path for inputs outside of that interval.
+
+    public static double sin(double x) {
+        if (Math.abs(x) < PI_4) {
+            return AMD64MathIntrinsicNode.compute(x, Operation.SIN);
+        } else {
+            return callDouble1(ARITHMETIC_SIN, x);
+        }
+    }
+
+    public static double cos(double x) {
+        if (Math.abs(x) < PI_4) {
+            return AMD64MathIntrinsicNode.compute(x, Operation.COS);
+        } else {
+            return callDouble1(ARITHMETIC_COS, x);
+        }
+    }
+
+    public static double tan(double x) {
+        if (Math.abs(x) < PI_4) {
+            return AMD64MathIntrinsicNode.compute(x, Operation.TAN);
+        } else {
+            return callDouble1(ARITHMETIC_TAN, x);
+        }
+    }
+
+    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
+    private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value);
+
+    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
+    private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b);
+}
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.oracle.graal.replacements.amd64;
-
-import static com.oracle.graal.compiler.common.GraalOptions.*;
-
-import com.oracle.graal.amd64.*;
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * Method substitutions that are VM-independent but AMD64-dependent.
- */
-@ServiceProvider(ReplacementsProvider.class)
-public class AMD64Substitutions implements ReplacementsProvider {
-
-    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider lowerer, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) {
-        if (Intrinsify.getValue() && target.arch instanceof AMD64) {
-            replacements.registerSubstitutions(Integer.class, AMD64IntegerSubstitutions.class);
-            replacements.registerSubstitutions(Long.class, AMD64LongSubstitutions.class);
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.sparc/src/com/oracle/graal/replacements/sparc/SPARCGraphBuilderPlugins.java	Thu Apr 09 17:04:05 2015 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.sparc;
+
+import static com.oracle.graal.compiler.target.Backend.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration;
+import com.oracle.graal.replacements.*;
+
+public class SPARCGraphBuilderPlugins {
+
+    public static void register(Plugins plugins, ForeignCallsProvider foreignCalls) {
+        InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
+        registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, Kind.Int);
+        registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, Kind.Long);
+        registerMathPlugins(invocationPlugins, foreignCalls);
+    }
+
+    private static void registerIntegerLongPlugins(InvocationPlugins plugins, Class<?> substituteDeclaringClass, Kind kind) {
+        Class<?> declaringClass = kind.toBoxedJavaClass();
+        Class<?> type = kind.toJavaClass();
+        Registration r = new Registration(plugins, declaringClass);
+        r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type);
+        r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type);
+    }
+
+    private static void registerMathPlugins(InvocationPlugins plugins, ForeignCallsProvider foreignCalls) {
+        Registration r = new Registration(plugins, Math.class);
+        r.register1("sin", Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_SIN));
+        r.register1("cos", Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_COS));
+        r.register1("tan", Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_TAN));
+        r.register1("exp", Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_EXP));
+        r.register1("log", Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_LOG));
+        r.register1("log10", Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_LOG10));
+        r.register2("pow", Double.TYPE, Double.TYPE, new ForeignCallPlugin(foreignCalls, ARITHMETIC_POW));
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -25,17 +25,14 @@
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 
 /**
  * Substitutions for {@link java.lang.reflect.Array} methods.
  */
-@ClassSubstitution(java.lang.reflect.Array.class)
 public class ArraySubstitutions {
 
-    @MethodSubstitution
     public static Object newInstance(Class<?> componentType, int length) throws NegativeArraySizeException {
         // The error cases must be handled here since DynamicNewArrayNode can only deoptimize the
         // caller in response to exceptions.
@@ -48,7 +45,6 @@
         return DynamicNewArrayNode.newArray(GuardingPiNode.asNonNullClass(componentType), length);
     }
 
-    @MethodSubstitution
     public static int getLength(Object array) {
         if (!array.getClass().isArray()) {
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraysSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraysSubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -22,16 +22,13 @@
  */
 package com.oracle.graal.replacements;
 
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
 
 /**
  * Substitutions for {@link java.util.Arrays} methods.
  */
-@ClassSubstitution(value = java.util.Arrays.class)
 public class ArraysSubstitutions {
 
-    @MethodSubstitution
     public static boolean equals(boolean[] a, boolean[] a2) {
         if (a == a2) {
             return true;
@@ -42,7 +39,6 @@
         return ArrayEqualsNode.equals(a, a2, a.length);
     }
 
-    @MethodSubstitution
     public static boolean equals(byte[] a, byte[] a2) {
         if (a == a2) {
             return true;
@@ -53,7 +49,6 @@
         return ArrayEqualsNode.equals(a, a2, a.length);
     }
 
-    @MethodSubstitution
     public static boolean equals(char[] a, char[] a2) {
         if (a == a2) {
             return true;
@@ -64,7 +59,6 @@
         return ArrayEqualsNode.equals(a, a2, a.length);
     }
 
-    @MethodSubstitution
     public static boolean equals(short[] a, short[] a2) {
         if (a == a2) {
             return true;
@@ -75,7 +69,6 @@
         return ArrayEqualsNode.equals(a, a2, a.length);
     }
 
-    @MethodSubstitution
     public static boolean equals(int[] a, int[] a2) {
         if (a == a2) {
             return true;
@@ -86,7 +79,6 @@
         return ArrayEqualsNode.equals(a, a2, a.length);
     }
 
-    @MethodSubstitution
     public static boolean equals(long[] a, long[] a2) {
         if (a == a2) {
             return true;
@@ -97,7 +89,6 @@
         return ArrayEqualsNode.equals(a, a2, a.length);
     }
 
-    @MethodSubstitution
     public static boolean equals(float[] a, float[] a2) {
         if (a == a2) {
             return true;
@@ -108,7 +99,6 @@
         return ArrayEqualsNode.equals(a, a2, a.length);
     }
 
-    @MethodSubstitution
     public static boolean equals(double[] a, double[] a2) {
         if (a == a2) {
             return true;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.replacements;
-
-import static com.oracle.graal.compiler.common.GraalOptions.*;
-
-import java.lang.reflect.*;
-import java.util.*;
-
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.nodes.spi.*;
-
-/**
- * Method substitutions that are VM-independent.
- */
-@ServiceProvider(ReplacementsProvider.class)
-public class GraalMethodSubstitutions implements ReplacementsProvider {
-
-    public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) {
-        if (Intrinsify.getValue()) {
-            replacements.registerSubstitutions(Arrays.class, ArraysSubstitutions.class);
-            replacements.registerSubstitutions(Array.class, ArraySubstitutions.class);
-            replacements.registerSubstitutions(String.class, StringSubstitutions.class);
-            replacements.registerSubstitutions(Math.class, MathSubstitutionsX86.class);
-            replacements.registerSubstitutions(Long.class, LongSubstitutions.class);
-            replacements.registerSubstitutions(Integer.class, IntegerSubstitutions.class);
-        }
-    }
-}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java	Thu Apr 09 17:04:05 2015 +0200
@@ -24,7 +24,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graphbuilderconf.*;
@@ -34,7 +33,6 @@
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
-import com.oracle.graal.phases.util.*;
 
 /**
  * Implementation of {@link GraphBuilderContext} used to produce a graph for a method based on an
@@ -42,17 +40,19 @@
  */
 public class IntrinsicGraphBuilder implements GraphBuilderContext, Receiver {
 
-    private final Providers providers;
-    private final SnippetReflectionProvider snippetReflection;
+    private final MetaAccessProvider metaAccess;
+    private final ConstantReflectionProvider constantReflection;
+    private final StampProvider stampProvider;
     private final StructuredGraph graph;
     private final ResolvedJavaMethod method;
     private FixedWithNextNode lastInstr;
     private ValueNode[] arguments;
     private ValueNode returnValue;
 
-    public IntrinsicGraphBuilder(Providers providers, SnippetReflectionProvider snippetReflection, ResolvedJavaMethod method) {
-        this.providers = providers;
-        this.snippetReflection = snippetReflection;
+    public IntrinsicGraphBuilder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, ResolvedJavaMethod method) {
+        this.metaAccess = metaAccess;
+        this.constantReflection = constantReflection;
+        this.stampProvider = stampProvider;
         this.graph = new StructuredGraph(method, AllowAssumptions.YES);
         this.method = method;
         this.lastInstr = graph.start();
@@ -135,19 +135,15 @@
     }
 
     public StampProvider getStampProvider() {
-        return providers.getStampProvider();
+        return stampProvider;
     }
 
     public MetaAccessProvider getMetaAccess() {
-        return providers.getMetaAccess();
+        return metaAccess;
     }
 
     public ConstantReflectionProvider getConstantReflection() {
-        return providers.getConstantReflection();
-    }
-
-    public SnippetReflectionProvider getSnippetReflection() {
-        return snippetReflection;
+        return constantReflection;
     }
 
     public StructuredGraph getGraph() {
@@ -200,11 +196,20 @@
 
     public StructuredGraph buildGraph(InvocationPlugin plugin) {
         Receiver receiver = method.isStatic() ? null : this;
-        if (InvocationPlugin.execute(this, method, plugin, receiver, arguments)) {
+        if (plugin.execute(this, method, receiver, arguments)) {
             assert (returnValue != null) == (method.getSignature().getReturnKind() != Kind.Void) : method;
             append(new ReturnNode(returnValue));
             return graph;
         }
         return null;
     }
+
+    public void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args) {
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s:intrinsic", method.format("%H.%n(%p)"));
+    }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -22,13 +22,10 @@
  */
 package com.oracle.graal.replacements;
 
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
 
-@ClassSubstitution(Long.class)
 public class LongSubstitutions {
 
-    @MethodSubstitution
     public static int numberOfLeadingZeros(long i) {
         if (i == 0) {
             return 64;
@@ -36,7 +33,6 @@
         return 63 - BitScanReverseNode.unsafeScan(i);
     }
 
-    @MethodSubstitution
     public static int numberOfTrailingZeros(long i) {
         if (i == 0) {
             return 64;
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.replacements;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.graph.Node.ConstantNodeParameter;
-import com.oracle.graal.graph.Node.NodeIntrinsic;
-import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.replacements.nodes.*;
-import com.oracle.graal.replacements.nodes.MathIntrinsicNode.Operation;
-
-/**
- * Substitutions for {@link java.lang.Math} methods.
- */
-@ClassSubstitution(value = java.lang.Math.class)
-public class MathSubstitutionsX86 {
-
-    private static final double PI_4 = Math.PI / 4;
-
-    /**
-     * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp).
-     */
-    @MethodSubstitution(guard = MathGuard.class)
-    public static double pow(double x, double y) {
-        // If the second argument is positive or negative zero, then the result is 1.0.
-        if (y == 0.0D) {
-            return 1;
-        }
-
-        // If the second argument is 1.0, then the result is the same as the first argument.
-        if (y == 1.0D) {
-            return x;
-        }
-
-        // If the second argument is NaN, then the result is NaN.
-        if (Double.isNaN(y)) {
-            return Double.NaN;
-        }
-
-        // If the first argument is NaN and the second argument is nonzero, then the result is NaN.
-        if (Double.isNaN(x) && y != 0.0D) {
-            return Double.NaN;
-        }
-
-        // x**-1 = 1/x
-        if (y == -1.0D) {
-            return 1 / x;
-        }
-
-        // x**2 = x*x
-        if (y == 2.0D) {
-            return x * x;
-        }
-
-        // x**0.5 = sqrt(x)
-        if (y == 0.5D && x >= 0.0D) {
-            return Math.sqrt(x);
-        }
-        return callDouble2(ARITHMETIC_POW, x, y);
-    }
-
-    // NOTE on snippets below:
-    // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the
-    // exact result, but x87 trigonometric FPU instructions are only that
-    // accurate within [-pi/4, pi/4]. Examine the passed value and provide
-    // a slow path for inputs outside of that interval.
-
-    @MethodSubstitution(guard = MathGuard.class)
-    public static double sin(double x) {
-        if (Math.abs(x) < PI_4) {
-            return MathIntrinsicNode.compute(x, Operation.SIN);
-        } else {
-            return callDouble1(ARITHMETIC_SIN, x);
-        }
-    }
-
-    @MethodSubstitution(guard = MathGuard.class)
-    public static double cos(double x) {
-        if (Math.abs(x) < PI_4) {
-            return MathIntrinsicNode.compute(x, Operation.COS);
-        } else {
-            return callDouble1(ARITHMETIC_COS, x);
-        }
-    }
-
-    @MethodSubstitution(guard = MathGuard.class)
-    public static double tan(double x) {
-        if (Math.abs(x) < PI_4) {
-            return MathIntrinsicNode.compute(x, Operation.TAN);
-        } else {
-            return callDouble1(ARITHMETIC_TAN, x);
-        }
-    }
-
-    public static class MathGuard implements SubstitutionGuard {
-        public boolean execute() {
-            // FIXME should return whether the current compilation target supports these
-            String arch = System.getProperty("os.arch");
-            return arch.equals("amd64") || arch.equals("x86_64");
-        }
-    }
-
-    public static final ForeignCallDescriptor ARITHMETIC_SIN = new ForeignCallDescriptor("arithmeticSin", double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_COS = new ForeignCallDescriptor("arithmeticCos", double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_TAN = new ForeignCallDescriptor("arithmeticTan", double.class, double.class);
-    public static final ForeignCallDescriptor ARITHMETIC_POW = new ForeignCallDescriptor("arithmeticPow", double.class, double.class, double.class);
-
-    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
-    private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value);
-
-    @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true)
-    private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b);
-}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Thu Apr 09 17:04:05 2015 +0200
@@ -337,17 +337,23 @@
 
     @Override
     public StructuredGraph getSubstitution(ResolvedJavaMethod original, boolean fromBytecodeOnly) {
+        ResolvedJavaMethod substitute = null;
         if (!fromBytecodeOnly) {
             InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(original);
-            if (plugin != null) {
-                StructuredGraph graph = new IntrinsicGraphBuilder(providers, snippetReflection, original).buildGraph(plugin);
+            if (plugin instanceof MethodSubstitutionPlugin) {
+                MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin;
+                substitute = msplugin.getSubstitute(providers.getMetaAccess());
+            } else if (plugin != null) {
+                StructuredGraph graph = new IntrinsicGraphBuilder(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider(), original).buildGraph(plugin);
                 if (graph != null) {
                     return graph;
                 }
             }
         }
-        ClassReplacements cr = getClassReplacements(original.getDeclaringClass().getName());
-        ResolvedJavaMethod substitute = cr == null ? null : cr.methodSubstitutions.get(original);
+        if (substitute == null) {
+            ClassReplacements cr = getClassReplacements(original.getDeclaringClass().getName());
+            substitute = cr == null ? null : cr.methodSubstitutions.get(original);
+        }
         if (substitute == null) {
             return null;
         }
@@ -661,12 +667,11 @@
         protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig,
                         OptimisticOptimizations optimisticOpts) {
             ReplacementContext initialReplacementContext = null;
-            if (method.getAnnotation(MethodSubstitution.class) != null) {
+            if (method.getAnnotation(Snippet.class) == null) {
                 // Late inlined intrinsic
                 initialReplacementContext = new IntrinsicContext(substitutedMethod, method, null, -1);
             } else {
                 // Snippet
-                assert method.getAnnotation(Snippet.class) != null;
                 ResolvedJavaMethod original = substitutedMethod != null ? substitutedMethod : method;
                 initialReplacementContext = new ReplacementContext(original, method);
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java	Thu Apr 09 17:04:05 2015 +0200
@@ -23,12 +23,16 @@
 package com.oracle.graal.replacements;
 
 import static com.oracle.graal.api.code.MemoryBarriers.*;
-import static com.oracle.graal.replacements.nodes.MathIntrinsicNode.Operation.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
 import sun.misc.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.directives.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
@@ -57,10 +61,10 @@
     }
     // @formatter:on
 
-    public static void registerInvocationPlugins(MetaAccessProvider metaAccess, Architecture arch, InvocationPlugins plugins, boolean useBoxingPlugins) {
+    public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins, boolean useBoxingPlugins) {
         registerObjectPlugins(plugins);
         registerClassPlugins(plugins);
-        registerMathPlugins(arch, plugins);
+        registerMathPlugins(plugins);
         registerUnsignedMathPlugins(plugins);
         registerCharacterPlugins(plugins);
         registerShortPlugins(plugins);
@@ -68,7 +72,10 @@
         registerIntegerLongPlugins(plugins, Kind.Long);
         registerFloatPlugins(plugins);
         registerDoublePlugins(plugins);
-        registerUnsafePlugins(arch, plugins);
+        registerStringPlugins(plugins);
+        registerArraysPlugins(plugins);
+        registerArrayPlugins(plugins);
+        registerUnsafePlugins(plugins);
         registerEdgesPlugins(metaAccess, plugins);
         registerGraalDirectivesPlugins(plugins);
         if (useBoxingPlugins) {
@@ -79,7 +86,48 @@
         }
     }
 
-    private static void registerUnsafePlugins(Architecture arch, InvocationPlugins plugins) {
+    private static final Field STRING_VALUE_FIELD;
+    static {
+        try {
+            STRING_VALUE_FIELD = String.class.getDeclaredField("value");
+        } catch (NoSuchFieldException e) {
+            throw new GraalInternalError(e);
+        }
+    }
+
+    private static void registerStringPlugins(InvocationPlugins plugins) {
+        Registration r = new Registration(plugins, String.class);
+        r.registerMethodSubstitution(StringSubstitutions.class, "equals", Receiver.class, Object.class);
+
+        r = new Registration(plugins, StringSubstitutions.class);
+        r.register1("getValue", String.class, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
+                ResolvedJavaField field = b.getMetaAccess().lookupJavaField(STRING_VALUE_FIELD);
+                b.addPush(new LoadFieldNode(value, field));
+                return true;
+            }
+        });
+    }
+
+    private static void registerArraysPlugins(InvocationPlugins plugins) {
+        Registration r = new Registration(plugins, Arrays.class);
+        r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", boolean[].class, boolean[].class);
+        r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", byte[].class, byte[].class);
+        r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", short[].class, short[].class);
+        r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", char[].class, char[].class);
+        r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", int[].class, int[].class);
+        r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", float[].class, float[].class);
+        r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", long[].class, long[].class);
+        r.registerMethodSubstitution(ArraysSubstitutions.class, "equals", double[].class, double[].class);
+    }
+
+    private static void registerArrayPlugins(InvocationPlugins plugins) {
+        Registration r = new Registration(plugins, Array.class);
+        r.registerMethodSubstitution(ArraySubstitutions.class, "newInstance", Class.class, int.class);
+        r.registerMethodSubstitution(ArraySubstitutions.class, "getLength", Object.class);
+    }
+
+    private static void registerUnsafePlugins(InvocationPlugins plugins) {
         Registration r = new Registration(plugins, Unsafe.class);
         for (Kind kind : Kind.values()) {
             if ((kind.isPrimitive() && kind != Kind.Void) || kind == Kind.Object) {
@@ -119,39 +167,9 @@
                     return true;
                 }
             });
-
-            if (getAndSetEnabled(arch)) {
-                r.register4("getAndSet" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() {
-                    public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode value) {
-                        // Emits a null-check for the otherwise unused receiver
-                        unsafe.get();
-                        b.addPush(kind.getStackKind(), new AtomicReadAndWriteNode(object, offset, value, kind, LocationIdentity.any()));
-                        return true;
-                    }
-                });
-                if (kind != Kind.Object) {
-                    r.register4("getAndAdd" + kind.name(), Receiver.class, Object.class, long.class, javaClass, new InvocationPlugin() {
-                        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode delta) {
-                            // Emits a null-check for the otherwise unused receiver
-                            unsafe.get();
-                            b.addPush(kind.getStackKind(), new AtomicReadAndAddNode(object, offset, delta, LocationIdentity.any()));
-                            return true;
-                        }
-                    });
-                }
-            }
         }
     }
 
-    /**
-     * Determines if the platform includes such for intrinsifying the {@link Unsafe#getAndSetInt}
-     * method family.
-     */
-    public static boolean getAndSetEnabled(Architecture arch) {
-        // FIXME should return whether the current compilation target supports these
-        return arch.getName().equals("AMD64");
-    }
-
     private static void registerIntegerLongPlugins(InvocationPlugins plugins, Kind kind) {
         Class<?> declaringClass = kind.toBoxedJavaClass();
         Class<?> type = kind.toJavaClass();
@@ -242,7 +260,7 @@
         });
     }
 
-    private static void registerMathPlugins(Architecture arch, InvocationPlugins plugins) {
+    private static void registerMathPlugins(InvocationPlugins plugins) {
         Registration r = new Registration(plugins, Math.class);
         for (Kind kind : new Kind[]{Kind.Int, Kind.Long}) {
             Class<?> type = kind.toJavaClass();
@@ -283,31 +301,6 @@
                 return true;
             }
         });
-        r.register2("pow", Double.TYPE, Double.TYPE, new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
-                ValueNode folded = MathPowNode.tryFold(x, y);
-                if (folded != null) {
-                    b.addPush(Kind.Double, folded);
-                } else {
-                    b.addPush(Kind.Double, new MathPowNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), x, y));
-                }
-                return true;
-            }
-        });
-        if (getAndSetEnabled(arch)) {
-            r.register1("log", Double.TYPE, new InvocationPlugin() {
-                public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
-                    b.push(Kind.Double, b.recursiveAppend(MathIntrinsicNode.create(value, LOG)));
-                    return true;
-                }
-            });
-            r.register1("log10", Double.TYPE, new InvocationPlugin() {
-                public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
-                    b.push(Kind.Double, b.recursiveAppend(MathIntrinsicNode.create(value, LOG10)));
-                    return true;
-                }
-            });
-        }
     }
 
     public static class UnsignedMathPlugin implements InvocationPlugin {
@@ -645,7 +638,7 @@
         String[] names = {"org.openjdk.jmh.infra.Blackhole", "org.openjdk.jmh.logic.BlackHole"};
         for (String name : names) {
             Class<?> blackholeClass;
-            blackholeClass = ReplacementsImpl.resolveClass(name, true);
+            blackholeClass = MethodSubstitutionPlugin.resolveClass(name, true);
             if (blackholeClass != null) {
                 Registration r = new Registration(plugins, blackholeClass);
                 for (Kind kind : Kind.values()) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java	Thu Apr 09 17:04:05 2015 +0200
@@ -22,12 +22,8 @@
  */
 package com.oracle.graal.replacements;
 
-import static com.oracle.graal.compiler.common.UnsafeAccess.*;
-
-import java.lang.reflect.*;
-
-import com.oracle.graal.api.replacements.*;
-import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.replacements.nodes.*;
 
 import edu.umd.cs.findbugs.annotations.*;
@@ -35,24 +31,8 @@
 /**
  * Substitutions for {@link java.lang.String} methods.
  */
-@ClassSubstitution(value = java.lang.String.class)
 public class StringSubstitutions {
 
-    /**
-     * Offset of the {@link String#value} field.
-     */
-    @java.lang.SuppressWarnings("javadoc") private static final long valueOffset;
-
-    static {
-        try {
-            Field valueField = String.class.getDeclaredField("value");
-            valueOffset = unsafe.objectFieldOffset(valueField);
-        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException e) {
-            throw new GraalInternalError(e);
-        }
-    }
-
-    @MethodSubstitution(isStatic = false)
     @SuppressFBWarnings(value = "ES_COMPARING_PARAMETER_STRING_WITH_EQ", justification = "reference equality on the receiver is what we want")
     public static boolean equals(final String thisString, Object obj) {
         if (thisString == obj) {
@@ -69,9 +49,14 @@
             return true;
         }
 
-        final char[] array1 = (char[]) unsafe.getObject(thisString, valueOffset);
-        final char[] array2 = (char[]) unsafe.getObject(thatString, valueOffset);
+        final char[] array1 = getValue(thisString);
+        final char[] array2 = getValue(thatString);
 
         return ArrayEqualsNode.equals(array1, array2, array1.length);
     }
+
+    /**
+     * Will be intrinsified with an {@link InvocationPlugin} to a {@link LoadFieldNode}.
+     */
+    private static native char[] getValue(String s);
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java	Thu Apr 09 17:04:05 2015 +0200
@@ -170,6 +170,10 @@
             InliningUtil.inline(invoke, replacementGraph, false, null);
             Debug.dump(graph(), "After inlining replacement %s", replacementGraph);
         } else {
+            if (invoke.bci() < 0) {
+                throw new GraalInternalError("%s: cannot lower to invoke with invalid BCI: %s", graph(), this);
+            }
+
             if (invoke.stateAfter() == null) {
                 ResolvedJavaMethod method = graph().method();
                 if (method.getAnnotation(MethodSubstitution.class) != null || method.getAnnotation(Snippet.class) != null) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.replacements.nodes;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.compiler.common.*;
-import com.oracle.graal.compiler.common.type.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.lir.gen.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.calc.*;
-import com.oracle.graal.nodes.spi.*;
-
-@NodeInfo
-public final class MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable {
-
-    public static final NodeClass<MathIntrinsicNode> TYPE = NodeClass.create(MathIntrinsicNode.class);
-    protected final Operation operation;
-
-    public enum Operation {
-        LOG,
-        LOG10,
-        SIN,
-        COS,
-        TAN
-    }
-
-    public Operation operation() {
-        return operation;
-    }
-
-    public static ValueNode create(ValueNode value, Operation op) {
-        ValueNode c = tryConstantFold(value, op);
-        if (c != null) {
-            return c;
-        }
-        return new MathIntrinsicNode(value, op);
-    }
-
-    protected static ValueNode tryConstantFold(ValueNode value, Operation op) {
-        if (value.isConstant()) {
-            double ret = doCompute(value.asJavaConstant().asDouble(), op);
-            return ConstantNode.forDouble(ret);
-        }
-        return null;
-    }
-
-    protected MathIntrinsicNode(ValueNode value, Operation op) {
-        super(TYPE, StampFactory.forKind(Kind.Double), value);
-        assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64;
-        this.operation = op;
-    }
-
-    @Override
-    public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) {
-        Value input = builder.operand(getValue());
-        Value result;
-        switch (operation()) {
-            case LOG:
-                result = gen.emitMathLog(input, false);
-                break;
-            case LOG10:
-                result = gen.emitMathLog(input, true);
-                break;
-            case SIN:
-                result = gen.emitMathSin(input);
-                break;
-            case COS:
-                result = gen.emitMathCos(input);
-                break;
-            case TAN:
-                result = gen.emitMathTan(input);
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-        builder.setResult(this, result);
-    }
-
-    @Override
-    public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
-        ValueNode c = tryConstantFold(forValue, operation());
-        if (c != null) {
-            return c;
-        }
-        return this;
-    }
-
-    @NodeIntrinsic
-    public static native double compute(double value, @ConstantNodeParameter Operation op);
-
-    private static double doCompute(double value, Operation op) {
-        switch (op) {
-            case LOG:
-                return Math.log(value);
-            case LOG10:
-                return Math.log10(value);
-            case SIN:
-                return Math.sin(value);
-            case COS:
-                return Math.cos(value);
-            case TAN:
-                return Math.tan(value);
-            default:
-                throw new GraalInternalError("unknown op %s", op);
-        }
-    }
-}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java	Thu Apr 09 16:13:32 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.replacements.nodes;
-
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.spi.*;
-import com.oracle.graal.nodeinfo.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.CallTargetNode.InvokeKind;
-
-@NodeInfo
-public final class MathPowNode extends MacroStateSplitNode implements Canonicalizable.Binary<ValueNode> {
-
-    public static final NodeClass<MathPowNode> TYPE = NodeClass.create(MathPowNode.class);
-
-    public MathPowNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode x, ValueNode y) {
-        super(TYPE, invokeKind, targetMethod, bci, returnType, x, y);
-    }
-
-    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
-        ValueNode folded = tryFold(forX, forY);
-        return folded != null ? folded : this;
-    }
-
-    public static ValueNode tryFold(ValueNode x, ValueNode y) {
-        if (x.isConstant() && y.isConstant()) {
-            double xPrim = x.asJavaConstant().asDouble();
-            double yPrim = y.asJavaConstant().asDouble();
-            return ConstantNode.forDouble(Math.pow(xPrim, yPrim));
-        }
-        return null;
-    }
-
-    public ValueNode getX() {
-        return arguments.get(0);
-    }
-
-    public ValueNode getY() {
-        return arguments.get(1);
-    }
-}
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java	Thu Apr 09 17:04:05 2015 +0200
@@ -25,7 +25,6 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graphbuilderconf.*;
 import com.oracle.graal.java.*;
@@ -46,8 +45,8 @@
     private final AllowAssumptions allowAssumptions;
     private final Map<ResolvedJavaMethod, EncodedGraph> graphCache;
 
-    public CachingPEGraphDecoder(Providers providers, SnippetReflectionProvider snippetReflection, GraphBuilderConfiguration graphBuilderConfig, AllowAssumptions allowAssumptions) {
-        super(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider(), snippetReflection);
+    public CachingPEGraphDecoder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, AllowAssumptions allowAssumptions) {
+        super(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider());
 
         this.providers = providers;
         this.graphBuilderConfig = graphBuilderConfig;
@@ -59,8 +58,7 @@
         StructuredGraph graph = new StructuredGraph(method, allowAssumptions);
         try (Debug.Scope scope = Debug.scope("createGraph", graph)) {
 
-            new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), snippetReflection, providers.getConstantReflection(), graphBuilderConfig,
-                            TruffleCompilerImpl.Optimizations, null).apply(graph);
+            new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), graphBuilderConfig, TruffleCompilerImpl.Optimizations, null).apply(graph);
 
             PhaseContext context = new PhaseContext(providers);
             new CanonicalizerPhase().apply(graph, context);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java	Thu Apr 09 17:04:05 2015 +0200
@@ -29,7 +29,6 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.graph.spi.*;
@@ -62,7 +61,6 @@
     protected final MetaAccessProvider metaAccess;
     protected final ConstantReflectionProvider constantReflection;
     protected final StampProvider stampProvider;
-    protected final SnippetReflectionProvider snippetReflection;
 
     protected class PEMethodScope extends MethodScope {
         protected final ResolvedJavaMethod method;
@@ -143,11 +141,6 @@
         }
 
         @Override
-        public SnippetReflectionProvider getSnippetReflection() {
-            return snippetReflection;
-        }
-
-        @Override
         public StructuredGraph getGraph() {
             return methodScope.graph;
         }
@@ -183,6 +176,11 @@
         }
 
         @Override
+        public void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args) {
+            throw unimplemented();
+        }
+
+        @Override
         public FrameState createStateAfter() {
             throw unimplemented();
         }
@@ -276,11 +274,10 @@
         }
     }
 
-    public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, SnippetReflectionProvider snippetReflection) {
+    public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider) {
         this.metaAccess = metaAccess;
         this.constantReflection = constantReflection;
         this.stampProvider = stampProvider;
-        this.snippetReflection = snippetReflection;
     }
 
     protected static LoopExplosionKind loopExplosionKind(ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin) {
@@ -377,7 +374,7 @@
 
         PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, invoke, invokePredecessor);
         InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext);
-        if (InvocationPlugin.execute(graphBuilderContext, targetMethod, invocationPlugin, invocationPluginReceiver.init(targetMethod, arguments), arguments)) {
+        if (invocationPlugin.execute(graphBuilderContext, targetMethod, invocationPluginReceiver.init(targetMethod, arguments), arguments)) {
 
             if (graphBuilderContext.lastInstr != null) {
                 registerNode(loopScope, invokeOrderId, graphBuilderContext.pushedNode, true, true);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Apr 09 17:04:05 2015 +0200
@@ -181,7 +181,7 @@
             this.loopExplosionPlugin = loopExplosionPlugin;
         }
 
-        private boolean hasMethodHandleArgument(GraphBuilderContext builder, ValueNode[] arguments) {
+        private boolean hasMethodHandleArgument(ValueNode[] arguments) {
             /*
              * We want to process invokes that have a constant MethodHandle parameter. And the
              * method must be statically bound, otherwise we do not have a single target method.
@@ -189,7 +189,7 @@
             for (ValueNode argument : arguments) {
                 if (argument.isConstant()) {
                     JavaConstant constant = argument.asJavaConstant();
-                    if (constant.getKind() == Kind.Object && builder.getSnippetReflection().asObject(MethodHandle.class, constant) != null) {
+                    if (constant.getKind() == Kind.Object && snippetReflection.asObject(MethodHandle.class, constant) != null) {
                         return true;
                     }
                 }
@@ -219,7 +219,7 @@
                         GraalInternalError.shouldNotReachHere("The direct call node does not resolve to a constant!");
                     }
 
-                    Object callNode = builder.getSnippetReflection().asObject(Object.class, (JavaConstant) arg1.asConstant());
+                    Object callNode = snippetReflection.asObject(Object.class, (JavaConstant) arg1.asConstant());
                     if (callNode instanceof OptimizedDirectCallNode) {
                         OptimizedDirectCallNode directCallNode = (OptimizedDirectCallNode) callNode;
                         lastDirectCallNode = directCallNode;
@@ -239,7 +239,7 @@
             }
 
             if (duringParsing && (!original.hasBytecodes() || original.getCode().length >= TrivialInliningSize.getValue() || builder.getDepth() >= InlineDuringParsingMaxDepth.getValue()) &&
-                            !hasMethodHandleArgument(builder, arguments)) {
+                            !hasMethodHandleArgument(arguments)) {
                 return null;
             }
             return new InlineInfo(original, false, false);
@@ -271,7 +271,7 @@
     protected void doFastPE(OptimizedCallTarget callTarget, StructuredGraph graph) {
         GraphBuilderConfiguration newConfig = configForRoot.copy();
         InvocationPlugins invocationPlugins = newConfig.getPlugins().getInvocationPlugins();
-        TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), invocationPlugins, false);
+        TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), invocationPlugins, false, snippetReflection);
 
         newConfig.setUseProfiling(false);
         Plugins plugins = newConfig.getPlugins();
@@ -285,8 +285,7 @@
         }
         plugins.setInlineInvokePlugin(inlinePlugin);
         plugins.setLoopExplosionPlugin(new PELoopExplosionPlugin());
-        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), this.snippetReflection, providers.getConstantReflection(), newConfig,
-                        TruffleCompilerImpl.Optimizations, null).apply(graph);
+        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), newConfig, TruffleCompilerImpl.Optimizations, null).apply(graph);
         if (PrintTruffleExpansionHistogram.getValue()) {
             ((HistogramInlineInvokePlugin) inlinePlugin).print(callTarget, System.out);
         }
@@ -295,7 +294,7 @@
     protected void doGraphPE(OptimizedCallTarget callTarget, StructuredGraph graph) {
         GraphBuilderConfiguration newConfig = configForRoot.copy();
         InvocationPlugins parsingInvocationPlugins = newConfig.getPlugins().getInvocationPlugins();
-        TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), parsingInvocationPlugins, true);
+        TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), parsingInvocationPlugins, true, snippetReflection);
 
         callTarget.setInlining(new TruffleInlining(callTarget, new DefaultInliningPolicy()));
 
@@ -306,12 +305,12 @@
         plugins.setLoadFieldPlugin(new InterceptLoadFieldPlugin());
         plugins.setInlineInvokePlugin(new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements(), true, parsingInvocationPlugins, loopExplosionPlugin));
 
-        CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(providers, snippetReflection, newConfig, AllowAssumptions.from(graph.getAssumptions() != null));
+        CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(providers, newConfig, AllowAssumptions.from(graph.getAssumptions() != null));
 
         ParameterPlugin parameterPlugin = new InterceptReceiverPlugin(callTarget);
 
         InvocationPlugins decodingInvocationPlugins = new InvocationPlugins(providers.getMetaAccess());
-        TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), decodingInvocationPlugins, false);
+        TruffleGraphBuilderPlugins.registerInvocationPlugins(providers.getMetaAccess(), decodingInvocationPlugins, false, snippetReflection);
         InlineInvokePlugin decodingInlinePlugin = new PEInlineInvokePlugin(callTarget.getInlining(), providers.getReplacements(), false, decodingInvocationPlugins, loopExplosionPlugin);
         if (PrintTruffleExpansionHistogram.getValue()) {
             decodingInlinePlugin = new HistogramInlineInvokePlugin(graph, decodingInlinePlugin);
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java	Thu Apr 09 17:04:05 2015 +0200
@@ -76,7 +76,7 @@
         StringIndexOutOfBoundsException.class,
         ClassCastException.class
     };
-    // @formatter:off
+    // @formatter:on
 
     public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability,
                     OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints);
@@ -97,7 +97,6 @@
         GraphBuilderPhase phase = (GraphBuilderPhase) backend.getSuites().getDefaultGraphBuilderSuite().findPhase(GraphBuilderPhase.class).previous();
         InvocationPlugins invocationPlugins = new InvocationPlugins(phase.getGraphBuilderConfig().getPlugins().getInvocationPlugins());
         Plugins plugins = new Plugins(invocationPlugins);
-
         this.config = GraphBuilderConfiguration.getDefault(plugins).withSkippedExceptionTypes(skippedExceptionTypes);
 
         this.partialEvaluator = new PartialEvaluator(providers, config, Graal.getRequiredCapability(SnippetReflectionProvider.class));
@@ -161,8 +160,8 @@
             CodeCacheProvider codeCache = providers.getCodeCache();
             CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false);
             CompilationResult compilationResult = new CompilationResult(name);
-            result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), graphBuilderSuite, Optimizations, getProfilingInfo(graph), speculationLog, suites,
-                            lirSuites, compilationResult, CompilationResultBuilderFactory.Default);
+            result = compileGraph(graph, cc, graph.method(), providers, backend, codeCache.getTarget(), graphBuilderSuite, Optimizations, getProfilingInfo(graph), speculationLog, suites, lirSuites,
+                            compilationResult, CompilationResultBuilderFactory.Default);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Thu Apr 09 16:13:32 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java	Thu Apr 09 17:04:05 2015 +0200
@@ -27,6 +27,7 @@
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.*;
@@ -49,9 +50,9 @@
  * Provides {@link InvocationPlugin}s for Truffle classes.
  */
 public class TruffleGraphBuilderPlugins {
-    public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins, boolean canDelayIntrinsification) {
+    public static void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins, boolean canDelayIntrinsification, SnippetReflectionProvider snippetReflection) {
 
-        registerOptimizedAssumptionPlugins(plugins, canDelayIntrinsification);
+        registerOptimizedAssumptionPlugins(plugins, canDelayIntrinsification, snippetReflection);
         registerExactMathPlugins(plugins);
         registerCompilerDirectivesPlugins(plugins);
         registerCompilerAssertsPlugins(plugins, canDelayIntrinsification);
@@ -66,13 +67,13 @@
 
     }
 
-    public static void registerOptimizedAssumptionPlugins(InvocationPlugins plugins, boolean canDelayIntrinsification) {
+    public static void registerOptimizedAssumptionPlugins(InvocationPlugins plugins, boolean canDelayIntrinsification, SnippetReflectionProvider snippetReflection) {
         Registration r = new Registration(plugins, OptimizedAssumption.class);
         InvocationPlugin plugin = new InvocationPlugin() {
             public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
                 if (receiver.isConstant()) {
                     Constant constant = receiver.get().asConstant();
-                    OptimizedAssumption assumption = b.getSnippetReflection().asObject(OptimizedAssumption.class, (JavaConstant) constant);
+                    OptimizedAssumption assumption = snippetReflection.asObject(OptimizedAssumption.class, (JavaConstant) constant);
                     if (assumption.isValid()) {
                         if (targetMethod.getName().equals("isValid")) {
                             b.addPush(ConstantNode.forBoolean(true));
--- a/mx/suite.py	Thu Apr 09 16:13:32 2015 +0200
+++ b/mx/suite.py	Thu Apr 09 17:04:05 2015 +0200
@@ -389,7 +389,10 @@
     "com.oracle.graal.hotspot.sparc" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
-      "dependencies" : ["com.oracle.graal.compiler.sparc"],
+      "dependencies" : [
+        "com.oracle.graal.compiler.sparc",
+        "com.oracle.graal.replacements.sparc",
+      ],
       "checkstyle" : "com.oracle.graal.graph",
       "annotationProcessors" : ["com.oracle.graal.service.processor"],
       "javaCompliance" : "1.8",
@@ -594,7 +597,7 @@
       "sourceDirs" : ["src"],
       "dependencies" : [
           "com.oracle.graal.replacements",
-          "com.oracle.graal.amd64",
+          "com.oracle.graal.lir.amd64",
           ],
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
@@ -602,6 +605,17 @@
       "workingSets" : "Graal,Replacements,AMD64",
     },
 
+    "com.oracle.graal.replacements.sparc" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+          "com.oracle.graal.replacements",
+          ],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal,Replacements,SPARC",
+    },
+
     "com.oracle.graal.replacements.test" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],