# HG changeset patch # User Doug Simon # Date 1428591845 -7200 # Node ID d2ce468854b4302d0779f936ec62a240f51a0a23 # Parent 891e3e7024b81a77bfde03c7f902970ee2935a5f# Parent 220ecaa0cc9b403fd79295cffd850ab9a8b58b36 Merge. diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- 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)); diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- 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)); diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- 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; } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTestSubstitutions.java --- 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(); - } -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- 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; } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ForeignCallPlugin.java --- /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; + } +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java --- 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. */ diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java --- 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); } } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java --- 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("")) { - 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()) { diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java --- /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()); + } +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- 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) { diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- 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) { diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java --- 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; diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- 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; diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java --- 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); + } + } + } } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- 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()); diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java --- 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 diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AESCryptSubstitutions.java --- 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); } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java --- 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()); diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java --- 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); } } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/IdentityHashCodeNode.java --- /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 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()); + } +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java --- 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 = "", isStatic = false, forced = true) - public static void init(Object thisObj) { - RegisterFinalizerNode.register(thisObj); - } } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java --- 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 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()); - } -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- 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. */ diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/lang/Object_hashCode02.java --- /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); + } +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArithmeticLIRGenerator.java --- /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); +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java --- 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(); } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java --- 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); } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BreakpointNode.java --- 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 TYPE = NodeClass.create(BreakpointNode.class); @Input NodeInputList arguments; - public BreakpointNode(ValueNode[] arguments) { + public BreakpointNode(ValueNode... arguments) { super(TYPE, StampFactory.forVoid()); this.arguments = new NodeInputList<>(this, arguments); } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java --- 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) { diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java --- 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) { diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java --- /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; + } + }); + } + } + } +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Guards.java --- 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); - } - } -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64IntegerSubstitutions.java --- 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); - } -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64LongSubstitutions.java --- 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); - } -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathIntrinsicNode.java --- /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 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); + } + } +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java --- /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); +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java --- 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); - } - } - -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements.sparc/src/com/oracle/graal/replacements/sparc/SPARCGraphBuilderPlugins.java --- /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)); + } +} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java --- 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); diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraysSubstitutions.java --- 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; diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- 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); - } - } -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java --- 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)")); + } } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/LongSubstitutions.java --- 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; diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java --- 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); -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- 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); } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- 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()) { diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java --- 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); } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- 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) { diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- 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 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); - } - } -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java --- 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 { - - public static final NodeClass 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); - } -} diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CachingPEGraphDecoder.java --- 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 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); diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PEGraphDecoder.java --- 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); diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- 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); diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- 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); } diff -r 220ecaa0cc9b -r d2ce468854b4 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java --- 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)); diff -r 220ecaa0cc9b -r d2ce468854b4 mx/suite.py --- 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"],