# HG changeset patch # User Tom Rodriguez # Date 1406680815 25200 # Node ID 29404eec7ced1e0ca5588f13f1fa86f697c40dde # Parent 3812931f935003259027f59e3eabd32771574956 eliminate duplicate entries from profile data diff -r 3812931f9350 -r 29404eec7ced graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- 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++; diff -r 3812931f9350 -r 29404eec7ced graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java --- 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]; } diff -r 3812931f9350 -r 29404eec7ced graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- 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 ptypes) { + Set 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);