# HG changeset patch # User Doug Simon # Date 1428420746 -7200 # Node ID a2cd0e7072e22c0835b9a5286d623c7fb35866a6 # Parent e807c6f675dec47152e66f8196fd5cf1bb5adb8b added MethodSubstitutionPlugin as (eventual) replacement for @MethodSubstitution mechanism diff -r e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java Tue Apr 07 17:32:26 2015 +0200 @@ -168,6 +168,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(); diff -r e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Tue Apr 07 17:32:26 2015 +0200 @@ -97,10 +97,6 @@ return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4, arg5); } - default ResolvedJavaMethod getSubstitute() { - return null; - } - /** * Executes this plugin against a set of invocation arguments. * diff -r e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Tue Apr 07 17:32:26 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 { @@ -404,6 +416,11 @@ } public static boolean check(InvocationPlugins plugins, MethodInfo method, InvocationPlugin plugin) { + if (plugin instanceof MethodSubstitutionPlugin) { + MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin; + msplugin.getJavaSubstitute(); + return true; + } InvocationPlugins p = plugins; while (p != null) { assert !p.registrations.contains(method) : "a plugin is already registered for " + method; diff -r e807c6f675de -r a2cd0e7072e2 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 Tue Apr 07 17:32:26 2015 +0200 @@ -0,0 +1,119 @@ +/* + * 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 sun.misc.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +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 class MethodSubstitutionPlugin implements InvocationPlugin { + + private ResolvedJavaMethod cachedSubstitute; + private final Class declaringClass; + private final String name; + private final Class[] parameters; + + /** + * 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; + } + + /** + * Gets the substitute method, resolving it first if necessary. + */ + public ResolvedJavaMethod getSubstitute(MetaAccessProvider metaAccess) { + if (cachedSubstitute == null) { + cachedSubstitute = metaAccess.lookupJavaMethod(getJavaSubstitute()); + assert cachedSubstitute.getAnnotation(MethodSubstitution.class) != null; + } + return cachedSubstitute; + } + + /** + * Gets the reflection API version of the substitution method. + */ + Method getJavaSubstitute() throws GraalInternalError { + try { + Method substituteMethod = declaringClass.getDeclaredMethod(name, parameters); + 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; + } catch (NoSuchMethodException e) { + throw new GraalInternalError(e); + } + } + + /** + * 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()); + b.intrinsify(targetMethod, subst, argsIncludingReceiver); + return true; + } +} diff -r e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Tue Apr 07 17:32:26 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; @@ -80,7 +81,9 @@ 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); + Plugins plugins = HotSpotGraphBuilderPlugins.create(runtime.getConfig(), wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements, target.arch); + SPARCGraphBuilderPlugins.register(plugins); + return plugins; } protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntimeProvider runtime, Plugins plugins) { diff -r e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Tue Apr 07 17:32:26 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 e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Apr 07 17:32:26 2015 +0200 @@ -1265,14 +1265,18 @@ } 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 +1312,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); diff -r e807c6f675de -r a2cd0e7072e2 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Tue Apr 07 17:32:26 2015 +0200 @@ -71,6 +71,9 @@ * modification. */ private static StructuredGraph getOriginalGraph(final ResolvedJavaMethod method, final HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) { + if (method.getName().equals("hashCode")) { + System.console(); + } StructuredGraph result = InliningUtil.getIntrinsicGraph(context.getReplacements(), method); if (result != null) { return result; diff -r e807c6f675de -r a2cd0e7072e2 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java Tue Apr 07 17:32:26 2015 +0200 @@ -29,16 +29,17 @@ import com.oracle.graal.graphbuilderconf.InvocationPlugins.Receiver; import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.*; +import com.oracle.graal.replacements.*; public class AMD64GraphBuilderPlugins { public static void register(Plugins plugins, AMD64 arch) { InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); - registerIntegerLongPlugins(invocationPlugins, Kind.Int, arch); - registerIntegerLongPlugins(invocationPlugins, Kind.Long, arch); + registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, Kind.Int, arch); + registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, Kind.Long, arch); } - private static void registerIntegerLongPlugins(InvocationPlugins plugins, Kind kind, AMD64 arch) { + 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); @@ -54,6 +55,8 @@ return true; } }); + } else { + r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type); } if (arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction)) { r.register1("numberOfTrailingZeros", type, new InvocationPlugin() { @@ -67,6 +70,8 @@ return true; } }); + } else { + r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type); } } diff -r e807c6f675de -r a2cd0e7072e2 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 Tue Apr 07 17:32:26 2015 +0200 @@ -0,0 +1,46 @@ +/* + * 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 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) { + InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); + registerIntegerLongPlugins(invocationPlugins, IntegerSubstitutions.class, Kind.Int); + registerIntegerLongPlugins(invocationPlugins, LongSubstitutions.class, Kind.Long); + } + + 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); + } +} diff -r e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java Tue Apr 07 17:32:26 2015 +0200 @@ -207,4 +207,8 @@ } return null; } + + public void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args) { + throw GraalInternalError.shouldNotReachHere(); + } } diff -r e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue Apr 07 17:32:26 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) { + if (plugin instanceof MethodSubstitutionPlugin) { + MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin; + substitute = msplugin.getSubstitute(providers.getMetaAccess()); + } else if (plugin != null) { StructuredGraph graph = new IntrinsicGraphBuilder(providers, snippetReflection, 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; } diff -r e807c6f675de -r a2cd0e7072e2 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 Mon Apr 06 13:14:01 2015 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Tue Apr 07 17:32:26 2015 +0200 @@ -645,7 +645,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 e807c6f675de -r a2cd0e7072e2 mx/suite.py --- a/mx/suite.py Mon Apr 06 13:14:01 2015 +0200 +++ b/mx/suite.py Tue Apr 07 17:32:26 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", @@ -602,6 +605,18 @@ "workingSets" : "Graal,Replacements,AMD64", }, + "com.oracle.graal.replacements.sparc" : { + "subDir" : "graal", + "sourceDirs" : ["src"], + "dependencies" : [ + "com.oracle.graal.replacements", + "com.oracle.graal.sparc", + ], + "checkstyle" : "com.oracle.graal.graph", + "javaCompliance" : "1.8", + "workingSets" : "Graal,Replacements,SPARC", + }, + "com.oracle.graal.replacements.test" : { "subDir" : "graal", "sourceDirs" : ["src"],