changeset 8934:cdd70fd1479b

Merge
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 09 Apr 2013 10:48:14 +0200
parents a214dada94c4 (current diff) f2bddf68d293 (diff)
children 689f2b71251c 6cae606d563f 1b5eeb50e690
files graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java
diffstat 7 files changed, 112 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Tue Apr 09 10:29:44 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java	Tue Apr 09 10:48:14 2013 +0200
@@ -36,10 +36,31 @@
  */
 public class TypeCheckHints {
 
-    private static final ResolvedJavaType[] NO_TYPES = {};
+    /**
+     * A receiver type profiled in a type check instruction.
+     */
+    public static class Hint {
+
+        /**
+         * A type seen while profiling a type check instruction.
+         */
+        public final ResolvedJavaType type;
+
+        /**
+         * Specifies if {@link #type} was a sub-type of the checked type.
+         */
+        public final boolean positive;
+
+        Hint(ResolvedJavaType type, boolean positive) {
+            this.type = type;
+            this.positive = positive;
+        }
+    }
+
+    private static final Hint[] NO_HINTS = {};
 
     /**
-     * If true, then {@link #types} contains the only possible type that could pass the type check
+     * If true, then {@link #hints} contains the only possible type that could pass the type check
      * because the target of the type check is a final class or has been speculated to be a final
      * class.
      */
@@ -48,7 +69,7 @@
     /**
      * The most likely types that the type check instruction will see.
      */
-    public final ResolvedJavaType[] types;
+    public final Hint[] hints;
 
     /**
      * Derives hint information for use when generating the code for a type check instruction.
@@ -58,18 +79,18 @@
      * @param assumptions the object in which speculations are recorded. This is null if
      *            speculations are not supported.
      * @param minHintHitProbability if the probability that the type check will hit one of the
-     *            profiled types (up to {@code maxHints}) is below this value, then {@link #types}
+     *            profiled types (up to {@code maxHints}) is below this value, then {@link #hints}
      *            will be null
-     * @param maxHints the maximum length of {@link #types}
+     * @param maxHints the maximum length of {@link #hints}
      */
     public TypeCheckHints(ResolvedJavaType type, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) {
         if (type != null && !canHaveSubtype(type)) {
-            types = new ResolvedJavaType[]{type};
+            hints = new Hint[]{new Hint(type, true)};
             exact = true;
         } else {
             ResolvedJavaType uniqueSubtype = type == null ? null : type.findUniqueConcreteSubtype();
             if (uniqueSubtype != null) {
-                types = new ResolvedJavaType[]{uniqueSubtype};
+                hints = new Hint[]{new Hint(uniqueSubtype, true)};
                 if (assumptions.useOptimisticAssumptions()) {
                     assumptions.recordConcreteSubtype(type, uniqueSubtype);
                     exact = true;
@@ -78,33 +99,32 @@
                 }
             } else {
                 exact = false;
-                ResolvedJavaType[] hintTypes = NO_TYPES;
+                Hint[] hintsBuf = NO_HINTS;
                 JavaTypeProfile typeProfile = profile;
                 if (typeProfile != null) {
                     double notRecordedTypes = typeProfile.getNotRecordedProbability();
                     ProfiledType[] ptypes = typeProfile.getTypes();
                     if (notRecordedTypes < (1D - minHintHitProbability) && ptypes != null && ptypes.length > 0) {
-                        hintTypes = new ResolvedJavaType[ptypes.length];
+                        hintsBuf = new Hint[ptypes.length];
                         int hintCount = 0;
                         double totalHintProbability = 0.0d;
                         for (ProfiledType ptype : ptypes) {
-                            ResolvedJavaType hint = ptype.getType();
-                            if (type != null && type.isAssignableFrom(hint)) {
-                                hintTypes[hintCount++] = hint;
+                            if (type != null) {
+                                hintsBuf[hintCount++] = new Hint(type, type.isAssignableFrom(ptype.getType()));
                                 totalHintProbability += ptype.getProbability();
                             }
                         }
                         if (totalHintProbability >= minHintHitProbability) {
-                            if (hintTypes.length != hintCount || hintCount > maxHints) {
-                                hintTypes = Arrays.copyOf(hintTypes, Math.min(maxHints, hintCount));
+                            if (hintsBuf.length != hintCount || hintCount > maxHints) {
+                                hintsBuf = Arrays.copyOf(hintsBuf, Math.min(maxHints, hintCount));
                             }
                         } else {
-                            hintTypes = NO_TYPES;
+                            hintsBuf = NO_HINTS;
                         }
 
                     }
                 }
-                this.types = hintTypes;
+                this.hints = hintsBuf;
             }
         }
     }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Tue Apr 09 10:29:44 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java	Tue Apr 09 10:48:14 2013 +0200
@@ -122,7 +122,9 @@
     }
 
     /**
-     * A list of types for which the runtime has recorded probability information.
+     * A list of types for which the runtime has recorded probability information. Note that this
+     * includes both positive and negative types where a positive type is a subtype of the checked
+     * type and a negative type is not.
      */
     public ProfiledType[] getTypes() {
         return ptypes;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Tue Apr 09 10:29:44 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java	Tue Apr 09 10:48:14 2013 +0200
@@ -202,7 +202,7 @@
 
             assert type != null;
             if (hintInfo.exact) {
-                ConstantNode[] hints = createHints(hintInfo, runtime, graph);
+                ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
                 assert hints.length == 1;
                 key = new Key(exact).add("checkNull", checkNull);
                 arguments = arguments("object", object).add("exactHub", hints[0]);
@@ -210,7 +210,7 @@
                 key = new Key(primary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
                 arguments = arguments("hub", hub).add("object", object);
             } else {
-                ConstantNode[] hints = createHints(hintInfo, runtime, graph);
+                ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs;
                 key = new Key(secondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
                 arguments = arguments("hub", hub).add("object", object).add("hints", hints);
             }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Tue Apr 09 10:29:44 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java	Tue Apr 09 10:48:14 2013 +0200
@@ -192,7 +192,7 @@
                 Arguments arguments;
                 Key key;
                 if (hintInfo.exact) {
-                    ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
+                    ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs;
                     assert hints.length == 1;
                     key = new Key(instanceofExact).add("checkNull", checkNull);
                     arguments = arguments("object", object).add("exactHub", hints[0]).add("trueValue", trueValue).add("falseValue", falseValue);
@@ -200,7 +200,7 @@
                     key = new Key(instanceofPrimary).add("checkNull", checkNull).add("superCheckOffset", type.superCheckOffset());
                     arguments = arguments("hub", hub).add("object", object).add("trueValue", trueValue).add("falseValue", falseValue);
                 } else {
-                    ConstantNode[] hints = createHints(hintInfo, runtime, hub.graph());
+                    ConstantNode[] hints = createHints(hintInfo, runtime, true, hub.graph()).hubs;
                     key = new Key(instanceofSecondary).add("hints", Varargs.vargargs(new Word[hints.length], StampFactory.forKind(wordKind()))).add("checkNull", checkNull);
                     arguments = arguments("hub", hub).add("object", object).add("hints", hints).add("trueValue", trueValue).add("falseValue", falseValue);
                 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Tue Apr 09 10:29:44 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/TypeCheckSnippetUtils.java	Tue Apr 09 10:48:14 2013 +0200
@@ -25,6 +25,8 @@
 import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*;
 import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*;
 
+import java.util.*;
+
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
@@ -98,12 +100,45 @@
         return false;
     }
 
-    static ConstantNode[] createHints(TypeCheckHints hints, MetaAccessProvider runtime, Graph graph) {
-        ConstantNode[] hintHubs = new ConstantNode[hints.types.length];
-        for (int i = 0; i < hintHubs.length; i++) {
-            hintHubs[i] = ConstantNode.forConstant(((HotSpotResolvedObjectType) hints.types[i]).klass(), runtime, graph);
+    /**
+     * A set of type check hints ordered by decreasing probabilities.
+     */
+    public static class Hints {
+
+        /**
+         * The hubs of the hint types.
+         */
+        public final ConstantNode[] hubs;
+
+        /**
+         * A predicate over {@link #hubs} specifying whether the corresponding hint type is a
+         * sub-type of the checked type.
+         */
+        public final boolean[] isPositive;
+
+        Hints(ConstantNode[] hints, boolean[] hintIsPositive) {
+            this.hubs = hints;
+            this.isPositive = hintIsPositive;
         }
-        return hintHubs;
+    }
+
+    static Hints createHints(TypeCheckHints hints, MetaAccessProvider runtime, boolean positiveOnly, Graph graph) {
+        ConstantNode[] hubs = new ConstantNode[hints.hints.length];
+        boolean[] isPositive = new boolean[hints.hints.length];
+        int index = 0;
+        for (int i = 0; i < hubs.length; i++) {
+            if (!positiveOnly || hints.hints[i].positive) {
+                hubs[index] = ConstantNode.forConstant(((HotSpotResolvedObjectType) hints.hints[i].type).klass(), runtime, graph);
+                isPositive[index] = hints.hints[i].positive;
+                index++;
+            }
+        }
+        if (positiveOnly && index != hubs.length) {
+            assert index < hubs.length;
+            hubs = Arrays.copyOf(hubs, index);
+            isPositive = Arrays.copyOf(isPositive, index);
+        }
+        return new Hints(hubs, isPositive);
     }
 
     static Word loadSecondarySupersElement(Word metaspaceArray, int index) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Tue Apr 09 10:29:44 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java	Tue Apr 09 10:48:14 2013 +0200
@@ -105,7 +105,7 @@
             ResolvedJavaType fieldType = ((ResolvedJavaField) locId).getDeclaringClass();
             ResolvedJavaType beforePiType = parent.object().objectStamp().type();
 
-            if (fieldType.isAssignableFrom(beforePiType)) {
+            if (beforePiType != null && fieldType.isAssignableFrom(beforePiType)) {
                 replaceFirstInput(parent, parent.object());
                 return true;
             }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Apr 09 10:29:44 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java	Tue Apr 09 10:48:14 2013 +0200
@@ -496,7 +496,7 @@
                 } else {
                     Kind kind = ((LocalNode) parameter).kind();
                     assert argument != null || kind == Kind.Object : this + " cannot accept null for non-object parameter named " + name;
-                    Constant constant = Constant.forBoxed(kind, argument);
+                    Constant constant = forBoxed(argument, kind);
                     replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph));
                 }
             } else if (parameter instanceof LocalNode[]) {
@@ -520,7 +520,7 @@
                     if (value instanceof ValueNode) {
                         replacements.put(local, (ValueNode) value);
                     } else {
-                        Constant constant = Constant.forBoxed(local.kind(), value);
+                        Constant constant = forBoxed(value, local.kind());
                         ConstantNode element = ConstantNode.forConstant(constant, runtime, replaceeGraph);
                         replacements.put(local, element);
                     }
@@ -533,6 +533,32 @@
     }
 
     /**
+     * Converts a Java boxed value to a {@link Constant} of the right kind. This adjusts for the
+     * limitation that a {@link Local}'s kind is a {@linkplain Kind#getStackKind() stack kind} and
+     * so cannot be used for re-boxing primitives smaller than an int.
+     * 
+     * @param argument a Java boxed value
+     * @param localKind the kind of the {@link Local} to which {@code argument} will be bound
+     */
+    protected Constant forBoxed(Object argument, Kind localKind) {
+        assert localKind == localKind.getStackKind();
+        if (localKind == Kind.Int && !(argument instanceof Integer)) {
+            if (argument instanceof Boolean) {
+                return Constant.forBoxed(Kind.Boolean, argument);
+            }
+            if (argument instanceof Byte) {
+                return Constant.forBoxed(Kind.Byte, argument);
+            }
+            if (argument instanceof Short) {
+                return Constant.forBoxed(Kind.Short, argument);
+            }
+            assert argument instanceof Character;
+            return Constant.forBoxed(Kind.Char, argument);
+        }
+        return Constant.forBoxed(localKind, argument);
+    }
+
+    /**
      * Logic for replacing a snippet-lowered node at its usages with the return value of the
      * snippet. An alternative to the {@linkplain SnippetTemplate#DEFAULT_REPLACER default}
      * replacement logic can be used to handle mismatches between the stamp of the node being