# HG changeset patch # User Doug Simon # Date 1365523737 -7200 # Node ID 82d8fac3ad136d3d0dd1314c2aadea7c7c47026c # Parent b47759136478e187247db85e396f29a6636ebf5d# Parent dedc3f7d3033dfd7f55d91ff589665d9c07ef0f0 Merge. diff -r dedc3f7d3033 -r 82d8fac3ad13 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Tue Apr 09 17:25:02 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/TypeCheckHints.java Tue Apr 09 18:08:57 2013 +0200 @@ -74,7 +74,7 @@ /** * Derives hint information for use when generating the code for a type check instruction. * - * @param type the target type of the type check + * @param targetType the target type of the type check * @param profile the profiling information available for the instruction (if any) * @param assumptions the object in which speculations are recorded. This is null if * speculations are not supported. @@ -83,16 +83,16 @@ * will be null * @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)) { - hints = new Hint[]{new Hint(type, true)}; + public TypeCheckHints(ResolvedJavaType targetType, JavaTypeProfile profile, Assumptions assumptions, double minHintHitProbability, int maxHints) { + if (targetType != null && !canHaveSubtype(targetType)) { + hints = new Hint[]{new Hint(targetType, true)}; exact = true; } else { - ResolvedJavaType uniqueSubtype = type == null ? null : type.findUniqueConcreteSubtype(); + ResolvedJavaType uniqueSubtype = targetType == null ? null : targetType.findUniqueConcreteSubtype(); if (uniqueSubtype != null) { hints = new Hint[]{new Hint(uniqueSubtype, true)}; if (assumptions.useOptimisticAssumptions()) { - assumptions.recordConcreteSubtype(type, uniqueSubtype); + assumptions.recordConcreteSubtype(targetType, uniqueSubtype); exact = true; } else { exact = false; @@ -109,8 +109,9 @@ int hintCount = 0; double totalHintProbability = 0.0d; for (ProfiledType ptype : ptypes) { - if (type != null) { - hintsBuf[hintCount++] = new Hint(type, type.isAssignableFrom(ptype.getType())); + if (targetType != null) { + ResolvedJavaType hintType = ptype.getType(); + hintsBuf[hintCount++] = new Hint(hintType, targetType.isAssignableFrom(hintType)); totalHintProbability += ptype.getProbability(); } } diff -r dedc3f7d3033 -r 82d8fac3ad13 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java Tue Apr 09 17:25:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodUnresolved.java Tue Apr 09 18:08:57 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; + import com.oracle.graal.api.meta.*; /** @@ -51,6 +53,6 @@ @Override public String toString() { - return "HotSpotMethod<" + holder.getName() + ". " + name + ", unresolved>"; + return format("HotSpotMethod<%H.%n(%p), unresolved>", this); } } diff -r dedc3f7d3033 -r 82d8fac3ad13 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Tue Apr 09 17:25:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Tue Apr 09 18:08:57 2013 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; + import java.lang.annotation.*; import java.lang.invoke.*; import java.lang.reflect.*; @@ -153,7 +155,7 @@ @Override public String toString() { - return "HotSpotField<" + MetaUtil.format("%h.%n", this) + ":" + offset + ">"; + return format("HotSpotField<%H.%n %t:", this) + offset + ">"; } @Override diff -r dedc3f7d3033 -r 82d8fac3ad13 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Apr 09 17:25:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Apr 09 18:08:57 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; import static com.oracle.graal.graph.FieldIntrospection.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; @@ -186,7 +187,7 @@ @Override public String toString() { - return "HotSpotMethod<" + MetaUtil.format("%h.%n", this) + ">"; + return format("HotSpotMethod<%H.%n(%p)>", this); } public int getCompiledCodeSize() { diff -r dedc3f7d3033 -r 82d8fac3ad13 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java Tue Apr 09 17:25:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotUnresolvedField.java Tue Apr 09 18:08:57 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.meta; +import static com.oracle.graal.api.meta.MetaUtil.*; + import com.oracle.graal.api.meta.*; /** @@ -60,6 +62,6 @@ */ @Override public String toString() { - return MetaUtil.format("%H.%n [unresolved]", this); + return format("HotSpotField<%H.%n %t, unresolved>", this); } } diff -r dedc3f7d3033 -r 82d8fac3ad13 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Tue Apr 09 17:25:02 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Tue Apr 09 18:08:57 2013 +0200 @@ -24,6 +24,7 @@ import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; +import static com.oracle.graal.replacements.Snippet.Varargs.*; import static com.oracle.graal.replacements.SnippetTemplate.Arguments.*; import static com.oracle.graal.replacements.nodes.BranchProbabilityNode.*; @@ -114,6 +115,7 @@ @Parameter("trueValue") Object trueValue, @Parameter("falseValue") Object falseValue, @VarargsParameter("hints") Word[] hints, + @VarargsParameter("hintIsPositive") boolean[] hintIsPositive, @ConstantParameter("checkNull") boolean checkNull) { if (checkNull && object == null) { probability(NOT_FREQUENT_PROBABILITY); @@ -125,10 +127,11 @@ ExplodeLoopNode.explodeLoop(); for (int i = 0; i < hints.length; i++) { Word hintHub = hints[i]; + boolean positive = hintIsPositive[i]; if (hintHub.equal(objectHub)) { probability(NOT_FREQUENT_PROBABILITY); hintsHit.inc(); - return trueValue; + return positive ? trueValue : falseValue; } } if (!checkSecondarySubType(hub, objectHub)) { @@ -174,7 +177,7 @@ super(runtime, replacements, target, InstanceOfSnippets.class); instanceofExact = snippet("instanceofExact", Object.class, Word.class, Object.class, Object.class, boolean.class); instanceofPrimary = snippet("instanceofPrimary", Word.class, Object.class, Object.class, Object.class, boolean.class, int.class); - instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean.class); + instanceofSecondary = snippet("instanceofSecondary", Word.class, Object.class, Object.class, Object.class, Word[].class, boolean[].class, boolean.class); instanceofDynamic = snippet("instanceofDynamic", Class.class, Object.class, Object.class, Object.class, boolean.class); } @@ -200,9 +203,13 @@ 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, 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); + Hints hints = createHints(hintInfo, runtime, false, hub.graph()); + ConstantNode[] hintHubs = hints.hubs; + boolean[] hintIsPositive = hints.isPositive; + Varargs hintsParam = vargargs(new Word[hintHubs.length], StampFactory.forKind(wordKind())); + Varargs hintIsPositiveParam = vargargs(new boolean[hintIsPositive.length], StampFactory.forKind(Kind.Boolean)); + key = new Key(instanceofSecondary).add("hints", hintsParam).add("hintIsPositive", hintIsPositiveParam).add("checkNull", checkNull); + arguments = arguments("hub", hub).add("object", object).add("hints", hintHubs).add("hintIsPositive", hintIsPositive).add("trueValue", trueValue).add("falseValue", falseValue); } return new KeyAndArguments(key, arguments); } else { diff -r dedc3f7d3033 -r 82d8fac3ad13 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Apr 09 17:25:02 2013 +0200 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Apr 09 18:08:57 2013 +0200 @@ -39,6 +39,30 @@ public final class SchedulePhase extends Phase { + /** + * Error thrown when a graph cannot be scheduled. + */ + public static class SchedulingError extends Error { + + private static final long serialVersionUID = 1621001069476473145L; + + public SchedulingError() { + super(); + } + + /** + * This constructor creates a {@link SchedulingError} with a message assembled via + * {@link String#format(String, Object...)}. + * + * @param format a {@linkplain Formatter format} string + * @param args parameters to {@link String#format(String, Object...)} + */ + public SchedulingError(String format, Object... args) { + super(String.format(format, args)); + } + + } + public static enum SchedulingStrategy { EARLIEST, LATEST, LATEST_OUT_OF_LOOPS } @@ -169,8 +193,8 @@ /** * Sets {@link ScheduledNode#scheduledNext} on all scheduled nodes in all blocks using the - * scheduling built by @link {@link #run(StructuredGraph)}. This method should thus only be - * called when run has been successfully executed. + * scheduling built by {@link #run(StructuredGraph)}. This method should thus only be called + * when run has been successfully executed. */ public void scheduleGraph() { assert blockToNodesMap != null : "cannot set scheduledNext before run has been executed"; @@ -207,7 +231,9 @@ private void assignBlockToNodes(StructuredGraph graph, SchedulingStrategy strategy) { for (Block block : cfg.getBlocks()) { List nodes = new ArrayList<>(); - assert blockToNodesMap.get(block) == null; + if (blockToNodesMap.get(block) != null) { + throw new SchedulingError(); + } blockToNodesMap.put(block, nodes); for (FixedNode node : block.getNodes()) { nodes.add(node); @@ -234,8 +260,9 @@ } // PhiNodes and FixedNodes should already have been placed in blocks by // ControlFlowGraph.identifyBlocks - assert !(node instanceof PhiNode) : node; - assert !(node instanceof FixedNode) : node; + if (node instanceof PhiNode || node instanceof FixedNode) { + throw new SchedulingError("%s should already have been placed in a block", node); + } Block block; switch (strategy) { @@ -251,8 +278,10 @@ // schedule at the latest position possible in the outermost loop possible Block earliestBlock = earliestBlock(node); block = scheduleOutOfLoops(node, block, earliestBlock); - assert earliestBlock.dominates(block) : "Graph cannot be scheduled : inconsistent for " + node + ", " + node.usages().count() + " usages, (" + earliestBlock + - " needs to dominate " + block + ")"; + if (!earliestBlock.dominates(block)) { + throw new SchedulingError("%s: Graph cannot be scheduled : inconsistent for %s, %d usages, (%s needs to dominate %s)", node.graph(), node, node.usages().count(), + earliestBlock, block); + } } break; default: @@ -271,7 +300,9 @@ private Block latestBlock(ScheduledNode node, SchedulingStrategy strategy) { CommonDominatorBlockClosure cdbc = new CommonDominatorBlockClosure(null); for (Node succ : node.successors().nonNull()) { - assert cfg.getNodeToBlock().get(succ) != null; + if (cfg.getNodeToBlock().get(succ) == null) { + throw new SchedulingError(); + } cdbc.apply(cfg.getNodeToBlock().get(succ)); } ensureScheduledUsages(node, strategy); @@ -281,7 +312,9 @@ List usages = phantomUsages.get(node); if (usages != null) { for (FixedNode usage : usages) { - assert cfg.getNodeToBlock().get(usage) != null; + if (cfg.getNodeToBlock().get(usage) == null) { + throw new SchedulingError(); + } cdbc.apply(cfg.getNodeToBlock().get(usage)); } } @@ -331,7 +364,9 @@ */ BitSet dominators = new BitSet(cfg.getBlocks().length); - assert node.predecessor() == null; + if (node.predecessor() != null) { + throw new SchedulingError(); + } for (Node input : node.inputs().nonNull()) { assert input instanceof ValueNode; Block inputEarliest; @@ -356,7 +391,9 @@ } private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) { - assert latestBlock != null : "no latest : " + n; + if (latestBlock == null) { + throw new SchedulingError("no latest : %s", n); + } Block cur = latestBlock; Block result = latestBlock; while (cur.getLoop() != null && cur != earliest && cur.getDominator() != null) { @@ -378,7 +415,9 @@ * @param closure the closure that will be called for each block */ private void blocksForUsage(ScheduledNode node, Node usage, BlockClosure closure, SchedulingStrategy strategy) { - assert !(node instanceof PhiNode); + if (node instanceof PhiNode) { + throw new SchedulingError(node.toString()); + } if (usage instanceof PhiNode) { // An input to a PhiNode is used at the end of the predecessor block that corresponds to @@ -388,7 +427,9 @@ PhiNode phi = (PhiNode) usage; MergeNode merge = phi.merge(); Block mergeBlock = cfg.getNodeToBlock().get(merge); - assert mergeBlock != null : "no block for merge " + merge.toString(Verbosity.Id); + if (mergeBlock == null) { + throw new SchedulingError("no block for merge %s", merge.toString(Verbosity.Id)); + } for (int i = 0; i < phi.valueCount(); ++i) { if (phi.valueAt(i) == node) { if (mergeBlock.getPredecessorCount() <= i) { @@ -412,7 +453,9 @@ blocksForUsage(node, unscheduledUsage, closure, strategy); } else if (unscheduledUsage instanceof MergeNode) { // Only FrameStates can be connected to MergeNodes. - assert usage instanceof FrameState; + if (!(usage instanceof FrameState)) { + throw new SchedulingError(usage.toString()); + } // If a FrameState belongs to a MergeNode then it's inputs will be placed at the // common dominator of all EndNodes. for (Node pred : unscheduledUsage.cfgPredecessors()) { @@ -420,8 +463,12 @@ } } else { // For the time being, only FrameStates can be connected to StateSplits. - assert usage instanceof FrameState; - assert unscheduledUsage instanceof StateSplit; + if (!(usage instanceof FrameState)) { + throw new SchedulingError(usage.toString()); + } + if (!(unscheduledUsage instanceof StateSplit)) { + throw new SchedulingError(unscheduledUsage.toString()); + } // Otherwise: Put the input into the same block as the usage. assignBlockToNode((ScheduledNode) unscheduledUsage, strategy); closure.apply(cfg.getNodeToBlock().get(unscheduledUsage)); @@ -459,8 +506,12 @@ } private void sortNodesWithinBlock(Block b, NodeBitMap visited, SchedulingStrategy strategy) { - assert !visited.isMarked(b.getBeginNode()) && cfg.blockFor(b.getBeginNode()) == b; - assert !visited.isMarked(b.getEndNode()) && cfg.blockFor(b.getEndNode()) == b; + if (visited.isMarked(b.getBeginNode()) || cfg.blockFor(b.getBeginNode()) != b) { + throw new SchedulingError(); + } + if (visited.isMarked(b.getEndNode()) || cfg.blockFor(b.getEndNode()) != b) { + throw new SchedulingError(); + } List sortedInstructions; switch (strategy) { @@ -520,7 +571,9 @@ private void addUnscheduledToLatestSorting(Block b, VirtualState state, List sortedInstructions, NodeBitMap visited) { if (state != null) { // UnscheduledNodes should never be marked as visited. - assert !visited.isMarked(state); + if (visited.isMarked(state)) { + throw new SchedulingError(); + } for (Node input : state.inputs()) { if (input instanceof VirtualState) { diff -r dedc3f7d3033 -r 82d8fac3ad13 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Tue Apr 09 17:25:02 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Tue Apr 09 18:08:57 2013 +0200 @@ -24,17 +24,18 @@ import java.util.*; - import com.oracle.graal.api.code.CompilationResult.Call; import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.code.CompilationResult.Site; import com.oracle.graal.api.meta.*; -import com.oracle.graal.test.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; -import com.oracle.graal.replacements.test.CheckCastTest.*; +import com.oracle.graal.replacements.test.CheckCastTest.Depth12; +import com.oracle.graal.replacements.test.CheckCastTest.Depth13; +import com.oracle.graal.replacements.test.CheckCastTest.Depth14; +import com.oracle.graal.test.*; /** * Tests the implementation of instanceof, allowing profiling information to be manually specified. @@ -125,6 +126,7 @@ test("isMap", profile(), Object.class); test("isMap", profile(HashMap.class), Object.class); test("isMap", profile(TreeMap.class, HashMap.class), Object.class); + test("isMap", profile(String.class, HashMap.class), Object.class); } @LongTest @@ -150,6 +152,7 @@ test("isDepth12", profile(), o); test("isDepth12", profile(Depth13.class), o); test("isDepth12", profile(Depth13.class, Depth14.class), o); + test("isDepth12", profile(String.class, HashMap.class), o); } @LongTest