changeset 19178:c8091ec0fdc0

added graph builder plugins for FrameWithoutBoxing
author Doug Simon <doug.simon@oracle.com>
date Fri, 06 Feb 2015 17:59:24 +0100
parents 1a7b33c96c0d
children df3561f7c9ad
files graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java
diffstat 4 files changed, 154 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java	Fri Feb 06 17:59:24 2015 +0100
@@ -47,6 +47,8 @@
 
     Assumptions getAssumptions();
 
+    ConstantReflectionProvider getConstantReflection();
+
     void push(Kind kind, ValueNode value);
 
     /**
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Feb 06 17:59:24 2015 +0100
@@ -37,8 +37,8 @@
 import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.*;
-import com.oracle.graal.graph.Graph.Mark;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.iterators.*;
 import com.oracle.graal.java.BciBlockMapping.BciBlock;
@@ -1659,6 +1659,7 @@
             }
 
             public void push(Kind kind, ValueNode value) {
+                assert kind == kind.getStackKind();
                 frameState.push(kind, value);
             }
 
@@ -1669,6 +1670,11 @@
                     return this.explodeLoopsContext.peek().peelIteration;
                 }
             }
+
+            public ConstantReflectionProvider getConstantReflection() {
+                return constantReflectionProvider;
+            }
+
         }
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Fri Feb 06 17:59:24 2015 +0100
@@ -94,6 +94,13 @@
         }
 
         /**
+         * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[])
+         */
+        default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) {
+            throw invalidHandler(builder, arg1, arg2, arg3, arg4);
+        }
+
+        /**
          * Executes a given plugin against a set of invocation arguments by dispatching to the
          * plugin's {@code apply(...)} method that matches the number of arguments.
          *
@@ -111,6 +118,8 @@
                 return plugin.apply(builder, args[0], args[1]);
             } else if (args.length == 3) {
                 return plugin.apply(builder, args[0], args[1], args[2]);
+            } else if (args.length == 4) {
+                return plugin.apply(builder, args[0], args[1], args[2], args[3]);
             } else {
                 throw plugin.invalidHandler(builder, args);
             }
@@ -200,6 +209,17 @@
         }
 
         /**
+         * Registers a plugin for a method with 4 arguments.
+         *
+         * @param name the name of the method
+         * @param plugin the plugin to be registered
+         */
+        public void register4(String name, Class<?> arg1, Class<?> arg2, Class<?> arg3, Class<?> arg4, InvocationPlugin plugin) {
+            ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4);
+            plugins.register(method, plugin);
+        }
+
+        /**
          * Resolves a method given a declaring class, name and parameter types.
          */
         public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class<?> declaringClass, String name, Class<?>... parameterTypes) {
@@ -212,11 +232,27 @@
     }
 
     public static class InvocationPluginChecker {
-        static final Class<?>[] APPLY0 = {GraphBuilderContext.class};
-        static final Class<?>[] APPLY1 = {GraphBuilderContext.class, ValueNode.class};
-        static final Class<?>[] APPLY2 = {GraphBuilderContext.class, ValueNode.class, ValueNode.class};
-        static final Class<?>[] APPLY3 = {GraphBuilderContext.class, ValueNode.class, ValueNode.class, ValueNode.class};
-        static final Class<?>[][] SIGS = {APPLY0, APPLY1, APPLY2, APPLY3};
+        /**
+         * The set of all {@link InvocationPlugin#apply} method signatures.
+         */
+        static final Class<?>[][] SIGS;
+        static {
+            ArrayList<Class<?>[]> sigs = new ArrayList<>(5);
+            for (Method method : InvocationPlugin.class.getDeclaredMethods()) {
+                if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) {
+                    Class<?>[] sig = method.getParameterTypes();
+                    assert sig[0] == GraphBuilderContext.class;
+                    assert Arrays.asList(Arrays.copyOfRange(sig, 1, sig.length)).stream().allMatch(c -> c == ValueNode.class);
+                    while (sigs.size() < sig.length) {
+                        sigs.add(null);
+                    }
+                    sigs.set(sig.length - 1, sig);
+                }
+            }
+            assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null),
+                            ValueNode.class.getSimpleName());
+            SIGS = sigs.toArray(new Class<?>[sigs.size()][]);
+        }
 
         public static boolean check(ResolvedJavaMethod method, InvocationPlugin plugin) {
             int arguments = method.getSignature().getParameterCount(!method.isStatic());
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java	Fri Feb 06 16:49:34 2015 +0100
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java	Fri Feb 06 17:59:24 2015 +0100
@@ -22,17 +22,23 @@
  */
 package com.oracle.graal.truffle.substitutions;
 
+import static java.lang.Character.*;
+
 import java.util.concurrent.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
+import com.oracle.graal.compiler.common.calc.*;
 import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.java.*;
 import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin;
 import com.oracle.graal.java.GraphBuilderPlugins.Registration;
+import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.truffle.*;
+import com.oracle.graal.truffle.nodes.*;
 import com.oracle.graal.truffle.nodes.frame.*;
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.frame.*;
@@ -43,14 +49,7 @@
 public class TruffleGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider {
     public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
 
-        Registration r2 = new Registration(plugins, metaAccess, OptimizedCallTarget.class);
-        r2.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() {
-            public boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) {
-                builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(FrameWithoutBoxing.class)), arg1, arg2)));
-                return true;
-            }
-        });
-
+        // CompilerDirectives.class
         Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class);
         r.register0("inInterpreter", new InvocationPlugin() {
             public boolean apply(GraphBuilderContext builder) {
@@ -115,5 +114,102 @@
                 return true;
             }
         });
+
+        // OptimizedCallTarget.class
+        r = new Registration(plugins, metaAccess, OptimizedCallTarget.class);
+        r.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) {
+                builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(FrameWithoutBoxing.class)), arg1, arg2)));
+                return true;
+            }
+        });
+
+        // FrameWithoutBoxing.class
+        r = new Registration(plugins, metaAccess, FrameWithoutBoxing.class);
+        r.register1("materialize", Receiver.class, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext builder, ValueNode frame) {
+                builder.append(new MaterializeFrameNode(frame));
+                return true;
+            }
+        });
+        r.register4("unsafeCast", Object.class, Class.class, boolean.class, boolean.class, new InvocationPlugin() {
+            public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull) {
+                if (clazz.isConstant() && nonNull.isConstant()) {
+                    ConstantReflectionProvider constantReflection = builder.getConstantReflection();
+                    ResolvedJavaType javaType = constantReflection.asJavaType(clazz.asConstant());
+                    if (javaType == null) {
+                        builder.push(Kind.Object, object);
+                    } else {
+                        Stamp piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0);
+                        ConditionAnchorNode valueAnchorNode = builder.append(new ConditionAnchorNode(CompareNode.createCompareNode(object.graph(), Condition.EQ, condition,
+                                        ConstantNode.forBoolean(true, object.graph()))));
+                        PiNode piCast = builder.append(new PiNode(object, piStamp, valueAnchorNode));
+                        builder.push(Kind.Object, piCast);
+                    }
+                    return true;
+                }
+                // TODO: should we throw GraalInternalError.shouldNotReachHere() here?
+                return false;
+            }
+        });
+        for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}) {
+            String kindName = kind.getJavaName();
+            kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1);
+            String getName = "unsafeGet" + kindName;
+            String putName = "unsafePut" + kindName;
+            r.register4(getName, Object.class, long.class, boolean.class, Object.class, new CustomizedUnsafeLoadPlugin(kind));
+            r.register4(putName, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), Object.class, new CustomizedUnsafeStorePlugin(kind));
+        }
+    }
+
+    static class CustomizedUnsafeLoadPlugin implements InvocationPlugin {
+
+        private final Kind returnKind;
+
+        public CustomizedUnsafeLoadPlugin(Kind returnKind) {
+            this.returnKind = returnKind;
+        }
+
+        public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode offset, ValueNode condition, ValueNode location) {
+            if (location.isConstant()) {
+                LocationIdentity locationIdentity;
+                if (location.isNullConstant()) {
+                    locationIdentity = LocationIdentity.ANY_LOCATION;
+                } else {
+                    locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant());
+                }
+                CompareNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph())));
+                builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare)));
+                return true;
+            }
+            // TODO: should we throw GraalInternalError.shouldNotReachHere() here?
+            return false;
+        }
+    }
+
+    static class CustomizedUnsafeStorePlugin implements InvocationPlugin {
+
+        private final Kind kind;
+
+        public CustomizedUnsafeStorePlugin(Kind kind) {
+            this.kind = kind;
+        }
+
+        public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode offset, ValueNode value, ValueNode location) {
+            ValueNode locationArgument = location;
+            if (locationArgument.isConstant()) {
+                LocationIdentity locationIdentity;
+                if (locationArgument.isNullConstant()) {
+                    locationIdentity = LocationIdentity.ANY_LOCATION;
+                } else {
+                    locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant());
+                }
+
+                builder.append(new UnsafeStoreNode(object, offset, value, kind, locationIdentity, null));
+                return true;
+            }
+            // TODO: should we throw GraalInternalError.shouldNotReachHere() here?
+            return false;
+        }
     }
 }