changeset 22262:71a696ca2862

Support optimization of reads from special memory locations
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Mon, 20 Jul 2015 11:19:52 -0700
parents 11f9d9c2c1bf
children 7abe84b97eaa
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CanonicalizableLocation.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/NamedLocationIdentity.java
diffstat 6 files changed, 188 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Mon Jul 20 11:19:37 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CompressionNode.java	Mon Jul 20 11:19:52 2015 -0700
@@ -69,6 +69,10 @@
         return input.graph().unique(new CompressionNode(CompressionOp.Compress, input, encoding));
     }
 
+    public static CompressionNode compressNoUnique(ValueNode input, CompressEncoding encoding) {
+        return new CompressionNode(CompressionOp.Compress, input, encoding);
+    }
+
     public static CompressionNode uncompress(ValueNode input, CompressEncoding encoding) {
         return input.graph().unique(new CompressionNode(CompressionOp.Uncompress, input, encoding));
     }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Jul 20 11:19:37 2015 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Jul 20 11:19:52 2015 -0700
@@ -22,22 +22,29 @@
  */
 package com.oracle.graal.hotspot.replacements;
 
-import jdk.internal.jvmci.code.*;
-import jdk.internal.jvmci.common.*;
-import jdk.internal.jvmci.hotspot.*;
-import jdk.internal.jvmci.meta.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*;
 import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*;
 import static jdk.internal.jvmci.common.UnsafeAccess.*;
+import jdk.internal.jvmci.code.*;
+import jdk.internal.jvmci.common.*;
+import jdk.internal.jvmci.hotspot.*;
+import jdk.internal.jvmci.meta.Assumptions.AssumptionResult;
+import jdk.internal.jvmci.meta.*;
 
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.compiler.common.*;
+import com.oracle.graal.compiler.common.type.*;
 import com.oracle.graal.graph.Node.ConstantNodeParameter;
 import com.oracle.graal.graph.Node.NodeIntrinsic;
+import com.oracle.graal.graph.spi.*;
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.word.*;
+import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.memory.*;
+import com.oracle.graal.nodes.memory.address.*;
+import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.replacements.*;
 import com.oracle.graal.replacements.nodes.*;
 import com.oracle.graal.word.*;
@@ -49,6 +56,60 @@
  */
 public class HotSpotReplacementsUtil {
 
+    abstract static class HotSpotOptimizingLocationIdentity extends NamedLocationIdentity implements CanonicalizableLocation {
+
+        HotSpotOptimizingLocationIdentity(String name) {
+            super(name, true);
+        }
+
+        @Override
+        public abstract ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool);
+
+        protected ValueNode findReadHub(ValueNode object) {
+            ValueNode base = object;
+            if (base instanceof CompressionNode) {
+                base = ((CompressionNode) base).getValue();
+            }
+            if (base instanceof Access) {
+                Access access = (Access) base;
+                if (access.getLocationIdentity().equals(HUB_LOCATION)) {
+                    AddressNode address = access.getAddress();
+                    if (address instanceof OffsetAddressNode) {
+                        OffsetAddressNode offset = (OffsetAddressNode) address;
+                        return offset.getBase();
+                    }
+                }
+            } else if (base instanceof LoadHubNode) {
+                LoadHubNode loadhub = (LoadHubNode) base;
+                return loadhub.getValue();
+            }
+            return null;
+        }
+
+        /**
+         * Fold reads that convert from Class -> Hub -> Class or vice versa.
+         *
+         * @param read
+         * @param object
+         * @param otherLocation
+         * @return an earlier read or the original {@code read}
+         */
+        protected static ValueNode foldIndirection(ValueNode read, ValueNode object, LocationIdentity otherLocation) {
+            if (object instanceof Access) {
+                Access access = (Access) object;
+                if (access.getLocationIdentity().equals(otherLocation)) {
+                    AddressNode address = access.getAddress();
+                    if (address instanceof OffsetAddressNode) {
+                        OffsetAddressNode offset = (OffsetAddressNode) address;
+                        assert offset.getBase().stamp().isCompatible(read.stamp());
+                        return offset.getBase();
+                    }
+                }
+            }
+            return read;
+        }
+    }
+
     @Fold
     public static HotSpotVMConfig config() {
         return runtime().getConfig();
@@ -296,7 +357,23 @@
         return config().jvmAccWrittenFlags;
     }
 
-    public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = NamedLocationIdentity.immutable("Klass::_layout_helper");
+    public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = new HotSpotOptimizingLocationIdentity("Klass::_layout_helper") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            ValueNode javaObject = findReadHub(object);
+            if (javaObject != null) {
+                if (javaObject.stamp() instanceof ObjectStamp) {
+                    ObjectStamp stamp = (ObjectStamp) javaObject.stamp();
+                    HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) stamp.javaType(tool.getMetaAccess());
+                    if (type.isArray() && !type.getComponentType().isPrimitive()) {
+                        int layout = ((HotSpotResolvedObjectTypeImpl) type).layoutHelper();
+                        return ConstantNode.forInt(layout);
+                    }
+                }
+            }
+            return read;
+        }
+    };
 
     @Fold
     public static int klassLayoutHelperOffset() {
@@ -356,7 +433,20 @@
 
     public static final LocationIdentity HUB_WRITE_LOCATION = NamedLocationIdentity.mutable("Hub:write");
 
-    public static final LocationIdentity HUB_LOCATION = NamedLocationIdentity.immutable("Hub");
+    public static final LocationIdentity HUB_LOCATION = new HotSpotOptimizingLocationIdentity("Hub") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            ResolvedJavaType constantType = LoadHubNode.findSynonymType(read.graph(), tool.getMetaAccess(), object);
+            if (constantType != null) {
+                if (config().useCompressedClassPointers) {
+                    return ConstantNode.forConstant(read.stamp(), ((HotSpotMetaspaceConstant) constantType.getObjectHub()).compress(config().getKlassEncoding()), tool.getMetaAccess());
+                } else {
+                    return ConstantNode.forConstant(read.stamp(), constantType.getObjectHub(), tool.getMetaAccess());
+                }
+            }
+            return read;
+        }
+    };
 
     @Fold
     private static int hubOffset() {
@@ -655,14 +745,24 @@
         return config().klassModifierFlagsOffset;
     }
 
-    public static final LocationIdentity CLASS_KLASS_LOCATION = NamedLocationIdentity.immutable("Class._klass");
+    public static final LocationIdentity CLASS_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._klass") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            return foldIndirection(read, object, CLASS_MIRROR_LOCATION);
+        }
+    };
 
     @Fold
     public static int klassOffset() {
         return config().klassOffset;
     }
 
-    public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = NamedLocationIdentity.mutable("Class._array_klass");
+    public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._array_klass") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            return foldIndirection(read, object, ARRAY_KLASS_COMPONENT_MIRROR);
+        }
+    };
 
     @Fold
     public static int arrayKlassOffset() {
@@ -854,7 +954,26 @@
         }
     }
 
-    public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = NamedLocationIdentity.immutable("ObjArrayKlass::_element_klass");
+    public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") {
+        @Override
+        public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) {
+            ValueNode javaObject = findReadHub(object);
+            if (javaObject != null) {
+                ResolvedJavaType type = StampTool.typeOrNull(javaObject);
+                if (type != null && type.isArray()) {
+                    ResolvedJavaType element = type.getComponentType();
+                    if (element != null && !element.isPrimitive() && !element.getElementalType().isInterface()) {
+                        AssumptionResult<ResolvedJavaType> leafType = element.findLeafConcreteSubtype();
+                        if (leafType != null) {
+                            object.graph().getAssumptions().record(leafType);
+                            return ConstantNode.forConstant(read.stamp(), leafType.getResult().getObjectHub(), tool.getMetaAccess());
+                        }
+                    }
+                }
+            }
+            return read;
+        }
+    };
 
     @Fold
     public static int arrayClassElementOffset() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CanonicalizableLocation.java	Mon Jul 20 11:19:52 2015 -0700
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ *
+ * 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;
+
+import com.oracle.graal.graph.spi.*;
+import com.oracle.graal.nodes.memory.address.*;
+
+public interface CanonicalizableLocation {
+    ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool);
+}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Jul 20 11:19:37 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java	Mon Jul 20 11:19:52 2015 -0700
@@ -89,10 +89,18 @@
         return this;
     }
 
-    private static ValueNode findSynonym(ValueNode curValue, Stamp stamp, StructuredGraph graph, MetaAccessProvider metaAccess) {
+    public static ValueNode findSynonym(ValueNode curValue, Stamp stamp, StructuredGraph graph, MetaAccessProvider metaAccess) {
+        ResolvedJavaType exactType = findSynonymType(graph, metaAccess, curValue);
+        if (exactType != null) {
+            return ConstantNode.forConstant(stamp, exactType.getObjectHub(), metaAccess);
+        }
+        return null;
+    }
+
+    public static ResolvedJavaType findSynonymType(StructuredGraph graph, MetaAccessProvider metaAccess, ValueNode curValue) {
+        ResolvedJavaType exactType = null;
         if (metaAccess != null && curValue.stamp() instanceof ObjectStamp) {
             ObjectStamp objectStamp = (ObjectStamp) curValue.stamp();
-            ResolvedJavaType exactType = null;
             if (objectStamp.isExactType()) {
                 exactType = objectStamp.type();
             } else if (objectStamp.type() != null && graph != null && graph.getAssumptions() != null) {
@@ -102,12 +110,8 @@
                     graph.getAssumptions().record(leafConcreteSubtype);
                 }
             }
-
-            if (exactType != null) {
-                return ConstantNode.forConstant(stamp, exactType.getObjectHub(), metaAccess);
-            }
         }
-        return null;
+        return exactType;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java	Mon Jul 20 11:19:37 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java	Mon Jul 20 11:19:52 2015 -0700
@@ -133,6 +133,13 @@
                     return length;
                 }
             }
+            if (locationIdentity instanceof CanonicalizableLocation) {
+                CanonicalizableLocation canonicalize = (CanonicalizableLocation) locationIdentity;
+                ValueNode result = canonicalize.canonicalizeRead(read, address, object, tool);
+                assert result != null && result.stamp().isCompatible(read.stamp());
+                return result;
+            }
+
         }
         return read;
     }
--- a/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/NamedLocationIdentity.java	Mon Jul 20 11:19:37 2015 -0700
+++ b/jvmci/jdk.internal.jvmci.meta/src/jdk/internal/jvmci/meta/NamedLocationIdentity.java	Mon Jul 20 11:19:52 2015 -0700
@@ -29,18 +29,17 @@
 /**
  * A {@link LocationIdentity} with a name.
  */
-public final class NamedLocationIdentity extends LocationIdentity implements FormatWithToString {
+public class NamedLocationIdentity extends LocationIdentity implements FormatWithToString {
 
     /**
      * Map for asserting all {@link NamedLocationIdentity} instances have a unique name.
      */
     static class DB {
-        private static final HashMap<String, NamedLocationIdentity> map = new HashMap<>();
+        private static final HashSet<String> map = new HashSet<>();
 
-        static boolean checkUnique(NamedLocationIdentity identity) {
-            NamedLocationIdentity oldValue = map.put(identity.name, identity);
-            if (oldValue != null) {
-                throw new AssertionError("identity " + identity + " already exists");
+        static boolean checkUnique(String name) {
+            if (!map.add(name)) {
+                throw new AssertionError("identity " + name + " already exists");
             }
             return true;
         }
@@ -49,9 +48,10 @@
     private final String name;
     private final boolean immutable;
 
-    private NamedLocationIdentity(String name, boolean immutable) {
+    protected NamedLocationIdentity(String name, boolean immutable) {
         this.name = name;
         this.immutable = immutable;
+        assert DB.checkUnique(name);
     }
 
     /**
@@ -82,9 +82,7 @@
      * @param immutable true if the location is immutable
      */
     private static NamedLocationIdentity create(String name, boolean immutable) {
-        NamedLocationIdentity id = new NamedLocationIdentity(name, immutable);
-        assert DB.checkUnique(id);
-        return id;
+        return new NamedLocationIdentity(name, immutable);
     }
 
     @Override