changeset 16616:29404eec7ced

eliminate duplicate entries from profile data
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Tue, 29 Jul 2014 17:40:15 -0700
parents 3812931f9350
children c164a505fc23
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java
diffstat 3 files changed, 56 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Tue Jul 29 17:40:00 2014 -0700
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Tue Jul 29 17:40:15 2014 -0700
@@ -488,11 +488,24 @@
             long totalCount = 0;
             int entries = 0;
 
-            for (int i = 0; i < typeProfileWidth; i++) {
+            outer: for (int i = 0; i < typeProfileWidth; i++) {
                 long receiverKlass = data.readWord(position, getTypeOffset(i));
                 if (receiverKlass != 0) {
-                    types[entries] = HotSpotResolvedObjectType.fromMetaspaceKlass(receiverKlass);
+                    ResolvedJavaType klass = HotSpotResolvedObjectType.fromMetaspaceKlass(receiverKlass);
                     long count = data.readUnsignedInt(position, getTypeCountOffset(i));
+                    /*
+                     * Because of races in the profile collection machinery it's possible for a
+                     * class to appear multiple times so merge them to make the profile look
+                     * rational.
+                     */
+                    for (int j = 0; j < entries; j++) {
+                        if (types[j].equals(klass)) {
+                            totalCount += count;
+                            counts[j] += count;
+                            continue outer;
+                        }
+                    }
+                    types[entries] = klass;
                     totalCount += count;
                     counts[entries] = count;
                     entries++;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Tue Jul 29 17:40:00 2014 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java	Tue Jul 29 17:40:15 2014 -0700
@@ -44,7 +44,7 @@
     /**
      * Constructs a type switch instruction. The keyProbabilities array contain key.length + 1
      * entries. The last entry in every array describes the default case.
-     * 
+     *
      * @param value the instruction producing the value being switched on, the object hub
      * @param successors the list of successors
      * @param keys the list of types
@@ -57,6 +57,21 @@
         assert keySuccessors.length == keyProbabilities.length;
         this.keys = keys;
         assert assertValues();
+        assert assertKeys();
+    }
+
+    /**
+     * Don't allow duplicate keys
+     */
+    private boolean assertKeys() {
+        for (int i = 0; i < keys.length; i++) {
+            for (int j = 0; j < keys.length; j++) {
+                if (i == j)
+                    continue;
+                assert !keys[i].equals(keys[j]);
+            }
+        }
+        return true;
     }
 
     @Override
@@ -87,6 +102,15 @@
         return keys[index].getEncoding(Representation.ObjectHub);
     }
 
+    @Override
+    public boolean equalKeys(SwitchNode switchNode) {
+        if (!(switchNode instanceof TypeSwitchNode)) {
+            return false;
+        }
+        TypeSwitchNode other = (TypeSwitchNode) switchNode;
+        return Arrays.equals(keys, other.keys);
+    }
+
     public ResolvedJavaType typeAt(int index) {
         return keys[index];
     }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Jul 29 17:40:00 2014 -0700
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Jul 29 17:40:15 2014 -0700
@@ -78,6 +78,15 @@
         this.methodProbabilities = computeMethodProbabilities();
         this.maximumMethodProbability = maximumMethodProbability();
         assert maximumMethodProbability > 0;
+        assert assertUniqueTypes(ptypes);
+    }
+
+    private static boolean assertUniqueTypes(ArrayList<ProfiledType> ptypes) {
+        Set<ResolvedJavaType> set = new HashSet<>();
+        for (ProfiledType ptype : ptypes) {
+            set.add(ptype.getType());
+        }
+        return set.size() == ptypes.size();
     }
 
     private double[] computeMethodProbabilities() {
@@ -383,15 +392,22 @@
         ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()];
         double[] keyProbabilities = new double[ptypes.size() + 1];
         int[] keySuccessors = new int[ptypes.size() + 1];
+        double totalProbability = notRecordedTypeProbability;
         for (int i = 0; i < ptypes.size(); i++) {
             keys[i] = ptypes.get(i).getType();
             keyProbabilities[i] = ptypes.get(i).getProbability();
+            totalProbability += keyProbabilities[i];
             keySuccessors[i] = invokeIsOnlySuccessor ? 0 : typesToConcretes.get(i);
             assert keySuccessors[i] < successors.length - 1 : "last successor is the unknownTypeSux";
         }
         keyProbabilities[keyProbabilities.length - 1] = notRecordedTypeProbability;
         keySuccessors[keySuccessors.length - 1] = successors.length - 1;
 
+        // Normalize the probabilities.
+        for (int i = 0; i < keyProbabilities.length; i++) {
+            keyProbabilities[i] /= totalProbability;
+        }
+
         TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors));
         FixedWithNextNode pred = (FixedWithNextNode) invoke.asNode().predecessor();
         pred.setNext(typeSwitch);