# HG changeset patch # User Doug Simon # Date 1427459348 -3600 # Node ID 8470e81631f8e66445fb763d5b2e03b2a8202721 # Parent c1f116cd4b67bd143d3434609482a970a73688cb converted all @MacroSubstitution uses to InvocationPlugins diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java Fri Mar 27 13:29:08 2015 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -62,6 +63,8 @@ /** * Raw operation for adding a node to the graph when neither {@link #add}, * {@link #addPush(ValueNode)} nor {@link #addPush(Kind, ValueNode)} can be used. + * + * @return either the node added or an equivalent node */ T append(T value); @@ -85,28 +88,31 @@ void push(Kind kind, ValueNode value); /** - * Appends a node with a void kind to the graph. If the returned node is a {@link StateSplit}, - * with a null {@linkplain StateSplit#stateAfter() frame state}, the frame state is initialized. + * Adds a node to the graph. If the returned node is a {@link StateSplit} with a null + * {@linkplain StateSplit#stateAfter() frame state}, the frame state is initialized. * * @param value the value to add to the graph and push to the stack. The {@code value.getKind()} * kind is used when type checking this operation. * @return a node equivalent to {@code value} in the graph */ default T add(T value) { - assert value.getKind() == Kind.Void; - T appended = append(value); - if (appended instanceof StateSplit) { - StateSplit stateSplit = (StateSplit) appended; + if (value.graph() != null) { + assert !(value instanceof StateSplit) || ((StateSplit) value).stateAfter() != null; + return value; + } + T equivalentValue = append(value); + if (equivalentValue instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) equivalentValue; if (stateSplit.stateAfter() == null) { stateSplit.setStateAfter(createStateAfter()); } } - return appended; + return equivalentValue; } /** * Adds a node with a non-void kind to the graph, pushes it to the stack. If the returned node - * is a {@link StateSplit}, with a null {@linkplain StateSplit#stateAfter() frame state}, the + * is a {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}, the * frame state is initialized. * * @param value the value to add to the graph and push to the stack. The {@code value.getKind()} @@ -119,7 +125,7 @@ /** * Adds a node with a non-void kind to the graph, pushes it to the stack. If the returned node - * is a {@link StateSplit}, with a null {@linkplain StateSplit#stateAfter() frame state}, the + * is a {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}, the * frame state is initialized. * * @param kind the kind to use when type checking this operation @@ -127,17 +133,28 @@ * @return a node equivalent to {@code value} in the graph */ default T addPush(Kind kind, T value) { - T appended = append(value); - push(kind, appended); - if (appended instanceof StateSplit) { - StateSplit stateSplit = (StateSplit) appended; + T equivalentValue = value.graph() != null ? value : append(value); + push(kind.getStackKind(), equivalentValue); + if (equivalentValue instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) equivalentValue; if (stateSplit.stateAfter() == null) { stateSplit.setStateAfter(createStateAfter()); } } - return appended; + return equivalentValue; } + /** + * Handles an invocation that a plugin determines can replace the original invocation (i.e., the + * one for which the plugin was applied). This applies all standard graph builder processing to + * the replaced invocation including applying any relevant plugins to it. + * + * @param invokeKind the kind of the replacement invocation + * @param targetMethod the target of the replacement invocation + * @param args the arguments to the replacement invocation + */ + void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args); + StampProvider getStampProvider(); MetaAccessProvider getMetaAccess(); @@ -177,6 +194,16 @@ int bci(); /** + * Gets the kind of invocation currently being parsed. + */ + InvokeKind getInvokeKind(); + + /** + * Gets the return type of the invocation currently being parsed. + */ + JavaType getInvokeReturnType(); + + /** * Gets the inline depth of this context. 0 implies this is the context for the * {@linkplain #getRootMethod() root method}. */ diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Fri Mar 27 13:29:08 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.graphbuilderconf; +import java.lang.invoke.*; import java.lang.reflect.*; import com.oracle.graal.api.meta.*; @@ -35,45 +36,65 @@ public interface InvocationPlugin extends GraphBuilderPlugin { /** + * Determines if this plugin is for a method with a polymorphic signature (e.g. + * {@link MethodHandle#invokeExact(Object...)}). + */ + default boolean isSignaturePolymorphic() { + return false; + } + + /** + * Handles invocation of a signature polymorphic method. + * + * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static + * @param argsIncludingReceiver all arguments to the invocation include the raw receiver in + * position 0 if {@code targetMethod} is not static + * @see #execute + */ + default boolean applyPolymorphic(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode... argsIncludingReceiver) { + return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); + } + + /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - throw invalidHandler(b, targetMethod, receiver); + return defaultHandler(b, targetMethod, receiver); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { - throw invalidHandler(b, targetMethod, receiver, arg); + return defaultHandler(b, targetMethod, receiver, arg); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { - throw invalidHandler(b, targetMethod, receiver, arg1, arg2); + return defaultHandler(b, targetMethod, receiver, arg1, arg2); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3) { - throw invalidHandler(b, targetMethod, receiver, arg1, arg2, arg3); + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { - throw invalidHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4); + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4); } /** * @see #execute */ default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4, ValueNode arg5) { - throw invalidHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4, arg5); + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4, arg5); } default ResolvedJavaMethod getSubstitute() { @@ -82,56 +103,64 @@ /** * Executes a given plugin against a set of invocation arguments by dispatching to the - * {@code apply(...)} method that matches the number of arguments. + * {@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 plugin is being applied * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static - * @param args the remaining arguments + * @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} * {@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[] args) { - if (receiver != null) { + static boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin plugin, Receiver receiver, ValueNode[] argsIncludingReceiver) { + if (plugin.isSignaturePolymorphic()) { + return plugin.applyPolymorphic(b, targetMethod, receiver, argsIncludingReceiver); + } else if (receiver != null) { assert !targetMethod.isStatic(); - assert args.length > 0; - if (args.length == 1) { + assert argsIncludingReceiver.length > 0; + if (argsIncludingReceiver.length == 1) { return plugin.apply(b, targetMethod, receiver); - } else if (args.length == 2) { - return plugin.apply(b, targetMethod, receiver, args[1]); - } else if (args.length == 3) { - return plugin.apply(b, targetMethod, receiver, args[1], args[2]); - } else if (args.length == 4) { - return plugin.apply(b, targetMethod, receiver, args[1], args[2], args[3]); - } else if (args.length == 5) { - return plugin.apply(b, targetMethod, receiver, args[1], args[2], args[3], args[4]); + } else if (argsIncludingReceiver.length == 2) { + return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1]); + } else if (argsIncludingReceiver.length == 3) { + return plugin.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]); + } else if (argsIncludingReceiver.length == 5) { + return plugin.apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]); } else { - throw plugin.invalidHandler(b, targetMethod, receiver, args); + return plugin.defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); } } else { assert targetMethod.isStatic(); - if (args.length == 0) { + if (argsIncludingReceiver.length == 0) { return plugin.apply(b, targetMethod, null); - } else if (args.length == 1) { - return plugin.apply(b, targetMethod, null, args[0]); - } else if (args.length == 2) { - return plugin.apply(b, targetMethod, null, args[0], args[1]); - } else if (args.length == 3) { - return plugin.apply(b, targetMethod, null, args[0], args[1], args[2]); - } else if (args.length == 4) { - return plugin.apply(b, targetMethod, null, args[0], args[1], args[2], args[3]); - } else if (args.length == 5) { - return plugin.apply(b, targetMethod, null, args[0], args[1], args[2], args[3], args[4]); + } else if (argsIncludingReceiver.length == 1) { + return plugin.apply(b, targetMethod, null, argsIncludingReceiver[0]); + } else if (argsIncludingReceiver.length == 2) { + return plugin.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]); + } else if (argsIncludingReceiver.length == 4) { + return plugin.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]); } else { - throw plugin.invalidHandler(b, targetMethod, receiver, args); + return plugin.defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); } } } - default Error invalidHandler(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod targetMethod, @SuppressWarnings("unused") Receiver receiver, ValueNode... args) { - return new GraalInternalError("Invocation plugin for %s does not handle invocations with %d arguments", targetMethod.format("%H.%n(%p)"), args.length); + /** + * Handles an invocation when a specific {@code apply} method is not available. + */ + default boolean defaultHandler(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod targetMethod, @SuppressWarnings("unused") Receiver receiver, ValueNode... args) { + throw new GraalInternalError("Invocation plugin for %s does not handle invocations with %d arguments", targetMethod.format("%H.%n(%p)"), args.length); } default StackTraceElement getApplySourceLocation(MetaAccessProvider metaAccess) { @@ -139,8 +168,10 @@ for (Method m : c.getDeclaredMethods()) { if (m.getName().equals("apply")) { return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); + } else if (m.getName().equals("defaultHandler")) { + return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); } } - throw new GraalInternalError("could not find method named \"apply\" in " + c.getName()); + throw new GraalInternalError("could not find method named \"apply\" or \"defaultHandler\" in " + c.getName()); } } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Fri Mar 27 13:29:08 2015 +0100 @@ -28,10 +28,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; import com.oracle.graal.compiler.common.*; -import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.hotspot.word.*; -import com.oracle.graal.nodes.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; @@ -81,21 +79,4 @@ } return super.registerMethodSubstitution(cr, originalMethod, substituteMethod); } - - @Override - public Class getMacroSubstitution(ResolvedJavaMethod method) { - HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; - int intrinsicId = hsMethod.intrinsicId(); - if (intrinsicId != 0) { - /* - * The methods of MethodHandle that need substitution are signature-polymorphic, i.e., - * the VM replicates them for every signature that they are actually used for. - * Therefore, we cannot use the usual annotation-driven mechanism to define the - */ - if (MethodHandleNode.lookupMethodHandleIntrinsic(method, providers.getConstantReflection().getMethodHandleAccess()) != null) { - return MethodHandleNode.class; - } - } - return super.getMacroSubstitution(method); - } } diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Fri Mar 27 13:29:08 2015 +0100 @@ -24,6 +24,10 @@ import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import java.lang.invoke.*; + +import sun.reflect.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -35,7 +39,9 @@ import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.nodes.ClassQueryNode.Query; import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.hotspot.replacements.arraycopy.*; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; @@ -60,7 +66,7 @@ */ public static Plugins create(HotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements, Architecture arch) { - InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess); + InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess, constantReflection.getMethodHandleAccess()); Plugins plugins = new Plugins(invocationPlugins); NodeIntrinsificationPhase nodeIntrinsification = new NodeIntrinsificationPhase(metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider); @@ -73,8 +79,11 @@ plugins.setGenericInvocationPlugin(new DefaultGenericInvocationPlugin(metaAccess, nodeIntrinsification, wordOperationPlugin)); registerObjectPlugins(invocationPlugins); + registerClassPlugins(invocationPlugins); registerSystemPlugins(invocationPlugins, foreignCalls); registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config); + registerCallSitePlugins(invocationPlugins); + registerReflectionPlugins(invocationPlugins); registerStableOptionPlugins(invocationPlugins); StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, arch, invocationPlugins, !config.useHeapProfiler); @@ -89,13 +98,79 @@ ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp(); ValueNode mirror; if (objectStamp.isExactType() && objectStamp.nonNull() && !GraalOptions.ImmutableCode.getValue()) { - mirror = b.append(ConstantNode.forConstant(objectStamp.type().getJavaClass(), b.getMetaAccess())); + mirror = ConstantNode.forConstant(objectStamp.type().getJavaClass(), b.getMetaAccess()); } else { StampProvider stampProvider = b.getStampProvider(); - LoadHubNode hub = b.append(new LoadHubNode(stampProvider, rcvr)); - mirror = b.append(new HubGetClassNode(b.getMetaAccess(), hub)); + LoadHubNode hub = b.add(new LoadHubNode(stampProvider, rcvr)); + mirror = new HubGetClassNode(b.getMetaAccess(), hub); + } + b.addPush(Kind.Object, mirror); + return true; + } + }); + r.register1("clone", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + ValueNode object = receiver.get(); + b.addPush(Kind.Object, new ObjectCloneNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), object)); + return true; + } + }); + } + + private static void registerClassPlugins(InvocationPlugins plugins) { + Registration r = new Registration(plugins, Class.class); + + for (Query query : Query.values()) { + r.register1(query.name(), Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + ValueNode javaClass = receiver.get(); + ValueNode folded = ClassQueryNode.tryFold(javaClass, query, b.getMetaAccess(), b.getConstantReflection()); + if (folded != null) { + b.addPush(query.returnKind, folded); + } else { + b.addPush(query.returnKind, new ClassQueryNode(b.getInvokeKind(), targetMethod, query, b.bci(), b.getInvokeReturnType(), javaClass)); + } + return true; } - b.push(Kind.Object, mirror); + }); + } + r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { + ValueNode javaClass = receiver.get(); + ValueNode folded = ClassCastNode.tryFold(javaClass, object, b.getConstantReflection(), b.getAssumptions()); + if (folded != null) { + b.addPush(Kind.Object, folded); + } else { + b.addPush(Kind.Object, new ClassCastNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), javaClass, object)); + } + return true; + } + }); + } + + private static void registerCallSitePlugins(InvocationPlugins plugins) { + InvocationPlugin plugin = new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + ValueNode callSite = receiver.get(); + ValueNode folded = CallSiteTargetNode.tryFold(callSite, b.getMetaAccess(), b.getAssumptions()); + if (folded != null) { + b.addPush(Kind.Object, folded); + } else { + b.addPush(Kind.Object, new CallSiteTargetNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), callSite)); + } + return true; + } + }; + plugins.register(plugin, ConstantCallSite.class, "getTarget", Receiver.class); + plugins.register(plugin, MutableCallSite.class, "getTarget", Receiver.class); + plugins.register(plugin, VolatileCallSite.class, "getTarget", Receiver.class); + } + + private static void registerReflectionPlugins(InvocationPlugins plugins) { + Registration r = new Registration(plugins, Reflection.class); + r.register0("getCallerClass", new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + b.addPush(new ReflectionGetCallerClassNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType())); return true; } }); @@ -115,14 +190,26 @@ return true; } }); + 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)); + return true; + } + }); + r.register5("arraycopy", Object.class, int.class, Object.class, int.class, int.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode src, ValueNode srcPos, ValueNode dst, ValueNode dstPos, ValueNode length) { + b.add(new ArrayCopyNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), src, srcPos, dst, dstPos, length)); + return true; + } + }); } private static void registerThreadPlugins(InvocationPlugins plugins, MetaAccessProvider metaAccess, WordTypes wordTypes, HotSpotVMConfig config) { Registration r = new Registration(plugins, Thread.class); r.register0("currentThread", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - CurrentJavaThreadNode thread = b.append(new CurrentJavaThreadNode(wordTypes.getWordKind())); - ConstantLocationNode location = b.append(new ConstantLocationNode(JAVA_THREAD_THREAD_OBJECT_LOCATION, config.threadObjectOffset)); + CurrentJavaThreadNode thread = b.add(new CurrentJavaThreadNode(wordTypes.getWordKind())); + ConstantLocationNode location = b.add(new ConstantLocationNode(JAVA_THREAD_THREAD_OBJECT_LOCATION, config.threadObjectOffset)); boolean compressible = false; ValueNode javaThread = WordOperationPlugin.readOp(b, Kind.Object, thread, location, BarrierType.NONE, compressible); boolean exactType = compressible; diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Fri Mar 27 13:29:08 2015 +0100 @@ -22,14 +22,22 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.hotspot.meta.HotSpotMethodHandleAccessProvider.*; + +import java.lang.invoke.*; +import java.util.*; + import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.MethodHandleAccessProvider.IntrinsicMethod; import com.oracle.graal.compiler.common.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graphbuilderconf.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.phases.*; +import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.replacements.StandardGraphBuilderPlugins.BoxPlugin; /** @@ -37,10 +45,12 @@ */ final class HotSpotInvocationPlugins extends InvocationPlugins { final HotSpotVMConfig config; + final MethodHandleAccessProvider methodHandleAccess; - public HotSpotInvocationPlugins(HotSpotVMConfig config, MetaAccessProvider metaAccess) { + public HotSpotInvocationPlugins(HotSpotVMConfig config, MetaAccessProvider metaAccess, MethodHandleAccessProvider methodHandleAccess) { super(metaAccess); this.config = config; + this.methodHandleAccess = methodHandleAccess; } @Override @@ -74,6 +84,62 @@ super.register(plugin, declaringClass, name, argumentTypes); } + private ResolvedJavaType methodHandleClass; + private final Map methodHandlePlugins = new EnumMap<>(IntrinsicMethod.class); + + @Override + public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { + if (methodHandleClass == null) { + methodHandleClass = metaAccess.lookupJavaType(MethodHandle.class); + } + if (method.getDeclaringClass().equals(methodHandleClass)) { + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; + int intrinsicId = hsMethod.intrinsicId(); + if (intrinsicId != 0) { + /* + * The methods of MethodHandle that need substitution are signature-polymorphic, + * i.e., the VM replicates them for every signature that they are actually used for. + */ + IntrinsicMethod intrinsicMethod = getMethodHandleIntrinsic(intrinsicId); + if (intrinsicMethod != null) { + InvocationPlugin plugin = methodHandlePlugins.get(intrinsicMethod); + if (plugin == null) { + plugin = new InvocationPlugin() { + public boolean applyPolymorphic(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode... argsIncludingReceiver) { + InvokeKind invokeKind = b.getInvokeKind(); + if (invokeKind != InvokeKind.Static) { + receiver.get(); + } + InvokeNode invoke = MethodHandleNode.tryResolveTargetInvoke(b.getAssumptions(), b.getConstantReflection().getMethodHandleAccess(), intrinsicMethod, targetMethod, + b.bci(), b.getInvokeReturnType(), argsIncludingReceiver); + if (invoke == null) { + b.addPush(new MethodHandleNode(intrinsicMethod, invokeKind, targetMethod, b.bci(), b.getInvokeReturnType(), argsIncludingReceiver)); + } else { + CallTargetNode callTarget = invoke.callTarget(); + NodeInputList argumentsList = callTarget.arguments(); + ValueNode[] args = argumentsList.toArray(new ValueNode[argumentsList.size()]); + for (ValueNode arg : args) { + b.recursiveAppend(arg); + } + b.handleReplacedInvoke(invoke.getInvokeKind(), callTarget.targetMethod(), args); + } + return true; + } + + public boolean isSignaturePolymorphic() { + return true; + } + }; + methodHandlePlugins.put(intrinsicMethod, plugin); + } + return plugin; + } + } + + } + return super.lookupInvocation(method); + } + @Override public void checkNewNodes(GraphBuilderContext b, InvocationPlugin plugin, NodeIterable newNodes) { if (GraalOptions.ImmutableCode.getValue()) { diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java Fri Mar 27 13:29:08 2015 +0100 @@ -98,18 +98,23 @@ public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) { int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId(); if (intrinsicId != 0) { - HotSpotVMConfig config = runtime().getConfig(); - if (intrinsicId == config.vmIntrinsicInvokeBasic) { - return IntrinsicMethod.INVOKE_BASIC; - } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { - return IntrinsicMethod.LINK_TO_INTERFACE; - } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { - return IntrinsicMethod.LINK_TO_SPECIAL; - } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { - return IntrinsicMethod.LINK_TO_STATIC; - } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { - return IntrinsicMethod.LINK_TO_VIRTUAL; - } + return getMethodHandleIntrinsic(intrinsicId); + } + return null; + } + + public static IntrinsicMethod getMethodHandleIntrinsic(int intrinsicId) { + HotSpotVMConfig config = runtime().getConfig(); + if (intrinsicId == config.vmIntrinsicInvokeBasic) { + return IntrinsicMethod.INVOKE_BASIC; + } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { + return IntrinsicMethod.LINK_TO_INTERFACE; + } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { + return IntrinsicMethod.LINK_TO_SPECIAL; + } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { + return IntrinsicMethod.LINK_TO_STATIC; + } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { + return IntrinsicMethod.LINK_TO_VIRTUAL; } return null; } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java Fri Mar 27 13:29:08 2015 +0100 @@ -79,9 +79,9 @@ assert right.stamp() instanceof MetaspacePointerStamp : right + " " + right.stamp(); assert opcode == POINTER_EQ || opcode == POINTER_NE; - PointerEqualsNode comparison = b.append(new PointerEqualsNode(left, right)); - ValueNode eqValue = b.append(forBoolean(opcode == POINTER_EQ)); - ValueNode neValue = b.append(forBoolean(opcode == POINTER_NE)); + PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right)); + ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ)); + ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE)); b.addPush(returnStackKind, new ConditionalNode(comparison, eqValue, neValue)); break; @@ -90,8 +90,8 @@ ValueNode pointer = args[0]; assert pointer.stamp() instanceof MetaspacePointerStamp; - IsNullNode isNull = b.append(new IsNullNode(pointer)); - b.addPush(returnStackKind, new ConditionalNode(isNull, b.append(forBoolean(true)), b.append(forBoolean(false)))); + IsNullNode isNull = b.add(new IsNullNode(pointer)); + b.addPush(returnStackKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); break; case FROM_POINTER: @@ -118,7 +118,7 @@ } else { location = makeLocation(b, args[1], args[2]); } - ReadNode read = b.append(new ReadNode(args[0], location, readStamp, BarrierType.NONE)); + ReadNode read = b.add(new ReadNode(args[0], location, readStamp, BarrierType.NONE)); /* * The read must not float outside its block otherwise it may float above an * explicit zero check on its base address. diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassCastNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -25,24 +25,23 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; /** * {@link MacroNode Macro node} for {@link Class#cast(Object)}. - * - * @see HotSpotClassSubstitutions#cast(Class, Object) */ @NodeInfo public final class ClassCastNode extends MacroStateSplitNode implements Canonicalizable.Binary { public static final NodeClass TYPE = NodeClass.create(ClassCastNode.class); - public ClassCastNode(Invoke invoke) { - super(TYPE, invoke); + public ClassCastNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode receiver, ValueNode object) { + super(TYPE, invokeKind, targetMethod, bci, returnType, receiver, object); } private ValueNode getJavaClass() { @@ -63,12 +62,18 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forJavaClass, ValueNode forObject) { - if (forJavaClass.isConstant()) { - ResolvedJavaType type = tool.getConstantReflection().asJavaType(forJavaClass.asConstant()); + ValueNode folded = tryFold(forJavaClass, forObject, tool.getConstantReflection(), null); + return folded != null ? folded : this; + } + + public static ValueNode tryFold(ValueNode javaClass, ValueNode object, ConstantReflectionProvider constantReflection, Assumptions assumptions) { + ValueNode value = GraphUtil.originalValue(javaClass); + if (value.isConstant()) { + ResolvedJavaType type = constantReflection.asJavaType(value.asConstant()); if (type != null && !type.isPrimitive()) { - return new CheckCastNode(type, forObject, null, false); + return CheckCastNode.create(type, object, null, false, assumptions); } } - return this; + return null; } } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetClassLoader0Node.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2014, 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.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#getClassLoader0()}. - * - * @see HotSpotClassSubstitutions#getClassLoader0(Class) - */ -@SuppressWarnings("javadoc") -@NodeInfo -public final class ClassGetClassLoader0Node extends MacroStateSplitNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassGetClassLoader0Node.class); - - public ClassGetClassLoader0Node(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant() && !GraalOptions.ImmutableCode.getValue()) { - HotSpotObjectConstant c = (HotSpotObjectConstant) javaClass.asConstant(); - JavaConstant classLoader = c.getClassLoader(); - if (classLoader != null) { - return ConstantNode.forConstant(classLoader, tool.getMetaAccess()); - } - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetComponentTypeNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +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.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#getComponentType()}. - * - * @see HotSpotClassSubstitutions#getComponentType(Class) - */ -@NodeInfo -public final class ClassGetComponentTypeNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassGetComponentTypeNode.class); - - public ClassGetComponentTypeNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - HotSpotObjectConstant c = (HotSpotObjectConstant) javaClass.asConstant(); - JavaConstant componentType = c.getComponentType(); - if (componentType != null) { - return ConstantNode.forConstant(componentType, tool.getMetaAccess()); - } - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetModifiersNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +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.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#getModifiers()}. - * - * @see HotSpotClassSubstitutions#getModifiers(Class) - */ -@NodeInfo -public final class ClassGetModifiersNode extends MacroNode implements Canonicalizable { - public static final NodeClass TYPE = NodeClass.create(ClassGetModifiersNode.class); - - public ClassGetModifiersNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - return ConstantNode.forInt(type.getModifiers()); - } - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassGetSuperclassNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +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.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#getSuperclass()}. - * - * @see HotSpotClassSubstitutions#getSuperclass(Class) - */ -@NodeInfo -public final class ClassGetSuperclassNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassGetSuperclassNode.class); - - public ClassGetSuperclassNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - HotSpotObjectConstant c = (HotSpotObjectConstant) javaClass.asConstant(); - JavaConstant superclass = c.getSuperclass(); - if (superclass != null) { - return ConstantNode.forConstant(superclass, tool.getMetaAccess()); - } - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsArrayNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +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.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#isArray()}. - * - * @see HotSpotClassSubstitutions#isArray(Class) - */ -@NodeInfo -public final class ClassIsArrayNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassIsArrayNode.class); - - public ClassIsArrayNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - return ConstantNode.forBoolean(type.isArray()); - } - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsInterfaceNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +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.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#isInterface()}. - * - * @see HotSpotClassSubstitutions#isInterface(Class) - */ -@NodeInfo -public final class ClassIsInterfaceNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassIsInterfaceNode.class); - - public ClassIsInterfaceNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - return ConstantNode.forBoolean(type.isInterface()); - } - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassIsPrimitiveNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +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.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * {@link MacroNode Macro node} for {@link Class#isPrimitive()}. - * - * @see HotSpotClassSubstitutions#isPrimitive(Class) - */ -@NodeInfo -public final class ClassIsPrimitiveNode extends MacroNode implements Canonicalizable { - - public static final NodeClass TYPE = NodeClass.create(ClassIsPrimitiveNode.class); - - public ClassIsPrimitiveNode(Invoke invoke) { - super(TYPE, invoke); - } - - private ValueNode getJavaClass() { - return arguments.get(0); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode javaClass = getJavaClass(); - if (javaClass.isConstant()) { - ConstantReflectionProvider constantReflection = tool.getConstantReflection(); - ResolvedJavaType type = constantReflection.asJavaType(javaClass.asConstant()); - if (type != null) { - return ConstantNode.forBoolean(type.isPrimitive()); - } - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassQueryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ClassQueryNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014, 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.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * {@link MacroNode Macro node} for some basic query methods in {@link Class}. + */ +@NodeInfo +public final class ClassQueryNode extends MacroStateSplitNode implements Canonicalizable { + + /** + * The query methods in {@link Class} supported by {@link ClassQueryNode}. + */ + public enum Query { + getClassLoader0(Kind.Object), + getComponentType(Kind.Object), + getSuperclass(Kind.Object), + getModifiers(Kind.Int), + isArray(Kind.Boolean), + isInterface(Kind.Boolean), + isPrimitive(Kind.Boolean); + + private Query(Kind returnKind) { + this.returnKind = returnKind; + } + + public final Kind returnKind; + } + + public static final NodeClass TYPE = NodeClass.create(ClassQueryNode.class); + + protected final Query query; + + public ClassQueryNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, Query query, int bci, JavaType returnType, ValueNode receiver) { + super(TYPE, invokeKind, targetMethod, bci, returnType, receiver); + this.query = query; + assert query.returnKind == targetMethod.getSignature().getReturnKind(); + } + + private ValueNode getJavaClass() { + return arguments.get(0); + } + + @Override + public Node canonical(CanonicalizerTool tool) { + ValueNode value = tryFold(getJavaClass(), query, tool.getMetaAccess(), tool.getConstantReflection()); + return value == null ? this : value; + } + + public static ValueNode tryFold(ValueNode javaClass, Query query, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) { + ValueNode value = GraphUtil.originalValue(javaClass); + if (value != null && value.isConstant()) { + if (query.returnKind == Kind.Object) { + if (GraalOptions.ImmutableCode.getValue()) { + return null; + } + HotSpotObjectConstant c = (HotSpotObjectConstant) value.asConstant(); + JavaConstant answer; + switch (query) { + case getClassLoader0: + answer = c.getClassLoader(); + break; + case getComponentType: + answer = c.getComponentType(); + break; + case getSuperclass: + answer = c.getSuperclass(); + break; + default: + GraalInternalError.shouldNotReachHere(); + answer = null; + } + if (answer != null) { + return ConstantNode.forConstant(answer, metaAccess); + } + } else { + ResolvedJavaType type = constantReflection.asJavaType(value.asConstant()); + if (type != null) { + switch (query) { + case isArray: + return ConstantNode.forBoolean(type.isArray()); + case isPrimitive: + return ConstantNode.forBoolean(type.isPrimitive()); + case isInterface: + return ConstantNode.forBoolean(type.isInterface()); + case getModifiers: + return ConstantNode.forInt(type.getModifiers()); + default: + GraalInternalError.shouldNotReachHere(); + } + } + } + } + return null; + } +} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ResolvedMethodHandleCallTargetNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/ResolvedMethodHandleCallTargetNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -0,0 +1,77 @@ +/* + * 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.nodes; + +import java.lang.invoke.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; + +/** + * A call target that replaces itself in the graph when being lowered by restoring the original + * {@link MethodHandle} invocation target. This is required for when a {@link MethodHandle} call was + * resolved to a constant target but the target was not inlined. In that case, the original + * invocation must be restored with all of its original arguments. Why? HotSpot linkage for + * {@link MethodHandle} intrinsics (see {@code MethodHandles::generate_method_handle_dispatch}) + * expects certain implicit arguments to be on the stack such as the MemberName suffix argument for + * a call to one of the MethodHandle.linkTo* methods. An + * {@linkplain MethodHandleNode#tryResolveTargetInvoke resolved} {@link MethodHandle} invocation + * drops these arguments which means the interpreter won't find them. + */ +@NodeInfo +public final class ResolvedMethodHandleCallTargetNode extends MethodCallTargetNode implements Lowerable { + + public static final NodeClass TYPE = NodeClass.create(ResolvedMethodHandleCallTargetNode.class); + protected final ResolvedJavaMethod originalTargetMethod; + protected final JavaType originalReturnType; + @Input NodeInputList originalArguments; + + public ResolvedMethodHandleCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod originalTargetMethod, + ValueNode[] originalArguments, JavaType originalReturnType) { + super(TYPE, invokeKind, targetMethod, arguments, returnType); + this.originalTargetMethod = originalTargetMethod; + this.originalReturnType = originalReturnType; + this.originalArguments = new NodeInputList<>(this, originalArguments); + } + + @Override + public void lower(LoweringTool tool) { + InvokeKind replacementInvokeKind = originalTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; + MethodCallTargetNode replacement = graph().add( + new MethodCallTargetNode(replacementInvokeKind, originalTargetMethod, originalArguments.toArray(new ValueNode[originalArguments.size()]), originalReturnType)); + + // Replace myself... + this.replaceAndDelete(replacement); + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + throw GraalInternalError.shouldNotReachHere("should have replaced itself"); + } +} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteSubstitutions.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2013, 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 java.lang.invoke.*; - -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.*; - -@ServiceProvider(ReplacementsProvider.class) -public class CallSiteSubstitutions implements ReplacementsProvider { - - @Override - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { - replacements.registerSubstitutions(ConstantCallSite.class, ConstantCallSiteSubstitutions.class); - replacements.registerSubstitutions(MutableCallSite.class, MutableCallSiteSubstitutions.class); - replacements.registerSubstitutions(VolatileCallSite.class, VolatileCallSiteSubstitutions.class); - } - - @ClassSubstitution(ConstantCallSite.class) - private static class ConstantCallSiteSubstitutions { - - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(ConstantCallSite callSite); - } - - @ClassSubstitution(MutableCallSite.class) - private static class MutableCallSiteSubstitutions { - - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(MutableCallSite callSite); - } - - @ClassSubstitution(VolatileCallSite.class) - private static class VolatileCallSiteSubstitutions { - - @MacroSubstitution(isStatic = false, macro = CallSiteTargetNode.class) - public static native MethodHandle getTarget(VolatileCallSite callSite); - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CallSiteTargetNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -27,8 +27,10 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; import com.oracle.graal.replacements.nodes.*; @NodeInfo @@ -36,18 +38,19 @@ public static final NodeClass TYPE = NodeClass.create(CallSiteTargetNode.class); - public CallSiteTargetNode(Invoke invoke) { - super(TYPE, invoke); + public CallSiteTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode receiver) { + super(TYPE, invokeKind, targetMethod, bci, returnType, receiver); } private ValueNode getCallSite() { return arguments.get(0); } - private ConstantNode getConstantCallTarget(MetaAccessProvider metaAccess) { - if (getCallSite().isConstant() && !getCallSite().isNullConstant()) { - HotSpotObjectConstant c = (HotSpotObjectConstant) getCallSite().asConstant(); - JavaConstant target = c.getCallSiteTarget(graph().getAssumptions()); + public static ConstantNode tryFold(ValueNode initialCallSite, MetaAccessProvider metaAccess, Assumptions assumptions) { + ValueNode callSite = GraphUtil.originalValue(initialCallSite); + if (callSite.isConstant() && !callSite.isNullConstant()) { + HotSpotObjectConstant c = (HotSpotObjectConstant) callSite.asConstant(); + JavaConstant target = c.getCallSiteTarget(assumptions); if (target != null) { return ConstantNode.forConstant(target, metaAccess); } @@ -57,7 +60,7 @@ @Override public Node canonical(CanonicalizerTool tool) { - ConstantNode target = getConstantCallTarget(tool.getMetaAccess()); + ConstantNode target = tryFold(getCallSite(), tool.getMetaAccess(), graph().getAssumptions()); if (target != null) { return target; } @@ -67,7 +70,7 @@ @Override public void lower(LoweringTool tool) { - ConstantNode target = getConstantCallTarget(tool.getMetaAccess()); + ConstantNode target = tryFold(getCallSite(), tool.getMetaAccess(), graph().getAssumptions()); if (target != null) { graph().replaceFixedWithFloating(this, target); diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotClassSubstitutions.java Fri Mar 27 13:29:08 2015 +0100 @@ -27,10 +27,8 @@ import java.lang.reflect.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.word.*; /** @@ -39,7 +37,6 @@ @ClassSubstitution(java.lang.Class.class) public class HotSpotClassSubstitutions { - @MacroSubstitution(macro = ClassGetModifiersNode.class, isStatic = false) @MethodSubstitution(isStatic = false, forced = true) public static int getModifiers(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -51,8 +48,6 @@ } } - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsInterfaceNode.class, isStatic = false) @MethodSubstitution(isStatic = false, forced = true) public static boolean isInterface(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -64,8 +59,6 @@ } } - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsArrayNode.class, isStatic = false) @MethodSubstitution(isStatic = false, forced = true) public static boolean isArray(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -76,18 +69,14 @@ } } - // This MacroSubstitution should be removed once non-null klass pointers can be optimized - @MacroSubstitution(macro = ClassIsPrimitiveNode.class, isStatic = false) @MethodSubstitution(isStatic = false, forced = true) public static boolean isPrimitive(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); return klass.isNull(); } - @MacroSubstitution(macro = ClassGetClassLoader0Node.class, isStatic = false) public static native ClassLoader getClassLoader0(Class thisObj); - @MacroSubstitution(macro = ClassGetSuperclassNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getSuperclass(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -113,7 +102,6 @@ return PiNode.asNonNullClass(klass.readObject(classMirrorOffset(), CLASS_MIRROR_LOCATION)); } - @MacroSubstitution(macro = ClassGetComponentTypeNode.class, isStatic = false) @MethodSubstitution(isStatic = false) public static Class getComponentType(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); @@ -124,7 +112,4 @@ } return null; } - - @MacroSubstitution(macro = ClassCastNode.class, isStatic = false) - public static native Object cast(final Class thisObj, Object obj); } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; @@ -47,52 +48,50 @@ public final class MethodHandleNode extends MacroStateSplitNode implements Simplifiable { public static final NodeClass TYPE = NodeClass.create(MethodHandleNode.class); - // Replacement method data - protected ResolvedJavaMethod replacementTargetMethod; - protected JavaType replacementReturnType; - @Input NodeInputList replacementArguments; + protected final IntrinsicMethod intrinsicMethod; - public MethodHandleNode(Invoke invoke) { - super(TYPE, invoke); - MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); - // See if we need to save some replacement method data. - if (callTarget instanceof SelfReplacingMethodCallTargetNode) { - SelfReplacingMethodCallTargetNode selfReplacingMethodCallTargetNode = (SelfReplacingMethodCallTargetNode) callTarget; - replacementTargetMethod = selfReplacingMethodCallTargetNode.replacementTargetMethod(); - replacementReturnType = selfReplacingMethodCallTargetNode.replacementReturnType(); - replacementArguments = selfReplacingMethodCallTargetNode.replacementArguments(); - } else { - // NodeInputList can't be null. - replacementArguments = new NodeInputList<>(this); - } + public MethodHandleNode(IntrinsicMethod intrinsicMethod, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(TYPE, invokeKind, targetMethod, bci, returnType, arguments); + this.intrinsicMethod = intrinsicMethod; } /** - * Returns the method handle method intrinsic identifier for the provided method, or - * {@code null} if the method is not a method that can be handled by this class. + * Attempts to transform application of an intrinsifiable {@link MethodHandle} method into an + * invocation on another method with possibly transformed arguments. + * + * @param assumptions object for recording any speculations made during the transformation + * @param methodHandleAccess objects for accessing the implementation internals of a + * {@link MethodHandle} + * @param intrinsicMethod denotes the intrinsifiable {@link MethodHandle} method being processed + * @param bci the BCI of the original {@link MethodHandle} call + * @param returnType return type of the original {@link MethodHandle} call + * @param arguments arguments to the original {@link MethodHandle} call + * @return a more direct invocation derived from the {@link MethodHandle} call or null */ - public static IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method, MethodHandleAccessProvider methodHandleAccess) { - return methodHandleAccess.lookupMethodHandleIntrinsic(method); + public static InvokeNode tryResolveTargetInvoke(Assumptions assumptions, MethodHandleAccessProvider methodHandleAccess, IntrinsicMethod intrinsicMethod, ResolvedJavaMethod original, int bci, + JavaType returnType, ValueNode... arguments) { + switch (intrinsicMethod) { + case INVOKE_BASIC: + return getInvokeBasicTarget(assumptions, intrinsicMethod, methodHandleAccess, original, bci, returnType, arguments); + case LINK_TO_STATIC: + case LINK_TO_SPECIAL: + case LINK_TO_VIRTUAL: + case LINK_TO_INTERFACE: + return getLinkToTarget(assumptions, intrinsicMethod, methodHandleAccess, original, bci, returnType, arguments); + default: + throw GraalInternalError.shouldNotReachHere(); + } } @Override public void simplify(SimplifierTool tool) { - InvokeNode invoke; - IntrinsicMethod intrinsicMethod = lookupMethodHandleIntrinsic(targetMethod, tool.getConstantReflection().getMethodHandleAccess()); - switch (intrinsicMethod) { - case INVOKE_BASIC: - invoke = getInvokeBasicTarget(tool, intrinsicMethod); - break; - case LINK_TO_STATIC: - case LINK_TO_SPECIAL: - case LINK_TO_VIRTUAL: - case LINK_TO_INTERFACE: - invoke = getLinkToTarget(tool, intrinsicMethod); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } + MethodHandleAccessProvider methodHandleAccess = tool.getConstantReflection().getMethodHandleAccess(); + ValueNode[] argumentsArray = arguments.toArray(new ValueNode[arguments.size()]); + InvokeNode invoke = tryResolveTargetInvoke(graph().getAssumptions(), methodHandleAccess, intrinsicMethod, targetMethod, bci, returnType, argumentsArray); if (invoke != null) { + assert invoke.graph() == null; + invoke = graph().addOrUniqueWithInputs(invoke); + invoke.setStateAfter(stateAfter()); FixedNode currentNext = next(); replaceAtUsages(invoke); GraphUtil.removeFixedWithUnusedInputs(this); @@ -105,8 +104,8 @@ * * @return the receiver argument node */ - private ValueNode getReceiver() { - return arguments.first(); + private static ValueNode getReceiver(ValueNode[] arguments) { + return arguments[0]; } /** @@ -114,8 +113,8 @@ * * @return the MemberName argument node (which is the last argument) */ - private ValueNode getMemberName() { - return arguments.last(); + private static ValueNode getMemberName(ValueNode[] arguments) { + return arguments[arguments.length - 1]; } /** @@ -124,10 +123,11 @@ * * @return invoke node for the {@link java.lang.invoke.MethodHandle} target */ - protected InvokeNode getInvokeBasicTarget(SimplifierTool tool, IntrinsicMethod intrinsicMethod) { - ValueNode methodHandleNode = getReceiver(); + private static InvokeNode getInvokeBasicTarget(Assumptions assumptions, IntrinsicMethod intrinsicMethod, MethodHandleAccessProvider methodHandleAccess, ResolvedJavaMethod original, int bci, + JavaType returnType, ValueNode[] arguments) { + ValueNode methodHandleNode = getReceiver(arguments); if (methodHandleNode.isConstant()) { - return getTargetInvokeNode(tool.getConstantReflection().getMethodHandleAccess().resolveInvokeBasicTarget(methodHandleNode.asJavaConstant(), false), intrinsicMethod); + return getTargetInvokeNode(assumptions, intrinsicMethod, bci, returnType, arguments, methodHandleAccess.resolveInvokeBasicTarget(methodHandleNode.asJavaConstant(), true), original); } return null; } @@ -140,10 +140,11 @@ * * @return invoke node for the member name target */ - protected InvokeNode getLinkToTarget(SimplifierTool tool, IntrinsicMethod intrinsicMethod) { - ValueNode memberNameNode = getMemberName(); + private static InvokeNode getLinkToTarget(Assumptions assumptions, IntrinsicMethod intrinsicMethod, MethodHandleAccessProvider methodHandleAccess, ResolvedJavaMethod original, int bci, + JavaType returnType, ValueNode[] arguments) { + ValueNode memberNameNode = getMemberName(arguments); if (memberNameNode.isConstant()) { - return getTargetInvokeNode(tool.getConstantReflection().getMethodHandleAccess().resolveLinkToTarget(memberNameNode.asJavaConstant()), intrinsicMethod); + return getTargetInvokeNode(assumptions, intrinsicMethod, bci, returnType, arguments, methodHandleAccess.resolveLinkToTarget(memberNameNode.asJavaConstant()), original); } return null; } @@ -155,7 +156,8 @@ * @param target the target, already loaded from the member name node * @return invoke node for the member name target */ - private InvokeNode getTargetInvokeNode(ResolvedJavaMethod target, IntrinsicMethod intrinsicMethod) { + private static InvokeNode getTargetInvokeNode(Assumptions assumptions, IntrinsicMethod intrinsicMethod, int bci, JavaType returnType, ValueNode[] arguments, ResolvedJavaMethod target, + ResolvedJavaMethod original) { if (target == null) { return null; } @@ -171,34 +173,35 @@ // Cast receiver to its type. if (!isStatic) { JavaType receiverType = target.getDeclaringClass(); - maybeCastArgument(0, receiverType); + maybeCastArgument(arguments, 0, receiverType); } // Cast reference arguments to its type. for (int index = 0; index < signature.getParameterCount(false); index++) { JavaType parameterType = signature.getParameterType(index, target.getDeclaringClass()); - maybeCastArgument(receiverSkip + index, parameterType); + maybeCastArgument(arguments, receiverSkip + index, parameterType); } if (target.canBeStaticallyBound()) { - return createTargetInvokeNode(target, intrinsicMethod); + return createTargetInvokeNode(intrinsicMethod, target, original, bci, returnType, arguments); } // Try to get the most accurate receiver type if (intrinsicMethod == IntrinsicMethod.LINK_TO_VIRTUAL || intrinsicMethod == IntrinsicMethod.LINK_TO_INTERFACE) { - ResolvedJavaType receiverType = StampTool.typeOrNull(getReceiver().stamp()); + ValueNode receiver = getReceiver(arguments); + ResolvedJavaType receiverType = StampTool.typeOrNull(receiver.stamp()); if (receiverType != null) { AssumptionResult concreteMethod = receiverType.findUniqueConcreteMethod(target); if (concreteMethod != null) { - graph().getAssumptions().record(concreteMethod); - return createTargetInvokeNode(concreteMethod.getResult(), intrinsicMethod); + assumptions.record(concreteMethod); + return createTargetInvokeNode(intrinsicMethod, concreteMethod.getResult(), original, bci, returnType, arguments); } } } else { AssumptionResult concreteMethod = target.getDeclaringClass().findUniqueConcreteMethod(target); if (concreteMethod != null) { - graph().getAssumptions().record(concreteMethod); - return createTargetInvokeNode(concreteMethod.getResult(), intrinsicMethod); + assumptions.record(concreteMethod); + return createTargetInvokeNode(intrinsicMethod, concreteMethod.getResult(), original, bci, returnType, arguments); } } @@ -212,15 +215,15 @@ * @param index of the argument to be cast * @param type the type the argument should be cast to */ - private void maybeCastArgument(int index, JavaType type) { + private static void maybeCastArgument(ValueNode[] arguments, int index, JavaType type) { if (type instanceof ResolvedJavaType) { ResolvedJavaType targetType = (ResolvedJavaType) type; if (!targetType.isPrimitive()) { - ValueNode argument = arguments.get(index); + ValueNode argument = arguments[index]; ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp()); if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) { - PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType))); - arguments.set(index, piNode); + PiNode piNode = new PiNode(argument, StampFactory.declared(targetType)); + arguments[index] = piNode; } } } @@ -228,57 +231,42 @@ /** * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed - * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}. + * to the InvokeNode is in fact a {@link ResolvedMethodHandleCallTargetNode}. * - * @param target the method to be called * @return invoke node for the member name target */ - private InvokeNode createTargetInvokeNode(ResolvedJavaMethod target, IntrinsicMethod intrinsicMethod) { + private static InvokeNode createTargetInvokeNode(IntrinsicMethod intrinsicMethod, ResolvedJavaMethod target, ResolvedJavaMethod original, int bci, JavaType returnType, ValueNode[] arguments) { InvokeKind targetInvokeKind = target.isStatic() ? InvokeKind.Static : InvokeKind.Special; JavaType targetReturnType = target.getSignature().getReturnType(null); // MethodHandleLinkTo* nodes have a trailing MemberName argument which // needs to be popped. - ValueNode[] originalArguments = arguments.toArray(new ValueNode[arguments.size()]); ValueNode[] targetArguments; switch (intrinsicMethod) { case INVOKE_BASIC: - targetArguments = originalArguments; + targetArguments = arguments; break; case LINK_TO_STATIC: case LINK_TO_SPECIAL: case LINK_TO_VIRTUAL: case LINK_TO_INTERFACE: - targetArguments = Arrays.copyOfRange(originalArguments, 0, arguments.size() - 1); + targetArguments = Arrays.copyOfRange(arguments, 0, arguments.length - 1); break; default: throw GraalInternalError.shouldNotReachHere(); } - // If there is already replacement information, use that instead. - MethodCallTargetNode callTarget; - if (replacementTargetMethod == null) { - callTarget = new SelfReplacingMethodCallTargetNode(targetInvokeKind, target, targetArguments, targetReturnType, getTargetMethod(), originalArguments, getReturnType()); - } else { - ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]); - callTarget = new SelfReplacingMethodCallTargetNode(targetInvokeKind, target, targetArguments, targetReturnType, replacementTargetMethod, args, replacementReturnType); - } - graph().add(callTarget); + MethodCallTargetNode callTarget = new ResolvedMethodHandleCallTargetNode(targetInvokeKind, target, targetArguments, targetReturnType, original, arguments, returnType); // The call target can have a different return type than the invoker, // e.g. the target returns an Object but the invoker void. In this case // we need to use the stamp of the invoker. Note: always using the // invoker's stamp would be wrong because it's a less concrete type // (usually java.lang.Object). - InvokeNode invoke; - if (stamp() == StampFactory.forVoid()) { - invoke = new InvokeNode(callTarget, getBci(), stamp()); + if (returnType.getKind() == Kind.Void) { + return new InvokeNode(callTarget, bci, StampFactory.forVoid()); } else { - invoke = new InvokeNode(callTarget, getBci()); + return new InvokeNode(callTarget, bci); } - graph().add(invoke); - invoke.setStateAfter(stateAfter()); - return invoke; } - } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectCloneNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -31,6 +31,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.java.*; @@ -43,8 +44,8 @@ public static final NodeClass TYPE = NodeClass.create(ObjectCloneNode.class); - public ObjectCloneNode(Invoke invoke) { - super(TYPE, invoke); + public ObjectCloneNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode receiver) { + super(TYPE, invokeKind, targetMethod, bci, returnType, receiver); } @Override diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Fri Mar 27 13:29:08 2015 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; /** * Substitutions for {@link java.lang.Object} methods. @@ -51,7 +50,4 @@ public static void init(Object thisObj) { RegisterFinalizerNode.register(thisObj); } - - @MacroSubstitution(macro = ObjectCloneNode.class, isStatic = false, forced = true) - public static native Object clone(Object obj); } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionGetCallerClassNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -31,6 +31,7 @@ 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.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; @@ -39,8 +40,8 @@ public static final NodeClass TYPE = NodeClass.create(ReflectionGetCallerClassNode.class); - public ReflectionGetCallerClassNode(Invoke invoke) { - super(TYPE, invoke); + public ReflectionGetCallerClassNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(TYPE, invokeKind, targetMethod, bci, returnType, arguments); } @Override diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ReflectionSubstitutions.java Fri Mar 27 13:29:08 2015 +0100 @@ -29,7 +29,6 @@ import com.oracle.graal.api.replacements.*; import com.oracle.graal.hotspot.word.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; /** * Substitutions for {@link sun.reflect.Reflection} methods. @@ -37,9 +36,6 @@ @ClassSubstitution(sun.reflect.Reflection.class) public class ReflectionSubstitutions { - @MacroSubstitution(macro = ReflectionGetCallerClassNode.class, optional = true) - public static native Class getCallerClass(); - @MethodSubstitution public static int getClassAccessFlags(Class aClass) { KlassPointer klass = ClassGetHubNode.readClass(GuardingPiNode.asNonNullClass(aClass)); diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemIdentityHashCodeNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -29,6 +29,7 @@ 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 @@ -36,8 +37,8 @@ public static final NodeClass TYPE = NodeClass.create(SystemIdentityHashCodeNode.class); - public SystemIdentityHashCodeNode(Invoke invoke) { - super(TYPE, invoke); + public SystemIdentityHashCodeNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode object) { + super(TYPE, invokeKind, targetMethod, bci, returnType, object); } @Override diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/SystemSubstitutions.java Fri Mar 27 13:29:08 2015 +0100 @@ -27,8 +27,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.hotspot.replacements.arraycopy.*; -import com.oracle.graal.nodes.spi.*; /** * Substitutions for {@link java.lang.System} methods. @@ -39,10 +37,6 @@ public static final ForeignCallDescriptor JAVA_TIME_MILLIS = new ForeignCallDescriptor("javaTimeMillis", long.class); public static final ForeignCallDescriptor JAVA_TIME_NANOS = new ForeignCallDescriptor("javaTimeNanos", long.class); - @MacroSubstitution(macro = ArrayCopyNode.class) - public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); - - @MacroSubstitution(macro = SystemIdentityHashCodeNode.class) @MethodSubstitution public static int identityHashCode(Object x) { if (probability(NOT_FREQUENT_PROBABILITY, x == null)) { diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopyNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; @@ -43,8 +44,8 @@ public static final NodeClass TYPE = NodeClass.create(ArrayCopyNode.class); - public ArrayCopyNode(Invoke invoke) { - super(TYPE, invoke); + public ArrayCopyNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode src, ValueNode srcPos, ValueNode dst, ValueNode dstPos, ValueNode length) { + super(TYPE, invokeKind, targetMethod, bci, returnType, src, srcPos, dst, dstPos, length); } private StructuredGraph selectSnippet(LoweringTool tool, final Replacements replacements) { diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Mar 27 13:29:08 2015 +0100 @@ -1143,6 +1143,21 @@ } } + private InvokeKind currentInvokeKind; + private JavaType currentInvokeReturnType; + + public InvokeKind getInvokeKind() { + return currentInvokeKind; + } + + public JavaType getInvokeReturnType() { + return currentInvokeReturnType; + } + + public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) { + appendInvoke(invokeKind, targetMethod, args); + } + private void appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) { ResolvedJavaMethod targetMethod = initialTargetMethod; InvokeKind invokeKind = initialInvokeKind; @@ -1179,22 +1194,29 @@ } } - if (tryGenericInvocationPlugin(args, targetMethod)) { - if (TraceParserPlugins.getValue()) { - traceWithContext("used generic invocation plugin for %s", targetMethod.format("%h.%n(%p)")); + try { + currentInvokeReturnType = returnType; + currentInvokeKind = invokeKind; + if (tryGenericInvocationPlugin(args, targetMethod)) { + if (TraceParserPlugins.getValue()) { + traceWithContext("used generic invocation plugin for %s", targetMethod.format("%h.%n(%p)")); + } + return; } - return; - } - if (tryInvocationPlugin(args, targetMethod, resultType)) { - if (TraceParserPlugins.getValue()) { - traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)")); + 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, invokeKind, returnType)) { + return; + } + } finally { + currentInvokeReturnType = null; + currentInvokeKind = null; } MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); @@ -1252,7 +1274,8 @@ boolean check(boolean pluginResult) { if (pluginResult == true) { - assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize : error("plugin manipulated the stack incorrectly"); + int expectedStackSize = beforeStackSize + resultType.getSlotCount(); + assert expectedStackSize == frameState.stackSize : error("plugin manipulated the stack incorrectly: expected=%d, actual=%d", expectedStackSize, frameState.stackSize); NodeIterable newNodes = currentGraph.getNewNodes(mark); assert !needsNullCheck || isPointerNonNull(args[0].stamp()) : error("plugin needs to null check the receiver of %s: receiver=%s", targetMethod.format("%H.%n(%p)"), args[0]); for (Node n : newNodes) { @@ -1278,6 +1301,15 @@ private boolean tryInvocationPlugin(ValueNode[] args, ResolvedJavaMethod targetMethod, Kind resultType) { InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod); if (plugin != null) { + + ReplacementContext context = this.replacementContext; + if (context != null && context.isCallToOriginal(targetMethod)) { + // Self recursive replacement means the original + // method should be called. + assert !targetMethod.hasBytecodes() : "TODO: when does this happen?"; + return false; + } + InvocationPluginAssertions assertions = assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; if (InvocationPlugin.execute(this, targetMethod, plugin, invocationPluginReceiver.init(targetMethod, args), args)) { assert assertions.check(true); @@ -1305,7 +1337,7 @@ return false; } - boolean inline(InlineInvokePlugin plugin, ResolvedJavaMethod targetMethod, InlineInfo inlineInfo, ValueNode[] args) { + public boolean inline(InlineInvokePlugin plugin, ResolvedJavaMethod targetMethod, InlineInfo inlineInfo, ValueNode[] args) { int bci = bci(); ResolvedJavaMethod inlinedMethod = inlineInfo.methodToInline; if (TraceInlineDuringParsing.getValue() || TraceParserPlugins.getValue()) { diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/SelfReplacingMethodCallTargetNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +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.nodes.java; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -/** - * A SelfReplacingMethodCallTargetNode replaces itself in the graph when being lowered with a - * {@link MethodCallTargetNode} that calls the stored replacement target method. - * - * This node is used for method handle call nodes which have a constant call target but are not - * inlined. - */ -@NodeInfo -public final class SelfReplacingMethodCallTargetNode extends MethodCallTargetNode implements Lowerable { - - public static final NodeClass TYPE = NodeClass.create(SelfReplacingMethodCallTargetNode.class); - // Replacement method data - protected final ResolvedJavaMethod replacementTargetMethod; - protected final JavaType replacementReturnType; - @Input NodeInputList replacementArguments; - - public SelfReplacingMethodCallTargetNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] arguments, JavaType returnType, ResolvedJavaMethod replacementTargetMethod, - ValueNode[] replacementArguments, JavaType replacementReturnType) { - super(TYPE, invokeKind, targetMethod, arguments, returnType); - this.replacementTargetMethod = replacementTargetMethod; - this.replacementReturnType = replacementReturnType; - this.replacementArguments = new NodeInputList<>(this, replacementArguments); - } - - public ResolvedJavaMethod replacementTargetMethod() { - return replacementTargetMethod; - } - - public JavaType replacementReturnType() { - return replacementReturnType; - } - - public NodeInputList replacementArguments() { - return replacementArguments; - } - - @Override - public void lower(LoweringTool tool) { - InvokeKind replacementInvokeKind = replacementTargetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; - MethodCallTargetNode replacement = graph().add( - new MethodCallTargetNode(replacementInvokeKind, replacementTargetMethod, replacementArguments.toArray(new ValueNode[replacementArguments.size()]), replacementReturnType)); - - // Replace myself... - this.replaceAndDelete(replacement); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - throw GraalInternalError.shouldNotReachHere("should have replaced itself"); - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Fri Mar 27 13:29:08 2015 +0100 @@ -212,7 +212,7 @@ if (callTarget.targetMethod() == null) { return "target method is null"; } - assert invoke.stateAfter() != null; + assert invoke.stateAfter() != null : invoke; if (!invoke.useForInlining()) { return "the invoke is marked to be not used for inlining"; } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Fri Mar 27 13:29:08 2015 +0100 @@ -22,6 +22,8 @@ */ package com.oracle.graal.replacements.test; +import java.util.function.*; + import org.junit.*; import com.oracle.graal.api.meta.*; @@ -34,6 +36,9 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.runtime.*; +/** + * Tests for expected behavior when parsing snippets and intrinsics. + */ public class ReplacementsParseTest extends GraalCompilerTest { private static final Object THROW_EXCEPTION_MARKER = new Object() { @@ -64,6 +69,10 @@ } return res; } + + static String identity(String s) { + return s; + } } @ClassSubstitution(TestMethods.class) @@ -75,11 +84,17 @@ return Math.nextAfter(xx, d); } + /** + * Tests partial intrinsification. + */ @MethodSubstitution static String stringize(Object obj) { if (obj != null && obj.getClass() == String.class) { return asNonNullString(obj); } else { + // A recursive call denotes exiting/deoptimizing + // out of the partial intrinsification to the + // slow/uncommon case. return stringize(obj); } } @@ -91,6 +106,17 @@ @NodeIntrinsic(PiNode.class) private static native String asNonNullStringIntrinsic(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull); + /** + * Tests that non-capturing lambdas are folded away. + */ + @MethodSubstitution + static String identity(String value) { + return apply(s -> s, value); + } + + private static String apply(Function f, String value) { + return f.apply(value); + } } private static boolean substitutionsInstalled; @@ -156,7 +182,7 @@ test("callStringize", Boolean.TRUE); } - public Object callStringize(Object obj) { + public static Object callStringize(Object obj) { return TestMethods.stringize(obj); } @@ -167,4 +193,14 @@ test(method, null, Boolean.TRUE); test(method, null, THROW_EXCEPTION_MARKER); } + + @Test + public void testLambda() { + test("callLambda", (String) null); + test("callLambda", "a string"); + } + + public static String callLambda(String value) { + return TestMethods.identity(value); + } } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultGenericInvocationPlugin.java Fri Mar 27 13:29:08 2015 +0100 @@ -85,7 +85,7 @@ if (!COULD_NOT_FOLD.equals(constant)) { if (constant != null) { // Replace the invoke with the result of the call - ConstantNode res = b.append(ConstantNode.forConstant(constant, b.getMetaAccess())); + ConstantNode res = b.add(ConstantNode.forConstant(constant, b.getMetaAccess())); b.addPush(res.getKind().getStackKind(), res); } else { // This must be a void invoke @@ -123,7 +123,7 @@ } if (res instanceof UnsafeCopyNode) { UnsafeCopyNode copy = (UnsafeCopyNode) res; - UnsafeLoadNode value = b.append(new UnsafeLoadNode(copy.sourceObject(), copy.sourceOffset(), copy.accessKind(), copy.getLocationIdentity())); + UnsafeLoadNode value = b.add(new UnsafeLoadNode(copy.sourceObject(), copy.sourceOffset(), copy.accessKind(), copy.getLocationIdentity())); b.add(new UnsafeStoreNode(copy.destinationObject(), copy.destinationOffset(), value, copy.accessKind(), copy.getLocationIdentity())); return true; } else if (res instanceof ForeignCallNode) { @@ -131,7 +131,7 @@ foreign.setBci(b.bci()); } - res = b.append(res); + res = b.add(res); InputType inputType = InputType.Value; if (returnKind == Kind.Object && stamp instanceof ObjectStamp) { diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Fri Mar 27 13:29:08 2015 +0100 @@ -27,7 +27,6 @@ import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.nodes.*; import com.oracle.graal.replacements.nodes.MathIntrinsicNode.Operation; @@ -42,7 +41,6 @@ /** * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp). */ - @MacroSubstitution(macro = MathPowNode.class) @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. diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Fri Mar 27 13:29:08 2015 +0100 @@ -180,9 +180,9 @@ r.register1("reverseBytes", char.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { // return (char) (Integer.reverse(i) >> 16); - ReverseBytesNode reverse = b.append(new ReverseBytesNode(value)); - RightShiftNode rightShift = b.append(new RightShiftNode(reverse, b.append(ConstantNode.forInt(16)))); - ZeroExtendNode charCast = b.append(new ZeroExtendNode(b.append(new NarrowNode(rightShift, 16)), 32)); + ReverseBytesNode reverse = b.add(new ReverseBytesNode(value)); + RightShiftNode rightShift = b.add(new RightShiftNode(reverse, b.add(ConstantNode.forInt(16)))); + ZeroExtendNode charCast = b.add(new ZeroExtendNode(b.add(new NarrowNode(rightShift, 16)), 32)); b.push(Kind.Char.getStackKind(), b.recursiveAppend(charCast.canonical(null, value))); return true; } @@ -194,9 +194,9 @@ r.register1("reverseBytes", short.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { // return (short) (Integer.reverse(i) >> 16); - ReverseBytesNode reverse = b.append(new ReverseBytesNode(value)); - RightShiftNode rightShift = b.append(new RightShiftNode(reverse, b.append(ConstantNode.forInt(16)))); - SignExtendNode charCast = b.append(new SignExtendNode(b.append(new NarrowNode(rightShift, 16)), 32)); + ReverseBytesNode reverse = b.add(new ReverseBytesNode(value)); + RightShiftNode rightShift = b.add(new RightShiftNode(reverse, b.add(ConstantNode.forInt(16)))); + SignExtendNode charCast = b.add(new SignExtendNode(b.add(new NarrowNode(rightShift, 16)), 32)); b.push(Kind.Short.getStackKind(), b.recursiveAppend(charCast.canonical(null, value))); return true; } @@ -255,6 +255,17 @@ 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) { @@ -363,7 +374,7 @@ Registration r = new Registration(plugins, Class.class); r.register2("isInstance", Receiver.class, Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver type, ValueNode object) { - LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getConstantReflection(), type.get(), object)); + LogicNode condition = b.add(InstanceOfDynamicNode.create(b.getConstantReflection(), type.get(), object)); b.push(Kind.Boolean.getStackKind(), b.recursiveAppend(new ConditionalNode(condition).canonical(null))); return true; } @@ -375,18 +386,6 @@ return true; } }); - r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { - if (receiver.isConstant()) { - ResolvedJavaType type = b.getConstantReflection().asJavaType(receiver.get().asConstant()); - if (type != null && !type.isPrimitive()) { - b.addPush(Kind.Object, CheckCastNode.create(type, object, null, false, b.getAssumptions())); - return true; - } - } - return false; - } - }); } /** @@ -401,7 +400,7 @@ for (Class c : new Class[]{Node.class, NodeList.class}) { r.register2("get" + c.getSimpleName() + "Unsafe", Node.class, long.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode node, ValueNode offset) { - ValueNode value = b.append(new UnsafeLoadNode(node, offset, Kind.Object, LocationIdentity.any())); + ValueNode value = b.add(new UnsafeLoadNode(node, offset, Kind.Object, LocationIdentity.any())); boolean exactType = false; boolean nonNull = false; b.addPush(Kind.Object, new PiNode(value, metaAccess.lookupJavaType(c), exactType, nonNull)); @@ -493,11 +492,11 @@ // Emits a null-check for the otherwise unused receiver unsafe.get(); if (isVolatile) { - b.append(new MembarNode(JMM_PRE_VOLATILE_READ)); + b.add(new MembarNode(JMM_PRE_VOLATILE_READ)); } b.addPush(returnKind.getStackKind(), new UnsafeLoadNode(object, offset, returnKind, LocationIdentity.any())); if (isVolatile) { - b.append(new MembarNode(JMM_POST_VOLATILE_READ)); + b.add(new MembarNode(JMM_POST_VOLATILE_READ)); } return true; } @@ -516,7 +515,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode address, ValueNode value) { // Emits a null-check for the otherwise unused receiver unsafe.get(); - b.append(new DirectStoreNode(address, value, kind)); + b.add(new DirectStoreNode(address, value, kind)); return true; } @@ -524,11 +523,11 @@ // Emits a null-check for the otherwise unused receiver unsafe.get(); if (isVolatile) { - b.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + b.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); } b.add(new UnsafeStoreNode(object, offset, value, kind, LocationIdentity.any())); if (isVolatile) { - b.append(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + b.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); } return true; } @@ -538,14 +537,14 @@ Registration r = new Registration(plugins, GraalDirectives.class); r.register0("deoptimize", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + b.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register0("deoptimizeAndInvalidate", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); return true; } }); @@ -559,7 +558,7 @@ r.register0("controlFlowAnchor", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new ControlFlowAnchorNode()); + b.add(new ControlFlowAnchorNode()); return true; } }); @@ -573,7 +572,7 @@ InvocationPlugin blackholePlugin = new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.append(new BlackholeNode(value)); + b.add(new BlackholeNode(value)); return true; } }; @@ -598,7 +597,7 @@ InvocationPlugin blackholePlugin = new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver blackhole, ValueNode value) { blackhole.get(); - b.append(new BlackholeNode(value)); + b.add(new BlackholeNode(value)); return true; } }; diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java Fri Mar 27 13:29:08 2015 +0100 @@ -91,7 +91,7 @@ case NOT: assert args.length == 1; - b.addPush(returnStackKind, new XorNode(args[0], b.append(forIntegerKind(wordKind, -1)))); + b.addPush(returnStackKind, new XorNode(args[0], b.add(forIntegerKind(wordKind, -1)))); break; case READ_POINTER: @@ -158,7 +158,7 @@ case FROM_OBJECT: assert args.length == 1; - WordCastNode objectToWord = b.append(WordCastNode.objectToWord(args[0], wordKind)); + WordCastNode objectToWord = b.add(WordCastNode.objectToWord(args[0], wordKind)); b.push(returnStackKind, objectToWord); break; @@ -169,7 +169,7 @@ case TO_OBJECT: assert args.length == 1; - WordCastNode wordToObject = b.append(WordCastNode.wordToObject(args[0], wordKind)); + WordCastNode wordToObject = b.add(WordCastNode.wordToObject(args[0], wordKind)); b.push(returnStackKind, wordToObject); break; @@ -210,15 +210,15 @@ comparison = new IntegerLessThanNode(a, b); } - ConstantNode trueValue = graph.append(forInt(1)); - ConstantNode falseValue = graph.append(forInt(0)); + ConstantNode trueValue = graph.add(forInt(1)); + ConstantNode falseValue = graph.add(forInt(0)); if (condition.canonicalNegate()) { ConstantNode temp = trueValue; trueValue = falseValue; falseValue = temp; } - ConditionalNode materialize = graph.append(new ConditionalNode(graph.append(comparison), trueValue, falseValue)); + ConditionalNode materialize = graph.add(new ConditionalNode(graph.add(comparison), trueValue, falseValue)); return materialize; } @@ -231,7 +231,7 @@ } public static ValueNode readOp(GraphBuilderContext b, Kind readKind, ValueNode base, LocationNode location, BarrierType barrierType, boolean compressible) { - JavaReadNode read = b.append(new JavaReadNode(readKind, base, location, barrierType, compressible)); + JavaReadNode read = b.add(new JavaReadNode(readKind, base, location, barrierType, compressible)); /* * The read must not float outside its block otherwise it may float above an explicit zero * check on its base address. @@ -249,14 +249,14 @@ } public LocationNode makeLocation(GraphBuilderContext b, ValueNode offset, LocationIdentity locationIdentity) { - return b.append(new IndexedLocationNode(locationIdentity, 0, fromSigned(b, offset), 1)); + return b.add(new IndexedLocationNode(locationIdentity, 0, fromSigned(b, offset), 1)); } public LocationNode makeLocation(GraphBuilderContext b, ValueNode offset, ValueNode locationIdentity) { if (locationIdentity.isConstant()) { return makeLocation(b, offset, snippetReflection.asObject(LocationIdentity.class, locationIdentity.asJavaConstant())); } - return b.append(new SnippetLocationNode(snippetReflection, locationIdentity, b.append(ConstantNode.forLong(0)), fromSigned(b, offset), b.append(ConstantNode.forInt(1)))); + return b.add(new SnippetLocationNode(snippetReflection, locationIdentity, b.add(ConstantNode.forLong(0)), fromSigned(b, offset), b.add(ConstantNode.forInt(1)))); } public ValueNode fromUnsigned(GraphBuilderContext b, ValueNode value) { @@ -278,14 +278,14 @@ if (toKind == Kind.Int) { assert value.getKind() == Kind.Long; - return b.append(new NarrowNode(value, 32)); + return b.add(new NarrowNode(value, 32)); } else { assert toKind == Kind.Long; assert value.getKind().getStackKind() == Kind.Int; if (unsigned) { - return b.append(new ZeroExtendNode(value, 64)); + return b.add(new ZeroExtendNode(value, 64)); } else { - return b.append(new SignExtendNode(value, 64)); + return b.add(new SignExtendNode(value, 64)); } } } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicArrayCopyNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; @@ -36,8 +37,8 @@ public static final NodeClass TYPE = NodeClass.create(BasicArrayCopyNode.class); - public BasicArrayCopyNode(NodeClass c, Invoke invoke) { - super(c, invoke); + public BasicArrayCopyNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, invokeKind, targetMethod, bci, returnType, arguments); } protected ValueNode getSource() { diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BasicObjectCloneNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; @@ -40,8 +41,8 @@ public static final NodeClass TYPE = NodeClass.create(BasicObjectCloneNode.class); - protected BasicObjectCloneNode(NodeClass c, Invoke invoke) { - super(c, invoke); + public BasicObjectCloneNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, invokeKind, targetMethod, bci, returnType, arguments); } @Override diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -42,9 +42,8 @@ import com.oracle.graal.replacements.*; /** - * Macro nodes can be used to temporarily replace an invoke (usually by using the - * {@link MacroSubstitution} annotation). They can, for example, be used to implement constant - * folding for known JDK functions like {@link Class#isInterface()}.
+ * Macro nodes can be used to temporarily replace an invoke. They can, for example, be used to + * implement constant folding for known JDK functions like {@link Class#isInterface()}.
*
* During lowering, multiple sources are queried in order to look for a replacement: *
    @@ -77,6 +76,16 @@ this.invokeKind = methodCallTarget.invokeKind(); } + protected MacroNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, StampFactory.forKind(returnType.getKind())); + assert targetMethod.getSignature().getParameterCount(!targetMethod.isStatic()) == arguments.length; + this.arguments = new NodeInputList<>(this, arguments); + this.bci = bci; + this.targetMethod = targetMethod; + this.returnType = returnType; + this.invokeKind = invokeKind; + } + public int getBci() { return bci; } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroStateSplitNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; @@ -41,9 +42,8 @@ public static final NodeClass TYPE = NodeClass.create(MacroStateSplitNode.class); @OptionalInput(InputType.State) protected FrameState stateAfter; - public MacroStateSplitNode(NodeClass c, Invoke invoke) { - super(c, invoke); - this.stateAfter = invoke.stateAfter(); + protected MacroStateSplitNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, invokeKind, targetMethod, bci, returnType, arguments); } @Override diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -22,28 +22,34 @@ */ 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(Invoke i) { - super(TYPE, i); + 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) { - if (forX.isConstant() && forY.isConstant()) { - double x = forX.asJavaConstant().asDouble(); - double y = forY.asJavaConstant().asDouble(); - return ConstantNode.forDouble(Math.pow(x, y)); - } else { - return this; + 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() { diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/PureFunctionMacroNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; /** * This node class can be used to create {@link MacroNode}s for simple pure functions like @@ -37,8 +38,8 @@ public static final NodeClass TYPE = NodeClass.create(PureFunctionMacroNode.class); - protected PureFunctionMacroNode(NodeClass c, Invoke invoke) { - super(c, invoke); + public PureFunctionMacroNode(NodeClass c, InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode... arguments) { + super(c, invokeKind, targetMethod, bci, returnType, arguments); } /** diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Fri Mar 27 13:29:08 2015 +0100 @@ -162,7 +162,7 @@ public boolean apply(GraphBuilderContext builder, ResolvedJavaField staticField) { if (TruffleCompilerOptions.TruffleExcludeAssertions.getValue() && staticField.getName().equals("$assertionsDisabled")) { - ConstantNode trueNode = builder.append(ConstantNode.forBoolean(true)); + ConstantNode trueNode = builder.add(ConstantNode.forBoolean(true)); builder.addPush(trueNode); return true; } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Fri Mar 27 13:29:08 2015 +0100 @@ -31,8 +31,6 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.truffle.substitutions.*; -import com.oracle.truffle.api.*; /** * Custom {@link Replacements} for Truffle compilation. @@ -44,15 +42,6 @@ protected TruffleReplacements(Providers providers, SnippetReflectionProvider snippetReflection) { super(providers, snippetReflection, providers.getCodeCache().getTarget()); this.graalReplacements = providers.getReplacements(); - - registerTruffleSubstitutions(); - } - - protected void registerTruffleSubstitutions() { - if (!TruffleCompilerOptions.FastPE.getValue()) { - registerSubstitutions(CompilerAsserts.class, CompilerAssertsSubstitutions.class); - registerSubstitutions(OptimizedAssumption.class, OptimizedAssumptionSubstitutions.class); - } } @Override diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/AssumptionNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +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.truffle.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.common.*; -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.spi.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.truffle.*; - -@NodeInfo -public final class AssumptionNode extends MacroNode implements Simplifiable { - - public static final NodeClass TYPE = NodeClass.create(AssumptionNode.class); - - public AssumptionNode(Invoke invoke) { - super(TYPE, invoke); - assert super.arguments.size() == 1; - } - - private ValueNode getAssumption() { - return arguments.first(); - } - - private static SnippetReflectionProvider getSnippetReflection() { - /* - * This class requires access to the objects encapsulated in Constants, and therefore breaks - * the compiler-VM separation of object constants. - */ - return Graal.getRequiredCapability(SnippetReflectionProvider.class); - } - - @Override - public void lower(LoweringTool tool) { - throw new GraalInternalError(GraphUtil.approxSourceException(this, new RuntimeException("assumption could not be evaluated to a constant"))); - } - - @Override - public void simplify(SimplifierTool tool) { - ValueNode assumption = getAssumption(); - Assumptions assumptions = graph().getAssumptions(); - if (assumption.isConstant()) { - JavaConstant c = assumption.asJavaConstant(); - assert c.getKind() == Kind.Object; - Object object = getSnippetReflection().asObject(Object.class, c); - OptimizedAssumption assumptionObject = (OptimizedAssumption) object; - StructuredGraph graph = graph(); - if (assumptionObject.isValid()) { - assumptions.record(new AssumptionValidAssumption(assumptionObject)); - if (super.getReturnType().getKind() == Kind.Boolean) { - graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(true, graph())); - } else { - graph.removeFixed(this); - } - } else { - if (super.getReturnType().getKind() == Kind.Boolean) { - graph.replaceFixedWithFloating(this, ConstantNode.forBoolean(false, graph())); - } else { - tool.deleteBranch(this.next()); - this.replaceAndDelete(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None))); - } - } - } - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverInlineMacroNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +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.truffle.nodes.asserts; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.replacements.nodes.*; - -@NodeInfo -public final class NeverInlineMacroNode extends MacroStateSplitNode implements com.oracle.graal.graph.IterableNodeType { - - public static final NodeClass TYPE = NodeClass.create(NeverInlineMacroNode.class); - - public NeverInlineMacroNode(Invoke invoke) { - super(TYPE, invoke); - } - - @Override - public void lower(LoweringTool tool) { - InvokeNode invoke = createInvoke(); - graph().replaceFixedWithFixed(this, invoke); - invoke.setUseForInlining(false); - invoke.lower(tool); - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/asserts/NeverPartOfCompilationNode.java Fri Mar 27 13:29:08 2015 +0100 @@ -49,7 +49,4 @@ throw GraphUtil.approxSourceException(neverPartOfCompilationNode, exception); } } - - @NodeIntrinsic - public static native void apply(@ConstantNodeParameter String message); } diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +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.truffle.nodes.typesystem; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.calc.*; -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.calc.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.truffle.nodes.*; - -/** - * Macro node for CompilerDirectives#unsafeGetInt*. - */ -@NodeInfo -public final class CustomizedUnsafeLoadMacroNode extends MacroStateSplitNode implements Canonicalizable { - public static final NodeClass TYPE = NodeClass.create(CustomizedUnsafeLoadMacroNode.class); - - private static final int ARGUMENT_COUNT = 4; - private static final int OBJECT_ARGUMENT_INDEX = 0; - private static final int OFFSET_ARGUMENT_INDEX = 1; - private static final int CONDITION_ARGUMENT_INDEX = 2; - private static final int LOCATION_ARGUMENT_INDEX = 3; - - public CustomizedUnsafeLoadMacroNode(Invoke invoke) { - super(TYPE, invoke); - assert arguments.size() == ARGUMENT_COUNT; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode locationArgument = arguments.get(LOCATION_ARGUMENT_INDEX); - if (locationArgument.isConstant()) { - ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX); - ValueNode offsetArgument = arguments.get(OFFSET_ARGUMENT_INDEX); - ValueNode conditionArgument = arguments.get(CONDITION_ARGUMENT_INDEX); - LocationIdentity locationIdentity; - if (locationArgument.isNullConstant()) { - locationIdentity = LocationIdentity.any(); - } else { - locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); - } - LogicNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true), tool.getConstantReflection()); - Kind returnKind = this.getTargetMethod().getSignature().getReturnKind(); - return new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare); - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeStoreMacroNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +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.truffle.nodes.typesystem; - -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.extended.*; -import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.truffle.nodes.*; - -/** - * Macro node for method CompilerDirectives#unsafePut*. - */ -@NodeInfo -public final class CustomizedUnsafeStoreMacroNode extends MacroStateSplitNode implements Canonicalizable, StateSplit { - public static final NodeClass TYPE = NodeClass.create(CustomizedUnsafeStoreMacroNode.class); - private static final int ARGUMENT_COUNT = 4; - private static final int OBJECT_ARGUMENT_INDEX = 0; - private static final int OFFSET_ARGUMENT_INDEX = 1; - private static final int VALUE_ARGUMENT_INDEX = 2; - private static final int LOCATION_ARGUMENT_INDEX = 3; - - public CustomizedUnsafeStoreMacroNode(Invoke invoke) { - super(TYPE, invoke); - assert arguments.size() == ARGUMENT_COUNT; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - ValueNode locationArgument = arguments.get(LOCATION_ARGUMENT_INDEX); - if (locationArgument.isConstant()) { - ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX); - ValueNode offsetArgument = arguments.get(OFFSET_ARGUMENT_INDEX); - ValueNode valueArgument = arguments.get(VALUE_ARGUMENT_INDEX); - LocationIdentity locationIdentity; - if (locationArgument.isNullConstant()) { - locationIdentity = LocationIdentity.any(); - } else { - locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); - } - - return new UnsafeStoreNode(objectArgument, offsetArgument, valueArgument, this.getTargetMethod().getSignature().getParameterKind(VALUE_ARGUMENT_INDEX), locationIdentity, stateAfter()); - } - return this; - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +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.truffle.nodes.typesystem; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.calc.*; -import com.oracle.graal.compiler.common.type.*; -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.calc.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * Macro node for method CompilerDirectives#unsafeCast. - */ -@NodeInfo -public final class UnsafeTypeCastMacroNode extends MacroStateSplitNode implements Simplifiable { - - public static final NodeClass TYPE = NodeClass.create(UnsafeTypeCastMacroNode.class); - private static final int OBJECT_ARGUMENT_INDEX = 0; - private static final int CLASS_ARGUMENT_INDEX = 1; - private static final int CONDITION_ARGUMENT_INDEX = 2; - private static final int NONNULL_ARGUMENT_INDEX = 3; - private static final int ARGUMENT_COUNT = 4; - - public UnsafeTypeCastMacroNode(Invoke invoke) { - super(TYPE, invoke); - assert arguments.size() == ARGUMENT_COUNT; - } - - @Override - public void simplify(SimplifierTool tool) { - ValueNode classArgument = arguments.get(CLASS_ARGUMENT_INDEX); - ValueNode nonNullArgument = arguments.get(NONNULL_ARGUMENT_INDEX); - if (classArgument.isConstant() && nonNullArgument.isConstant()) { - ValueNode objectArgument = arguments.get(OBJECT_ARGUMENT_INDEX); - ValueNode conditionArgument = arguments.get(CONDITION_ARGUMENT_INDEX); - ResolvedJavaType lookupJavaType = tool.getConstantReflection().asJavaType(classArgument.asConstant()); - tool.addToWorkList(usages()); - if (lookupJavaType == null) { - replaceAtUsages(objectArgument); - GraphUtil.removeFixedWithUnusedInputs(this); - } else { - Stamp piStamp = StampFactory.declaredTrusted(lookupJavaType, nonNullArgument.asJavaConstant().asInt() != 0); - ConditionAnchorNode valueAnchorNode = graph().add( - new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()), tool.getConstantReflection()))); - PiNode piCast = graph().unique(new PiNode(objectArgument, piStamp, valueAnchorNode)); - replaceAtUsages(piCast); - graph().replaceFixedWithFixed(this, valueAnchorNode); - } - } - } -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/CompilerAssertsSubstitutions.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2013, 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.truffle.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.truffle.nodes.asserts.*; -import com.oracle.truffle.api.*; - -@ClassSubstitution(CompilerAsserts.class) -public class CompilerAssertsSubstitutions { - - @MethodSubstitution - public static void neverPartOfCompilation(@SuppressWarnings("unused") String message) { - NeverPartOfCompilationNode.apply("Never part of compilation"); - } - -} diff -r c1f116cd4b67 -r 8470e81631f8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/OptimizedAssumptionSubstitutions.java Fri Mar 27 00:41:11 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2013, 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.truffle.substitutions; - -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.nodes.*; - -@ClassSubstitution(OptimizedAssumption.class) -public class OptimizedAssumptionSubstitutions { - - @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true) - public static native void check(OptimizedAssumption assumption); - - @MacroSubstitution(macro = AssumptionNode.class, isStatic = false, forced = true) - public static native boolean isValid(OptimizedAssumption assumption); -} diff -r c1f116cd4b67 -r 8470e81631f8 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 Fri Mar 27 00:41:11 2015 -0700 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Fri Mar 27 13:29:08 2015 +0100 @@ -55,6 +55,7 @@ registerOptimizedAssumptionPlugins(plugins); registerExactMathPlugins(plugins); registerCompilerDirectivesPlugins(plugins); + registerCompilerAssertsPlugins(plugins); registerOptimizedCallTargetPlugins(metaAccess, plugins); registerUnsafeAccessImplPlugins(plugins); @@ -68,21 +69,34 @@ public static void registerOptimizedAssumptionPlugins(InvocationPlugins plugins) { Registration r = new Registration(plugins, OptimizedAssumption.class); - r.register1("isValid", Receiver.class, new InvocationPlugin() { + 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); - b.addPush(Kind.Boolean.getStackKind(), ConstantNode.forBoolean(assumption.isValid())); if (assumption.isValid()) { + if (targetMethod.getName().equals("isValid")) { + b.addPush(ConstantNode.forBoolean(true)); + } else { + assert targetMethod.getName().equals("check") : targetMethod; + } b.getAssumptions().record(new AssumptionValidAssumption(assumption)); + } else { + if (targetMethod.getName().equals("isValid")) { + b.addPush(ConstantNode.forBoolean(false)); + } else { + assert targetMethod.getName().equals("check") : targetMethod; + b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.None)); + } } } else { throw b.bailout("assumption could not be reduced to a constant"); } return true; } - }); + }; + r.register1("isValid", Receiver.class, plugin); + r.register1("check", Receiver.class, plugin); } public static void registerExactMathPlugins(InvocationPlugins plugins) { @@ -138,13 +152,13 @@ }); r.register0("transferToInterpreter", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + b.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); return true; } }); r.register0("transferToInterpreterAndInvalidate", new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - b.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + b.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); return true; } }); @@ -184,12 +198,14 @@ }); r.register1("materialize", Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.append(new ForceMaterializeNode(value)); + b.add(new ForceMaterializeNode(value)); return true; } }); + } - r = new Registration(plugins, CompilerAsserts.class); + public static void registerCompilerAssertsPlugins(InvocationPlugins plugins) { + Registration r = new Registration(plugins, CompilerAsserts.class); r.register1("partialEvaluationConstant", Object.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { ValueNode curValue = value; @@ -219,7 +235,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode message) { if (message.isConstant()) { String messageString = message.asConstant().toValueString(); - b.append(new NeverPartOfCompilationNode(messageString)); + b.add(new NeverPartOfCompilationNode(messageString)); return true; } throw b.bailout("message for never part of compilation is non-constant"); @@ -301,7 +317,7 @@ } ConditionAnchorNode valueAnchorNode = null; if (!skipAnchor) { - valueAnchorNode = b.append(new ConditionAnchorNode(compareNode)); + valueAnchorNode = b.add(new ConditionAnchorNode(compareNode)); } b.addPush(Kind.Object, new PiNode(object, piStamp, valueAnchorNode)); } @@ -339,8 +355,8 @@ } else { locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); } - LogicNode compare = b.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), b.getConstantReflection())); - b.addPush(returnKind.getStackKind(), b.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); + LogicNode compare = b.add(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), b.getConstantReflection())); + b.addPush(returnKind.getStackKind(), b.add(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); return true; } // TODO: should we throw GraalInternalError.shouldNotReachHere() here?