changeset 21918:0ab08be12bbb

Merge
author Stefan Anzinger <stefan.anzinger@oracle.com>
date Thu, 11 Jun 2015 11:35:55 +0200
parents 0df6a0cb4b5f (current diff) 9fed54b2b98f (diff)
children 62da3906ab7f
files
diffstat 13 files changed, 164 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotAddressLowering.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotAddressLowering.java	Thu Jun 11 11:35:55 2015 +0200
@@ -102,9 +102,10 @@
                 ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister));
                 addr.setBase(base);
             } else if (encoding.base != 0) {
-                long disp = addr.getDisplacement() + heapBase;
+                long disp = addr.getDisplacement() + encoding.base;
                 if (NumUtil.isInt(disp)) {
                     addr.setDisplacement((int) disp);
+                    addr.setBase(null);
                 } else {
                     return false;
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java	Thu Jun 11 11:35:55 2015 +0200
@@ -23,16 +23,21 @@
 package com.oracle.graal.hotspot;
 
 import static com.oracle.graal.compiler.common.GraalOptions.*;
+import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.*;
 import static com.oracle.jvmci.code.CallingConvention.Type.*;
 import static com.oracle.jvmci.code.CodeUtil.*;
 
 import com.oracle.graal.compiler.*;
+import com.oracle.graal.graphbuilderconf.*;
+import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import com.oracle.graal.hotspot.meta.*;
 import com.oracle.graal.hotspot.phases.*;
+import com.oracle.graal.java.*;
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.spi.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.OptimisticOptimizations.Optimization;
 import com.oracle.graal.phases.tiers.*;
@@ -50,9 +55,12 @@
         HotSpotProviders providers = HotSpotGraalRuntime.runtime().getHostProviders();
         final boolean isOSR = entryBCI != INVOCATION_ENTRY_BCI;
 
-        StructuredGraph graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue()));
-        if (!mustRecordMethodInlining) {
-            graph.disableInlinedMethodRecording();
+        StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers);
+        if (graph == null) {
+            graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue()));
+            if (!mustRecordMethodInlining) {
+                graph.disableInlinedMethodRecording();
+            }
         }
 
         CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false);
@@ -85,6 +93,29 @@
         return result;
     }
 
+    /**
+     * Gets a graph produced from the intrinsic for a given method that can be compiled and
+     * installed for the method.
+     *
+     * @param method
+     * @return an intrinsic graph that can be compiled and installed for {@code method} or null
+     */
+    protected StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers) {
+        Replacements replacements = providers.getReplacements();
+        ResolvedJavaMethod substMethod = replacements.getSubstitutionMethod(method);
+        if (substMethod != null) {
+            assert !substMethod.equals(method);
+            StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES);
+            Plugins plugins = new Plugins(providers.getGraphBuilderPlugins());
+            GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
+            IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, ROOT_COMPILATION);
+            new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph);
+            assert !graph.isFrozen();
+            return graph;
+        }
+        return null;
+    }
+
     protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo) {
         return new OptimisticOptimizations(profilingInfo);
     }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java	Thu Jun 11 11:35:55 2015 +0200
@@ -118,6 +118,8 @@
             for (Node successor : successors()) {
                 if (successor != survivingSuccessor) {
                     tool.deleteBranch(successor);
+                    // deleteBranch can change the successors so reload it
+                    survivingSuccessor = successorAtKey(constant);
                 }
             }
             tool.addToWorkList(survivingSuccessor);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/Replacements.java	Thu Jun 11 11:35:55 2015 +0200
@@ -80,6 +80,13 @@
     StructuredGraph getSubstitution(ResolvedJavaMethod method, boolean fromBytecodeOnly, int invokeBci);
 
     /**
+     * Gets a method that is a substitution for a given method.
+     *
+     * @return the method, if any, whose bytecode are a substitution for {@code method}
+     */
+    ResolvedJavaMethod getSubstitutionMethod(ResolvedJavaMethod method);
+
+    /**
      * Determines if there is a {@linkplain #getSubstitution(ResolvedJavaMethod, int) substitution
      * graph} for a given method.
      *
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Thu Jun 11 11:35:55 2015 +0200
@@ -100,7 +100,7 @@
 
         if (!method.equals(curMethod) || !curDecorators.equals(decorators)) {
             cfgPrinter.printCompilation(method);
-            TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile);
+            TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile.getAbsolutePath());
         }
         curMethod = method;
         curDecorators = decorators;
@@ -131,7 +131,7 @@
             } catch (FileNotFoundException e) {
                 throw new JVMCIError("Could not open " + cfgFile.getAbsolutePath());
             }
-            TTY.println("CFGPrinter: Output to file %s", cfgFile);
+            TTY.println("CFGPrinter: Output to file %s", cfgFile.getAbsolutePath());
         }
 
         if (!checkMethodScope()) {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CompilationPrinter.java	Thu Jun 11 11:35:55 2015 +0200
@@ -183,7 +183,7 @@
     }
 
     public void printMachineCode(String code, String label) {
-        if (code.length() == 0) {
+        if (code == null || code.length() == 0) {
             return;
         }
         if (label != null) {
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Thu Jun 11 11:35:55 2015 +0200
@@ -327,8 +327,8 @@
             if (plugin != null) {
                 if (!plugin.inlineOnly() || invokeBci >= 0) {
                     if (plugin instanceof MethodSubstitutionPlugin) {
-                        MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin;
-                        substitute = msplugin.getSubstitute(providers.getMetaAccess());
+                        MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin;
+                        substitute = msPlugin.getSubstitute(providers.getMetaAccess());
                     } else {
                         StructuredGraph graph = new IntrinsicGraphBuilder(providers.getMetaAccess(), providers.getConstantReflection(), providers.getStampProvider(), original, invokeBci).buildGraph(plugin);
                         if (graph != null) {
@@ -682,6 +682,11 @@
     }
 
     public ResolvedJavaMethod getSubstitutionMethod(ResolvedJavaMethod original) {
+        InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(original);
+        if (plugin instanceof MethodSubstitutionPlugin) {
+            MethodSubstitutionPlugin msPlugin = (MethodSubstitutionPlugin) plugin;
+            return msPlugin.getSubstitute(providers.getMetaAccess());
+        }
         ClassReplacements cr = getClassReplacements(original.getDeclaringClass().getName());
         return cr == null ? null : cr.methodSubstitutions.get(original);
     }
--- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java	Thu Jun 11 11:35:55 2015 +0200
@@ -422,17 +422,6 @@
         }
     }
 
-    public StructuredGraph createRootGraph(StructuredGraph graph) {
-        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompiler.Optimizations, null).apply(graph);
-        return graph;
-    }
-
-    public StructuredGraph createInlineGraph(String name, StructuredGraph caller) {
-        StructuredGraph graph = new StructuredGraph(name, callInlinedMethod, AllowAssumptions.from(caller.getAssumptions() != null));
-        new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), configForRoot, TruffleCompiler.Optimizations, null).apply(graph);
-        return graph;
-    }
-
     private static void postPartialEvaluation(final StructuredGraph graph) {
         NeverPartOfCompilationNode.verifyNotFoundIn(graph);
         for (MaterializeFrameNode materializeNode : graph.getNodes(MaterializeFrameNode.TYPE).snapshot()) {
--- a/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ObjectType.java	Thu Jun 11 11:35:55 2015 +0200
@@ -61,16 +61,6 @@
         return null;
     }
 
-    /**
-     * Called when a new property is added to a shape.
-     *
-     * @param property the added property
-     * @param shapeBefore shape before the property was added
-     * @param shapeAfter shape after the property was added
-     */
-    public void onPropertyAdded(Property property, Shape shapeBefore, Shape shapeAfter) {
-    }
-
     public ForeignAccess getForeignAccessFactory() {
         return ForeignAccess.create(new com.oracle.truffle.api.interop.ForeignAccess.Factory() {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.api.object/src/com/oracle/truffle/api/object/ShapeListener.java	Thu Jun 11 11:35:55 2015 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.truffle.api.object;
+
+public interface ShapeListener {
+    /**
+     * Called when a property is added, removed, or replaced.
+     *
+     * @param key identifier of the property
+     */
+    void onPropertyTransition(Object key);
+}
--- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java	Thu Jun 11 11:35:55 2015 +0200
@@ -39,4 +39,20 @@
     protected ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType objectType, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) {
         return new ShapeBasic(layout, sharedData, parent, objectType, propertyMap, transition, allocator, id);
     }
+
+    @Override
+    public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) {
+        assert oldProperty.getKey().equals(newProperty.getKey());
+        onPropertyTransition(oldProperty);
+
+        Transition replacePropertyTransition = new Transition.DirectReplacePropertyTransition(oldProperty, newProperty);
+        ShapeImpl cachedShape = queryTransition(replacePropertyTransition);
+        if (cachedShape != null) {
+            return cachedShape;
+        }
+        PropertyMap newPropertyMap = this.getPropertyMap().replaceCopy(oldProperty, newProperty);
+        ShapeImpl newShape = createShape(getLayout(), getSharedData(), this, getObjectType(), newPropertyMap, replacePropertyTransition, allocator(), getId());
+        addDirectTransition(replacePropertyTransition, newShape);
+        return newShape;
+    }
 }
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java	Thu Jun 11 11:35:55 2015 +0200
@@ -23,6 +23,7 @@
 package com.oracle.truffle.object;
 
 import java.util.*;
+import java.util.concurrent.*;
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -39,6 +40,7 @@
 import com.oracle.truffle.object.Locations.DualLocation;
 import com.oracle.truffle.object.Locations.ValueLocation;
 import com.oracle.truffle.object.Transition.AddPropertyTransition;
+import com.oracle.truffle.object.Transition.DirectReplacePropertyTransition;
 import com.oracle.truffle.object.Transition.ObjectTypeTransition;
 import com.oracle.truffle.object.Transition.PropertyTransition;
 import com.oracle.truffle.object.Transition.RemovePropertyTransition;
@@ -89,7 +91,7 @@
      * @see #getTransitionMapForRead()
      * @see #getTransitionMapForWrite()
      */
-    private HashMap<Transition, ShapeImpl> transitionMap;
+    private volatile Map<Transition, ShapeImpl> transitionMap;
 
     private final Transition transitionFromParent;
 
@@ -302,8 +304,13 @@
         if (transitionMap != null) {
             return transitionMap;
         } else {
-            invalidateLeafAssumption();
-            return transitionMap = new HashMap<>();
+            synchronized (getMutex()) {
+                if (transitionMap != null) {
+                    return transitionMap;
+                }
+                invalidateLeafAssumption();
+                return transitionMap = new ConcurrentHashMap<>();
+            }
         }
     }
 
@@ -311,7 +318,7 @@
         return propertyMap;
     }
 
-    private ShapeImpl queryTransition(Transition transition) {
+    protected final ShapeImpl queryTransition(Transition transition) {
         ShapeImpl cachedShape = this.getTransitionMapForRead().get(transition);
         if (cachedShape != null) { // Shape already exists?
             shapeCacheHitCount.inc();
@@ -332,9 +339,14 @@
     @Override
     public ShapeImpl addProperty(Property property) {
         assert isValid();
-        ShapeImpl nextShape = addPropertyInternal(property);
-        objectType.onPropertyAdded(property, this, nextShape);
-        return nextShape;
+        onPropertyTransition(property);
+        return addPropertyInternal(property);
+    }
+
+    protected final void onPropertyTransition(Property property) {
+        if (sharedData instanceof ShapeListener) {
+            ((ShapeListener) sharedData).onPropertyTransition(property.getKey());
+        }
     }
 
     /**
@@ -627,6 +639,8 @@
     @TruffleBoundary
     @Override
     public final ShapeImpl removeProperty(Property prop) {
+        onPropertyTransition(prop);
+
         RemovePropertyTransition transition = new RemovePropertyTransition(prop);
         ShapeImpl cachedShape = queryTransition(transition);
         if (cachedShape != null) {
@@ -667,6 +681,8 @@
             return changeType(((ObjectTypeTransition) transition).getObjectType());
         } else if (transition instanceof ReservePrimitiveArrayTransition) {
             return reservePrimitiveExtensionArray();
+        } else if (transition instanceof DirectReplacePropertyTransition) {
+            return replaceProperty(((DirectReplacePropertyTransition) transition).getPropertyBefore(), ((DirectReplacePropertyTransition) transition).getPropertyAfter());
         } else {
             throw new UnsupportedOperationException();
         }
@@ -681,8 +697,10 @@
      * Duplicate shape exchanging existing property with new property.
      */
     @Override
-    public final ShapeImpl replaceProperty(Property oldProperty, Property newProperty) {
-        Transition replacePropertyTransition = new Transition.ReplacePropertyTransition(oldProperty, newProperty);
+    public ShapeImpl replaceProperty(Property oldProperty, Property newProperty) {
+        assert oldProperty.getKey().equals(newProperty.getKey());
+
+        Transition replacePropertyTransition = new Transition.IndirectReplacePropertyTransition(oldProperty, newProperty);
         ShapeImpl cachedShape = queryTransition(replacePropertyTransition);
         if (cachedShape != null) {
             return cachedShape;
--- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java	Thu Jun 11 11:35:27 2015 +0200
+++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java	Thu Jun 11 11:35:55 2015 +0200
@@ -133,10 +133,10 @@
         }
     }
 
-    public static final class ReplacePropertyTransition extends PropertyTransition {
+    public abstract static class AbstractReplacePropertyTransition extends PropertyTransition {
         private final Property after;
 
-        public ReplacePropertyTransition(Property before, Property after) {
+        public AbstractReplacePropertyTransition(Property before, Property after) {
             super(before);
             this.after = after;
         }
@@ -150,11 +150,41 @@
         }
 
         @Override
+        public boolean equals(Object obj) {
+            return super.equals(obj) && this.after.equals(((AbstractReplacePropertyTransition) obj).after);
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = super.hashCode();
+            result = prime * result + after.hashCode();
+            return result;
+        }
+    }
+
+    public static final class IndirectReplacePropertyTransition extends AbstractReplacePropertyTransition {
+        public IndirectReplacePropertyTransition(Property before, Property after) {
+            super(before, after);
+        }
+
+        @Override
         public boolean isDirect() {
             return false;
         }
     }
 
+    public static final class DirectReplacePropertyTransition extends AbstractReplacePropertyTransition {
+        public DirectReplacePropertyTransition(Property before, Property after) {
+            super(before, after);
+        }
+
+        @Override
+        public boolean isDirect() {
+            return true;
+        }
+    }
+
     public static final class ReservePrimitiveArrayTransition extends Transition {
         public ReservePrimitiveArrayTransition() {
         }