changeset 19071:cc1020cc0599

Merge.
author Doug Simon <doug.simon@oracle.com>
date Mon, 02 Feb 2015 22:50:17 +0100
parents 69f2926cd2ab (diff) b4056d536237 (current diff)
children deb2467530e4
files graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformHighPhase.java graal/com.oracle.graal.loop/src/com/oracle/graal/loop/phases/LoopTransformLowPhase.java
diffstat 7 files changed, 233 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java	Mon Feb 02 11:51:06 2015 -0800
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java	Mon Feb 02 22:50:17 2015 +0100
@@ -29,12 +29,18 @@
 import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.spi.*;
 
+/**
+ * Provider of HotSpot specific {@link GraphBuilderPlugin}s.
+ */
 @ServiceProvider(GraphBuilderPluginsProvider.class)
 public class HotSpotGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider {
     public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
         plugins.register(metaAccess, ObjectPlugin.class);
     }
 
+    /**
+     * HotSpot specific plugins for {@link Object}.
+     */
     enum ObjectPlugin implements GraphBuilderPlugin {
         getClass() {
             public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
@@ -52,10 +58,5 @@
         public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) {
             return GraphBuilderPlugin.resolveTarget(metaAccess, Object.class, name());
         }
-
-        @Override
-        public String toString() {
-            return Object.class.getName() + "." + name() + "()";
-        }
     }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPluginsProvider.java	Mon Feb 02 11:51:06 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultGraphBuilderPluginsProvider.java	Mon Feb 02 22:50:17 2015 +0100
@@ -22,41 +22,31 @@
  */
 package com.oracle.graal.java;
 
-import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.runtime.*;
-import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
 import com.oracle.graal.nodes.java.*;
 
+/**
+ * Provider of non-runtime specific {@link GraphBuilderPlugin}s.
+ */
 @ServiceProvider(GraphBuilderPluginsProvider.class)
 public class DefaultGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider {
     public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
         plugins.register(metaAccess, ObjectPlugin.class);
+        plugins.register(metaAccess, BoxingPlugin.class);
     }
 
+    /**
+     * Plugins for {@link Object}.
+     */
     enum ObjectPlugin implements GraphBuilderPlugin {
         init() {
             public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
-                assert args.length == 1;
-                ValueNode rcvr = args[0];
-                ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp();
-
-                boolean needsCheck = true;
-                if (objectStamp.isExactType()) {
-                    needsCheck = objectStamp.type().hasFinalizer();
-                } else if (objectStamp.type() != null && !objectStamp.type().hasFinalizableSubclass()) {
-                    // if either the declared type of receiver or the holder
-                    // can be assumed to have no finalizers
-                    Assumptions assumptions = builder.getAssumptions();
-                    if (assumptions.useOptimisticAssumptions()) {
-                        assumptions.recordNoFinalizableSubclassAssumption(objectStamp.type());
-                        needsCheck = false;
-                    }
-                }
-
-                if (needsCheck) {
-                    builder.append(new RegisterFinalizerNode(rcvr));
+                ValueNode object = args[0];
+                if (RegisterFinalizerNode.mayHaveFinalizer(object, builder.getAssumptions())) {
+                    builder.append(new RegisterFinalizerNode(object));
                 }
                 return true;
             }
@@ -71,4 +61,50 @@
             return Object.class.getName() + "." + name() + "()";
         }
     }
+
+    /**
+     * Plugins for the standard primitive box classes (e.g., {@link Integer} and friends).
+     */
+    enum BoxingPlugin implements GraphBuilderPlugin {
+        valueOf$Boolean(Kind.Boolean),
+        booleanValue$Boolean(Kind.Boolean),
+        valueOf$Byte(Kind.Byte),
+        byteValue$Byte(Kind.Byte),
+        valueOf$Short(Kind.Short),
+        shortValue$Short(Kind.Short),
+        valueOf$Char(Kind.Char),
+        charValue$Char(Kind.Char),
+        valueOf$Int(Kind.Int),
+        intValue$Int(Kind.Int),
+        valueOf$Long(Kind.Long),
+        longValue$Long(Kind.Long),
+        valueOf$Float(Kind.Float),
+        floatValue$Float(Kind.Float),
+        valueOf$Double(Kind.Double),
+        doubleValue$Double(Kind.Double);
+
+        BoxingPlugin(Kind kind) {
+            assert name().startsWith("valueOf$") || name().startsWith(kind.getJavaName() + "Value$");
+            this.kind = kind;
+            this.box = name().charAt(0) == 'v';
+        }
+
+        private final Kind kind;
+        private final boolean box;
+
+        public final boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+            if (box) {
+                ResolvedJavaType resultType = builder.getMetaAccess().lookupJavaType(kind.toBoxedJavaClass());
+                builder.push(Kind.Object, builder.append(new BoxNode(args[0], resultType, kind)));
+            } else {
+                builder.push(kind, builder.append(new UnboxNode(args[0], kind)));
+            }
+            return true;
+        }
+
+        public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) {
+            Class<?>[] parameterTypes = box ? new Class<?>[]{kind.toJavaClass()} : new Class<?>[0];
+            return GraphBuilderPlugin.resolveTarget(metaAccess, kind.toBoxedJavaClass(), name(), parameterTypes);
+        }
+    }
 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Feb 02 11:51:06 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Mon Feb 02 22:50:17 2015 +0100
@@ -775,9 +775,13 @@
                     if (graphBuilderPlugins != null) {
                         GraphBuilderPlugin plugin = graphBuilderPlugins.getPlugin(targetMethod);
                         if (plugin != null) {
+                            int beforeStackSize = frameState.stackSize;
                             if (plugin.handleInvocation(this, args)) {
+                                // System.out.println("used plugin: " + plugin);
+                                assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize;
                                 return;
                             }
+                            assert beforeStackSize == frameState.stackSize;
                         }
                     }
 
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java	Mon Feb 02 11:51:06 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugin.java	Mon Feb 02 22:50:17 2015 +0100
@@ -42,14 +42,21 @@
     boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args);
 
     /**
-     * Gets the target method handled by {@link #handleInvocation(GraphBuilderContext, ValueNode[])}
-     * .
+     * Gets the method handled by {@link #handleInvocation(GraphBuilderContext, ValueNode[])} .
      */
     ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess);
 
-    static ResolvedJavaMethod resolveTarget(MetaAccessProvider metaAccess, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
+    /**
+     * Looks up a {@link ResolvedJavaMethod}.
+     *
+     * @param methodNameBase the name of the method is the prefix of this value up to the first '$'
+     *            character
+     */
+    static ResolvedJavaMethod resolveTarget(MetaAccessProvider metaAccess, Class<?> declaringClass, String methodNameBase, Class<?>... parameterTypes) {
+        int index = methodNameBase.indexOf('$');
+        String methodName = index == -1 ? methodNameBase : methodNameBase.substring(0, index);
         try {
-            return metaAccess.lookupJavaMethod(methodName.equals("<init>") ? clazz.getDeclaredConstructor(parameterTypes) : clazz.getDeclaredMethod(methodName, parameterTypes));
+            return metaAccess.lookupJavaMethod(methodName.equals("<init>") ? declaringClass.getDeclaredConstructor(parameterTypes) : declaringClass.getDeclaredMethod(methodName, parameterTypes));
         } catch (NoSuchMethodException | SecurityException e) {
             throw new GraalInternalError(e);
         }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Mon Feb 02 11:51:06 2015 -0800
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java	Mon Feb 02 22:50:17 2015 +0100
@@ -44,6 +44,7 @@
             GraphBuilderPlugin gbp = (GraphBuilderPlugin) o;
             ResolvedJavaMethod target = gbp.getInvocationTarget(metaAccess);
             GraphBuilderPlugin oldValue = map.put(target, gbp);
+            // System.out.println("registered: " + gbp);
             assert oldValue == null;
         }
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Feb 02 11:51:06 2015 -0800
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java	Mon Feb 02 22:50:17 2015 +0100
@@ -56,27 +56,31 @@
         gen.getLIRGeneratorTool().emitForeignCall(linkage, gen.state(this), gen.operand(getValue()));
     }
 
+    /**
+     * Determines if the compiler should emit code to test whether a given object has a finalizer
+     * that must be registered with the runtime upon object initialization.
+     */
+    public static boolean mayHaveFinalizer(ValueNode object, Assumptions assumptions) {
+        ObjectStamp objectStamp = (ObjectStamp) object.stamp();
+        if (objectStamp.isExactType()) {
+            return objectStamp.type().hasFinalizer();
+        } else if (objectStamp.type() != null && !objectStamp.type().hasFinalizableSubclass()) {
+            // if either the declared type of receiver or the holder
+            // can be assumed to have no finalizers
+            if (assumptions.useOptimisticAssumptions()) {
+                assumptions.recordNoFinalizableSubclassAssumption(objectStamp.type());
+                return false;
+            }
+        }
+        return true;
+    }
+
     @Override
     public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
         if (!(forValue.stamp() instanceof ObjectStamp)) {
             return this;
         }
-
-        ObjectStamp objectStamp = (ObjectStamp) forValue.stamp();
-
-        boolean needsCheck = true;
-        if (objectStamp.isExactType()) {
-            needsCheck = objectStamp.type().hasFinalizer();
-        } else if (objectStamp.type() != null && !objectStamp.type().hasFinalizableSubclass()) {
-            // if either the declared type of receiver or the holder
-            // can be assumed to have no finalizers
-            if (tool.assumptions().useOptimisticAssumptions()) {
-                tool.assumptions().recordNoFinalizableSubclassAssumption(objectStamp.type());
-                needsCheck = false;
-            }
-        }
-
-        if (!needsCheck) {
+        if (!mayHaveFinalizer(forValue, tool.assumptions())) {
             return null;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java	Mon Feb 02 22:50:17 2015 +0100
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.truffle.substitutions;
+
+import java.util.concurrent.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.truffle.nodes.frame.*;
+import com.oracle.truffle.api.*;
+
+/**
+ * Provider of {@link GraphBuilderPlugin}s for Truffle classes.
+ */
+@ServiceProvider(GraphBuilderPluginsProvider.class)
+public class TruffleGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider {
+    public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) {
+        plugins.register(metaAccess, CompilerDirectivesPlugin.class);
+    }
+
+    /**
+     * Plugins for {@link CompilerDirectives}.
+     */
+    enum CompilerDirectivesPlugin implements GraphBuilderPlugin {
+        inInterpreter() {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                builder.append(ConstantNode.forBoolean(false));
+                return true;
+            }
+        },
+        inCompiledCode() {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                builder.append(ConstantNode.forBoolean(true));
+                return true;
+            }
+        },
+        transferToInterpreter() {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter));
+                return true;
+            }
+        },
+        transferToInterpreterAndInvalidate() {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter));
+                return true;
+            }
+        },
+        interpreterOnly(Runnable.class) {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                return true;
+            }
+        },
+        interpreterOnly$(Callable.class) {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                return true;
+            }
+        },
+        injectBranchProbability(double.class, boolean.class) {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                ValueNode probability = args[0];
+                ValueNode condition = args[1];
+                builder.append(new BranchProbabilityNode(probability, condition));
+                return true;
+            }
+        },
+        bailout(String.class) {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                // TODO: is this too eager? Should a BailoutNode be created instead?
+                ValueNode message = args[0];
+                if (message.isConstant()) {
+                    throw new BailoutException(message.asConstant().toValueString());
+                }
+                throw new BailoutException("bailout (message is not compile-time constant, so no additional information is available)");
+            }
+        },
+
+        isCompilationConstant(Object.class) {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                ValueNode arg0 = args[0];
+                if (arg0 instanceof BoxNode) {
+                    arg0 = ((BoxNode) arg0).getValue();
+                }
+                if (arg0.isConstant()) {
+                    builder.push(Kind.Boolean, builder.append(ConstantNode.forBoolean(true)));
+                    return true;
+                }
+
+                // Cannot create MacroNodes in a plugin (yet)
+                return false;
+            }
+        },
+        materialize(Object.class) {
+            public boolean handleInvocation(GraphBuilderContext builder, ValueNode[] args) {
+                builder.append(new ForceMaterializeNode(args[0]));
+                return true;
+            }
+        };
+
+        CompilerDirectivesPlugin(Class<?>... parameterTypes) {
+            this.parameterTypes = parameterTypes;
+        }
+
+        private final Class<?>[] parameterTypes;
+
+        public ResolvedJavaMethod getInvocationTarget(MetaAccessProvider metaAccess) {
+            return GraphBuilderPlugin.resolveTarget(metaAccess, CompilerDirectives.class, name(), parameterTypes);
+        }
+    }
+}