# HG changeset patch # User Doug Simon # Date 1422994953 -3600 # Node ID 81be933b83ebabf53e745eae3c43f2eacd57566c # Parent ccabd82be35cc79a6dcb2f752127527227c4a1d5 use anonymous classes for GraphBuilderPlugins instead of enums to common out registration logic and add better static checking diff -r ccabd82be35c -r 81be933b83eb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java Tue Feb 03 18:30:07 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java Tue Feb 03 21:22:33 2015 +0100 @@ -25,6 +25,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugins.Registration; +import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; @@ -35,17 +38,9 @@ @ServiceProvider(GraphBuilderPluginsProvider.class) public class HotSpotGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - plugins.register(metaAccess, ObjectPlugin.class); - } - - /** - * HotSpot specific plugins for {@link Object}. - */ - enum ObjectPlugin implements GraphBuilderPlugin { - getClass() { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - assert args.length == 1; - ValueNode rcvr = args[0]; + Registration r = new Registration(plugins, metaAccess, Object.class); + r.register1("getClass", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { GuardingPiNode pi = builder.append(new GuardingPiNode(rcvr)); StampProvider stampProvider = builder.getStampProvider(); LoadHubNode hub = builder.append(new LoadHubNode(stampProvider, pi)); @@ -53,10 +48,6 @@ builder.push(Kind.Object, mirror); return true; } - }; - - public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) { - return GraphBuilderPlugin.resolveTarget(metaAccess, Object.class, name()); - } + }); } } diff -r ccabd82be35c -r 81be933b83eb graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPlugins.java Tue Feb 03 21:22:33 2015 +0100 @@ -0,0 +1,62 @@ +/* + * 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.java; + +import java.util.*; +import java.util.stream.*; + +import com.oracle.graal.api.meta.*; + +/** + * Default implementation of {@link GraphBuilderPlugins} that uses a map. + */ +public class DefaultGraphBuilderPlugins implements GraphBuilderPlugins { + + private final Map plugins = new HashMap<>(); + + /** + * Registers an invocation plugin for a given method. There must be no plugin currently + * registered for {@code method}. + */ + public void register(ResolvedJavaMethod method, InvocationPlugin plugin) { + assert InvocationPluginChecker.check(method, plugin); + GraphBuilderPlugin oldValue = plugins.put(method, plugin); + // System.out.println("registered: " + plugin); + assert oldValue == null; + } + + /** + * Gets the plugin for a given method. + * + * @param method the method to lookup + * @return the plugin associated with {@code method} or {@code null} if none exists + */ + public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { + return plugins.get(method); + } + + @Override + public String toString() { + return plugins.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")); + } +} diff -r ccabd82be35c -r 81be933b83eb graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPluginsProvider.java Tue Feb 03 18:30:07 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * 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.java; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; - -/** - * Provider of non-runtime specific {@link GraphBuilderPlugin}s. - */ -@ServiceProvider(GraphBuilderPluginsProvider.class) -public class DefaultGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { - public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - plugins.register(metaAccess, ObjectPlugin.class); - plugins.register(metaAccess, BoxingPlugin.class); - } - - /** - * Plugins for {@link Object}. - */ - enum ObjectPlugin implements GraphBuilderPlugin { - init() { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - ValueNode object = args[0]; - if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { - builder.append(new RegisterFinalizerNode(object)); - } - return true; - } - - public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) { - return GraphBuilderPlugin.resolveTarget(metaAccess, Object.class, ""); - } - }; - - @Override - public String toString() { - return Object.class.getName() + "." + name() + "()"; - } - } - - /** - * Plugins for the standard primitive box classes (e.g., {@link Integer} and friends). - */ - enum BoxingPlugin implements GraphBuilderPlugin { - valueOf$Boolean(Kind.Boolean), - booleanValue$Boolean(Kind.Boolean), - valueOf$Byte(Kind.Byte), - byteValue$Byte(Kind.Byte), - valueOf$Short(Kind.Short), - shortValue$Short(Kind.Short), - valueOf$Char(Kind.Char), - charValue$Char(Kind.Char), - valueOf$Int(Kind.Int), - intValue$Int(Kind.Int), - valueOf$Long(Kind.Long), - longValue$Long(Kind.Long), - valueOf$Float(Kind.Float), - floatValue$Float(Kind.Float), - valueOf$Double(Kind.Double), - doubleValue$Double(Kind.Double); - - BoxingPlugin(Kind kind) { - assert name().startsWith("valueOf$") || name().startsWith(kind.getJavaName() + "Value$"); - this.kind = kind; - this.box = name().charAt(0) == 'v'; - } - - private final Kind kind; - private final boolean box; - - public final boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - if (box) { - ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); - builder.push(Kind.Object, builder.append(new BoxNode(args[0], resultType, kind))); - } else { - builder.push(kind, builder.append(new UnboxNode(args[0], kind))); - } - return true; - } - - public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) { - Class[] parameterTypes = box ? new Class[]{kind.toJavaClass()} : new Class[0]; - return GraphBuilderPlugin.resolveTarget(metaAccess, kind.toBoxedJavaClass(), name(), parameterTypes); - } - } -} diff -r ccabd82be35c -r 81be933b83eb 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 Tue Feb 03 18:30:07 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Feb 03 21:22:33 2015 +0100 @@ -42,6 +42,7 @@ import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.java.BciBlockMapping.LocalLiveness; +import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; @@ -63,7 +64,7 @@ public GraphBuilderPhase(GraphBuilderConfiguration config) { this.graphBuilderConfig = config; - this.graphBuilderPlugins = new GraphBuilderPlugins(); + this.graphBuilderPlugins = new DefaultGraphBuilderPlugins(); } @Override @@ -773,11 +774,22 @@ if (GraalOptions.InlineDuringParsing.getValue() && invokeKind.isDirect()) { if (graphBuilderPlugins != null) { - GraphBuilderPlugin plugin = graphBuilderPlugins.getPlugin(targetMethod); + InvocationPlugin plugin = graphBuilderPlugins.lookupInvocation(targetMethod); if (plugin != null) { int beforeStackSize = frameState.stackSize; - if (plugin.handleInvocation(this, args)) { - // System.out.println("used plugin: " + plugin); + boolean handled; + if (args.length == 0) { + handled = plugin.apply(this); + } else if (args.length == 1) { + handled = plugin.apply(this, args[0]); + } else if (args.length == 2) { + handled = plugin.apply(this, args[0], args[1]); + } else if (args.length == 3) { + handled = plugin.apply(this, args[0], args[1], args[2]); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + if (handled) { assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize; return; } diff -r ccabd82be35c -r 81be933b83eb graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Tue Feb 03 18:30:07 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java Tue Feb 03 21:22:33 2015 +0100 @@ -22,43 +22,14 @@ */ package com.oracle.graal.java; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.nodes.*; - /** - * Extensions for handling certain bytecode instructions while building a - * {@linkplain StructuredGraph graph} from a bytecode stream. + * Marker interface for graph builder plugins. + * + * Concrete plugins implement one of the sub-interfaces of this interface. + * + * @see GraphBuilderPluginsProvider + * @see GraphBuilderPlugins + * @see GraphBuilderPlugins.Registration */ public interface GraphBuilderPlugin { - - /** - * Processes an invocation parsed in a bytecode stream and add nodes to a graph being - * constructed that implement the semantics of the invocation. - * - * @param builder object being used to build a graph - * @param args the arguments to the invocation - */ - boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args); - - /** - * Gets the method handled by {@link #handleInvocation(GraphBuilderContext, ValueNode[])} . - */ - ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess); - - /** - * Looks up a {@link ResolvedJavaMethod}. - * - * @param methodNameBase the name of the method is the prefix of this value up to the first '$' - * character - */ - static ResolvedJavaMethod resolveTarget(MetaAccessProvider metaAccess, Class declaringClass, String methodNameBase, Class... parameterTypes) { - int index = methodNameBase.indexOf('$'); - String methodName = index == -1 ? methodNameBase : methodNameBase.substring(0, index); - try { - return metaAccess.lookupJavaMethod(methodName.equals("") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(methodName, parameterTypes)); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalInternalError(e); - } - } } diff -r ccabd82be35c -r 81be933b83eb graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Tue Feb 03 18:30:07 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Tue Feb 03 21:22:33 2015 +0100 @@ -22,45 +22,202 @@ */ package com.oracle.graal.java; +import static java.lang.String.*; + +import java.lang.reflect.*; import java.util.*; -import java.util.stream.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.nodes.*; /** - * A repository of {@link GraphBuilderPlugin}s. + * Interface for managing a set of graph builder {@link GraphBuilderPlugin}s. */ -public class GraphBuilderPlugins { - - private final Map map = new HashMap<>(); +public interface GraphBuilderPlugins { /** - * Registers all the constants of an enum that implements {@link GraphBuilderPlugin}. + * Plugin for handling a method invocation. */ - public & GraphBuilderPlugin> void register(MetaAccessProvider metaAccess, Class enumClass) { - assert Enum.class.isAssignableFrom(enumClass); - Object[] enumConstants = enumClass.getEnumConstants(); - for (Object o : enumConstants) { - GraphBuilderPlugin gbp = (GraphBuilderPlugin) o; - ResolvedJavaMethod target = gbp.getInvocationTarget(metaAccess); - GraphBuilderPlugin oldValue = map.put(target, gbp); - // System.out.println("registered: " + gbp); - assert oldValue == null; + public interface InvocationPlugin extends GraphBuilderPlugin { + /** + * Tries to handle an invocation to a method with no arguments. + * + * @return {@code true} this plugin handled the invocation + */ + default boolean apply(GraphBuilderContext builder) { + throw invalidHandler(builder); + } + + /** + * Tries to handle an invocation to a method with one argument. + * + * @return {@code true} this plugin handled the invocation + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg) { + throw invalidHandler(builder, arg); + } + + /** + * Tries to handle an invocation to a method with two arguments. + * + * @return {@code true} this plugin handled the invocation + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { + throw invalidHandler(builder, arg1, arg2); + } + + /** + * Tries to handle an invocation to a method with three arguments. + * + * @return {@code true} this plugin handled the invocation + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3) { + throw invalidHandler(builder, arg1, arg2, arg3); + } + + default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext builder, ValueNode... args) { + return new GraalInternalError("Invocation plugin %s does not handle invocations with %d arguments", getClass().getSimpleName(), args.length); } } /** - * Gets the plugin for a given method registered in the object. + * Utility for {@linkplain GraphBuilderPlugins#register(ResolvedJavaMethod, InvocationPlugin) + * registration} of plugins. + */ + public static class Registration { + + /** + * Sentinel class for use with {@link Registration#register1}, + * {@link Registration#register2} or {@link Registration#register3} to denote the receiver + * argument for a non-static method. + */ + public static final class Receiver { + private Receiver() { + throw GraalInternalError.shouldNotReachHere(); + } + } + + private final GraphBuilderPlugins plugins; + private final MetaAccessProvider metaAccess; + private final Class declaringClass; + + /** + * Creates an object for registering plugins for methods declared by a given class. + * + * @param plugins where to register the plugins + * @param metaAccess used to resolve classes and methods + * @param declaringClass the class declaring the methods for which plugins will be + * registered via this object + */ + public Registration(GraphBuilderPlugins plugins, MetaAccessProvider metaAccess, Class declaringClass) { + this.plugins = plugins; + this.metaAccess = metaAccess; + this.declaringClass = declaringClass; + } + + /** + * Registers a plugin for a method with no arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register0(String name, InvocationPlugin plugin) { + plugins.register(resolve(metaAccess, declaringClass, name), plugin); + } + + /** + * Registers a plugin for a method with 1 argument. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register1(String name, Class arg, InvocationPlugin plugin) { + ResolvedJavaMethod method = arg == Receiver.class ? resolve(metaAccess, declaringClass, name) : resolve(metaAccess, declaringClass, name, arg); + plugins.register(method, plugin); + } + + /** + * Registers a plugin for a method with 2 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register2(String name, Class arg1, Class arg2, InvocationPlugin plugin) { + ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2) : resolve(metaAccess, declaringClass, name, arg1, arg2); + plugins.register(method, plugin); + } + + /** + * Registers a plugin for a method with 3 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register3(String name, Class arg1, Class arg2, Class arg3, InvocationPlugin plugin) { + ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3); + plugins.register(method, plugin); + } + + /** + * Resolves a method given a declaring class, name and parameter types. + */ + public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class declaringClass, String name, Class... parameterTypes) { + try { + return metaAccess.lookupJavaMethod(name.equals("") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(name, parameterTypes)); + } catch (NoSuchMethodException | SecurityException e) { + throw new GraalInternalError(e); + } + } + } + + public static class InvocationPluginChecker { + static final Class[] APPLY0 = {GraphBuilderContext.class}; + static final Class[] APPLY1 = {GraphBuilderContext.class, ValueNode.class}; + static final Class[] APPLY2 = {GraphBuilderContext.class, ValueNode.class, ValueNode.class}; + static final Class[] APPLY3 = {GraphBuilderContext.class, ValueNode.class, ValueNode.class, ValueNode.class}; + static final Class[][] SIGS = {APPLY0, APPLY1, APPLY2, APPLY3}; + + public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) { + int arguments = method.getSignature().getParameterCount(!method.isStatic()); + assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method.format("%H.%n(%p)")); + Method expected = null; + for (Method m : plugin.getClass().getDeclaredMethods()) { + if (m.getName().equals("apply")) { + Class[] parameterTypes = m.getParameterTypes(); + assert Arrays.equals(SIGS[arguments], parameterTypes) : format("graph builder plugin for %s has wrong signature%nexpected: (%s)%n actual: (%s)", method.format("%H.%n(%p)"), + sigString(SIGS[arguments]), sigString(m.getParameterTypes())); + expected = m; + } + } + assert expected != null : format("graph builder plugin %s must define exactly one \"apply\" method, none found", plugin); + return true; + } + + protected static String sigString(Class... sig) { + StringBuilder sb = new StringBuilder(); + for (Class t : sig) { + if (sb.length() != 0) { + sb.append(", "); + } + sb.append(t.getSimpleName()); + } + return sb.toString(); + } + + } + + /** + * Registers an {@link InvocationPlugin} for a given method. There must be no plugin currently + * registered for {@code method}. + */ + void register(ResolvedJavaMethod method, InvocationPlugin plugin); + + /** + * Gets the {@link InvocationPlugin} for a given method. * * @param method the method to lookup * @return the plugin associated with {@code method} or {@code null} if none exists */ - public GraphBuilderPlugin getPlugin(ResolvedJavaMethod method) { - return map.get(method); - } - - @Override - public String toString() { - return map.keySet().stream().map(m -> m.format("%H.%n(%p)")).collect(Collectors.joining(", ")); - } + InvocationPlugin lookupInvocation(ResolvedJavaMethod method); } diff -r ccabd82be35c -r 81be933b83eb graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.java Tue Feb 03 18:30:07 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPluginsProvider.java Tue Feb 03 21:22:33 2015 +0100 @@ -30,9 +30,7 @@ */ public interface GraphBuilderPluginsProvider extends Service { /** - * Registers the plugins provided by this object with a plugins registry. - * - * @param plugins registry of plugins + * Registers the plugins provided by this object. */ void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins); } diff -r ccabd82be35c -r 81be933b83eb graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java Tue Feb 03 21:22:33 2015 +0100 @@ -0,0 +1,97 @@ +/* + * 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.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugins.Registration; +import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; + +/** + * Provider of non-runtime specific {@link GraphBuilderPlugin}s. + */ +@ServiceProvider(GraphBuilderPluginsProvider.class) +public class StandardGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { + public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + Registration r = new Registration(plugins, metaAccess, Object.class); + r.register1("", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode object) { + if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) { + builder.append(new RegisterFinalizerNode(object)); + } + return true; + } + }); + + for (Kind kind : Kind.values()) { + if (kind.isPrimitive() && kind != Kind.Void) { + new BoxPlugin(kind).register(metaAccess, plugins); + new UnboxPlugin(kind).register(metaAccess, plugins); + } + } + } + + static class BoxPlugin implements InvocationPlugin { + + private final Kind kind; + + BoxPlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode value) { + ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass()); + builder.push(Kind.Object, builder.append(new BoxNode(value, resultType, kind))); + return true; + } + + void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), "valueOf", kind.toJavaClass()); + plugins.register(method, this); + } + } + + static class UnboxPlugin implements InvocationPlugin { + + private final Kind kind; + + UnboxPlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.push(kind, builder.append(new UnboxNode(value, kind))); + return true; + } + + void register(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + String name = kind.toJavaClass().getSimpleName() + "Value"; + ResolvedJavaMethod method = Registration.resolve(metaAccess, kind.toBoxedJavaClass(), name); + plugins.register(method, this); + } + } +} diff -r ccabd82be35c -r 81be933b83eb graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java Tue Feb 03 18:30:07 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java Tue Feb 03 21:22:33 2015 +0100 @@ -28,6 +28,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugins.Registration; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.truffle.nodes.frame.*; @@ -39,96 +41,69 @@ @ServiceProvider(GraphBuilderPluginsProvider.class) public class TruffleGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - plugins.register(metaAccess, CompilerDirectivesPlugin.class); - } - - /** - * Plugins for {@link CompilerDirectives}. - */ - enum CompilerDirectivesPlugin implements GraphBuilderPlugin { - inInterpreter() { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - builder.append(ConstantNode.forBoolean(false)); + Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class); + r.register0("inInterpreter", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.push(Kind.Boolean, builder.append(ConstantNode.forBoolean(false))); return true; } - }, - inCompiledCode() { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - builder.append(ConstantNode.forBoolean(true)); + }); + r.register0("inCompiledCode", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.push(Kind.Boolean, builder.append(ConstantNode.forBoolean(true))); return true; } - }, - transferToInterpreter() { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + }); + r.register0("transferToInterpreter", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); return true; } - }, - transferToInterpreterAndInvalidate() { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + }); + r.register0("transferToInterpreterAndInvalidate", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); return true; } - }, - interpreterOnly(Runnable.class) { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + }); + r.register1("interpreterOnly", Runnable.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode arg) { return true; } - }, - interpreterOnly$(Callable.class) { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { + }); + r.register1("interpreterOnly", Callable.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode arg) { return true; } - }, - injectBranchProbability(double.class, boolean.class) { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - ValueNode probability = args[0]; - ValueNode condition = args[1]; + }); + r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { builder.append(new BranchProbabilityNode(probability, condition)); return true; } - }, - bailout(String.class) { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - // TODO: is this too eager? Should a BailoutNode be created instead? - ValueNode message = args[0]; + }); + r.register1("bailout", String.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode message) { if (message.isConstant()) { throw new BailoutException(message.asConstant().toValueString()); } throw new BailoutException("bailout (message is not compile-time constant, so no additional information is available)"); } - }, - - isCompilationConstant(Object.class) { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - ValueNode arg0 = args[0]; - if (arg0 instanceof BoxNode) { - arg0 = ((BoxNode) arg0).getValue(); - } - if (arg0.isConstant()) { + }); + r.register1("isCompilationConstant", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + if ((value instanceof BoxNode ? ((BoxNode) value).getValue() : value).isConstant()) { builder.push(Kind.Boolean, builder.append(ConstantNode.forBoolean(true))); return true; } - - // Cannot create MacroNodes in a plugin (yet) return false; } - }, - materialize(Object.class) { - public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) { - builder.append(new ForceMaterializeNode(args[0])); + }); + r.register1("materialize", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.append(new ForceMaterializeNode(value)); return true; } - }; - - CompilerDirectivesPlugin(Class... parameterTypes) { - this.parameterTypes = parameterTypes; - } - - private final Class[] parameterTypes; - - public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) { - return GraphBuilderPlugin.resolveTarget(metaAccess, CompilerDirectives.class, name(), parameterTypes); - } + }); } }