Mercurial > hg > graal-jvmci-8
changeset 5399:c976c744c802
Merge.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 14 May 2012 22:07:14 +0200 |
parents | 17cddac1f2da (diff) 9b44497fef98 (current diff) |
children | 028c9ce0fc0f |
files | |
diffstat | 9 files changed, 175 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Fri May 11 16:38:22 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Mon May 14 22:07:14 2012 +0200 @@ -259,10 +259,10 @@ /** * Use HIR lowering instead of LIR lowering for checkcast instructions. - * Only checkcasts in methods in a class whose name contains this option will be HIR lowered. - * TDOD (dnsimon) remove once HIR checkcast lowering works reliably + * Only checkcasts in methods whose fully qualified name contains this option will be HIR lowered. + * TODO (dnsimon) remove once HIR checkcast lowering works reliably */ - public static String HIRLowerCheckcast; + public static String HIRLowerCheckcast = ""; /** * The profiling info cache directory.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Fri May 11 16:38:22 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoweringPhase.java Mon May 14 22:07:14 2012 +0200 @@ -44,9 +44,56 @@ this.runtime = runtime; this.assumptions = assumptions; } - @Override protected void run(final StructuredGraph graph) { + // Step 1: repeatedly lower fixed nodes until no new ones are created + NodeBitMap processed = graph.createNodeBitMap(); + while (true) { + int mark = graph.getMark(); + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true); + processBlock(cfg.getStartBlock(), graph.createNodeBitMap(), processed, null); + + if (graph.getNewNodes(mark).filter(FixedNode.class).isEmpty()) { + break; + } + graph.verify(); + processed.grow(); + } + + // Step 2: lower the floating nodes + processed.negate(); + final CiLoweringTool loweringTool = new CiLoweringTool() { + + @Override + public Node getGuardAnchor() { + throw new UnsupportedOperationException(); + } + + @Override + public GraalRuntime getRuntime() { + return runtime; + } + + @Override + public Node createGuard(Node condition, RiDeoptReason deoptReason, RiDeoptAction action, long leafGraphId) { + // TODO (thomaswue): Document why this must not be called on floating nodes. + throw new UnsupportedOperationException(); + } + + @Override + public CiAssumptions assumptions() { + return assumptions; + } + }; + for (Node node : processed) { + if (node instanceof Lowerable) { + assert !(node instanceof FixedNode) || node.predecessor() == null : node; + ((Lowerable) node).lower(loweringTool); + } + } + } + + protected void run0(final StructuredGraph graph) { ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, false, true, true); NodeBitMap processed = graph.createNodeBitMap(); @@ -138,7 +185,7 @@ FixedNode guardAnchor = (FixedNode) getGuardAnchor(); if (GraalOptions.OptEliminateGuards) { for (Node usage : condition.usages()) { - if (activeGuards.isMarked(usage)) { + if (!activeGuards.isNew(usage) && activeGuards.isMarked(usage)) { return usage; } } @@ -157,9 +204,11 @@ // Lower the instructions of this block. for (Node node : b.getNodes()) { - processed.mark(node); - if (node instanceof Lowerable) { - ((Lowerable) node).lower(loweringTool); + if (!processed.isMarked(node)) { + processed.mark(node); + if (node instanceof Lowerable) { + ((Lowerable) node).lower(loweringTool); + } } } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Fri May 11 16:38:22 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/util/InliningUtil.java Mon May 14 22:07:14 2012 +0200 @@ -40,7 +40,6 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.max.cri.ci.*; @@ -909,7 +908,6 @@ /** * Performs replacement of a node with a snippet graph. - * * @param replacee the node that will be replaced * @param anchor the control flow replacee * @param snippetGraph the graph that the replacee will be replaced with @@ -922,12 +920,11 @@ final StructuredGraph snippetGraph, final boolean explodeLoops, final IsImmutablePredicate immutabilityPredicate, - final CiLoweringTool tool, final Object... args) { Debug.scope("InliningSnippet", snippetGraph.method(), new Runnable() { @Override public void run() { - inlineSnippet0(runtime, replacee, anchor, snippetGraph, explodeLoops, immutabilityPredicate, tool, args); + inlineSnippet0(runtime, replacee, anchor, snippetGraph, explodeLoops, immutabilityPredicate, args); } }); } @@ -937,7 +934,7 @@ StructuredGraph snippetGraph, boolean explodeLoops, IsImmutablePredicate immutabilityPredicate, - CiLoweringTool tool, Object... args) { + Object... args) { Debug.dump(replacee.graph(), "Before lowering %s", replacee); @@ -1016,22 +1013,22 @@ Map<Node, Node> duplicates = graph.addDuplicates(nodes, replacements); Debug.dump(graph, "After inlining snippet %s", snippetCopy.method()); +// if (tool != null) { +// boolean innerLowering = false; +// for (Node node : duplicates.values()) { +// if (node instanceof Lowerable) { +// innerLowering = true; +// ((Lowerable) node).lower(tool); +// +// } +// } +// if (innerLowering) { +// Debug.dump(graph, "After inner lowering"); +// } +// } + // Remove all frame states from the inlined snippet graph. Snippets must be atomic (i.e. free // of side-effects that prevent deoptimizing to a point before the snippet). - if (tool != null) { - boolean innerLowering = false; - for (Node node : duplicates.values()) { - if (node instanceof Lowerable) { - innerLowering = true; - ((Lowerable) node).lower(tool); - - } - } - if (innerLowering) { - Debug.dump(graph, "After inner lowering"); - } - } - for (Node node : graph.getNewNodes(mark)) { if (node instanceof StateSplit) { StateSplit stateSplit = (StateSplit) node;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TypeCheckSlowPath.java Fri May 11 16:38:22 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TypeCheckSlowPath.java Mon May 14 22:07:14 2012 +0200 @@ -25,6 +25,7 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.target.amd64.*; +import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.type.*; @@ -48,7 +49,7 @@ } public TypeCheckSlowPath(ValueNode objectHub, ValueNode hub) { - super(StampFactory.forKind(CiKind.Object)); + super(StampFactory.forKind(CiKind.Boolean)); this.objectHub = objectHub; this.hub = hub; } @@ -56,14 +57,20 @@ @Override public void generate(LIRGenerator gen) { CiValue objectHubOpr = gen.operand(objectHub); - AMD64TypeCheckSlowPathOp op = new AMD64TypeCheckSlowPathOp(objectHubOpr, gen.operand(hub)); + Variable result = gen.newVariable(CiKind.Boolean); + AMD64TypeCheckSlowPathOp op = new AMD64TypeCheckSlowPathOp(result, objectHubOpr, gen.operand(hub)); gen.append(op); - gen.setResult(this, objectHubOpr); + gen.setResult(this, result); } + /** + * Checks if {@code objectHub} is a subclass of {@code hub}. + * + * @return {@code true} if {@code objectHub} is a subclass of {@code hub}, {@code false} otherwise + */ @SuppressWarnings("unused") @NodeIntrinsic - public static Object check(Object objectHub, Object hub) { + public static boolean check(Object objectHub, Object hub) { throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler"); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Fri May 11 16:38:22 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/ri/HotSpotRuntime.java Mon May 14 22:07:14 2012 +0200 @@ -412,7 +412,7 @@ memoryRead.dependencies().add(tool.createGuard(graph.unique(new NullCheckNode(objectClassNode.object(), false)), RiDeoptReason.NullCheckException, RiDeoptAction.InvalidateReprofile, StructuredGraph.INVALID_GRAPH_ID)); graph.replaceFixed(objectClassNode, memoryRead); } else if (n instanceof CheckCastNode) { - if (GraalOptions.HIRLowerCheckcast != null && graph.method() != null && graph.method().holder().name().contains(GraalOptions.HIRLowerCheckcast)) { + if (shouldLowerCheckcast(graph)) { final Map<CiConstant, CiConstant> hintHubsSet = new IdentityHashMap<>(); IsImmutablePredicate immutabilityPredicate = new IsImmutablePredicate() { public boolean apply(CiConstant constant) { @@ -433,7 +433,7 @@ hintHubsSet.put(hintHubsConst, hintHubsConst); Debug.log("Lowering checkcast in %s: node=%s, hintsHubs=%s, exact=%b", graph, checkcast, Arrays.toString(hints.types), hints.exact); - InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, tool, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact)); + InliningUtil.inlineSnippet(this, checkcast, checkcast, snippetGraph, true, immutabilityPredicate, hub, object, hintHubsConst, CiConstant.forBoolean(hints.exact)); new DeadCodeEliminationPhase().apply(graph); } } else { @@ -441,6 +441,18 @@ } } + private static boolean shouldLowerCheckcast(StructuredGraph graph) { + String option = GraalOptions.HIRLowerCheckcast; + if (option != null) { + if (option.length() == 0) { + return true; + } + RiResolvedMethod method = graph.method(); + return method != null && CiUtil.format("%H.%n", method).contains(option); + } + return false; + } + private IndexedLocationNode createArrayLocation(Graph graph, CiKind elementKind, ValueNode index) { return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Fri May 11 16:38:22 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Mon May 14 22:07:14 2012 +0200 @@ -46,7 +46,7 @@ return object; } } - if (hintsAreExact || TypeCheckSlowPath.check(objectHub, hub) == null) { + if (hintsAreExact || !TypeCheckSlowPath.check(objectHub, hub)) { DeoptimizeNode.deopt(RiDeoptAction.InvalidateReprofile, RiDeoptReason.ClassCastException); } return object;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TypeCheckSlowPathOp.java Fri May 11 16:38:22 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64TypeCheckSlowPathOp.java Mon May 14 22:07:14 2012 +0200 @@ -38,8 +38,8 @@ */ public class AMD64TypeCheckSlowPathOp extends AMD64LIRInstruction { - public AMD64TypeCheckSlowPathOp(CiValue objectHub, CiValue hub) { - super("TYPECHECK_SLOW", new CiValue[] {objectHub}, null, new CiValue[] {objectHub, hub}, NO_OPERANDS, NO_OPERANDS); + public AMD64TypeCheckSlowPathOp(CiValue result, CiValue objectHub, CiValue hub) { + super("TYPECHECK_SLOW", new CiValue[] {result}, null, new CiValue[] {objectHub, hub}, NO_OPERANDS, NO_OPERANDS); } @Override
--- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/LowerCheckCastTest.java Fri May 11 16:38:22 2012 +0200 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/LowerCheckCastTest.java Mon May 14 22:07:14 2012 +0200 @@ -30,28 +30,18 @@ import com.oracle.graal.nodes.java.*; import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.ri.RiTypeProfile.*; +import com.oracle.max.cri.ri.RiTypeProfile.ProfiledType; public class LowerCheckCastTest extends GraphTest { - static { - // Ensure that the methods to be compiled and executed are fully resolved - asNumber(0); - asString("0"); - asNumberExt(0); - asStringExt("0"); - } - - private RiCompiledMethod compile(String name, RiTypeProfile profile) { - //System.out.println("compiling: " + name + ", hints=" + Arrays.toString(hintClasses) + ", exact=" + exact); - - Method method = getMethod(name); + private RiCompiledMethod compile(Method method, RiTypeProfile profile) { final StructuredGraph graph = parse(method); CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); - assert ccn != null; - CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), ccn.targetClass(), ccn.object(), profile)); - graph.replaceFixedWithFixed(ccn, ccnNew); + if (ccn != null) { + CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.targetClassInstruction(), ccn.targetClass(), ccn.object(), profile)); + graph.replaceFixedWithFixed(ccn, ccnNew); + } final RiResolvedMethod riMethod = runtime.getRiMethod(method); CiTargetMethod targetMethod = runtime.compile(riMethod, graph); @@ -69,50 +59,78 @@ return new RiTypeProfile(0.0D, ptypes); } - private void test(String name, RiTypeProfile profile, Object expected, Object... args) { - RiCompiledMethod compiledMethod = compile(name, profile); - Assert.assertEquals(expected, compiledMethod.executeVarargs(args)); + private void test(String name, RiTypeProfile profile, Object... args) { + Method method = getMethod(name); + Object expect = null; + Throwable exception = null; + try { + // This gives us both the expected return value as well as ensuring that the method to be compiled is fully resolved + expect = method.invoke(null, args); + } catch (InvocationTargetException e) { + exception = e.getTargetException(); + } catch (Exception e) { + throw new RuntimeException(e); + } + RiCompiledMethod compiledMethod = compile(method, profile); + compiledMethod.method(); + + if (exception != null) { + try { + compiledMethod.executeVarargs(args); + Assert.fail("expected " + exception); + } catch (Throwable e) { + Assert.assertEquals(exception.getClass(), e.getClass()); + } + } else { + Object actual = compiledMethod.executeVarargs(args); + Assert.assertEquals(expect, actual); + } } @Test public void test1() { - test("asNumber", profile(), 111, 111); - test("asNumber", profile(Integer.class), 111, 111); - test("asNumber", profile(Long.class, Short.class), 111, 111); - test("asNumberExt", profile(), 121, 111); - test("asNumberExt", profile(Integer.class), 121, 111); - test("asNumberExt", profile(Long.class, Short.class), 121, 111); + test("asNumber", profile(), 111); + test("asNumber", profile(Integer.class), 111); + test("asNumber", profile(Long.class, Short.class), 111); + test("asNumberExt", profile(), 111); + test("asNumberExt", profile(Integer.class), 111); + test("asNumberExt", profile(Long.class, Short.class), 111); } @Test public void test2() { - test("asString", profile(), "111", "111"); - test("asString", profile(String.class), "111", "111"); - test("asString", profile(String.class), "111", "111"); + test("asString", profile(), "111"); + test("asString", profile(String.class), "111"); + test("asString", profile(String.class), "111"); - test("asStringExt", profile(), "#111", "111"); - test("asStringExt", profile(String.class), "#111", "111"); - test("asStringExt", profile(String.class), "#111", "111"); - } + final String nullString = null; + test("asString", profile(), nullString); + test("asString", profile(String.class), nullString); + test("asString", profile(String.class), nullString); - @Test(expected = ClassCastException.class) - public void test3() { - test("asNumber", profile(), 111, "111"); + test("asStringExt", profile(), "111"); + test("asStringExt", profile(String.class), "111"); + test("asStringExt", profile(String.class), "111"); } - @Test(expected = ClassCastException.class) - public void test4() { - test("asString", profile(String.class), "111", 111); + @Test + public void test3() { + test("asNumber", profile(), "111"); } - @Test(expected = ClassCastException.class) - public void test5() { - test("asNumberExt", profile(), 111, "111"); + @Test + public void test4() { + test("asString", profile(String.class), 111); } - @Test(expected = ClassCastException.class) + @Test + public void test5() { + test("asNumberExt", profile(), "111"); + } + + @Test public void test6() { - test("asStringExt", profile(String.class), "111", 111); + test("asStringExt", profile(String.class), 111); } public static Number asNumber(Object o) { @@ -132,4 +150,16 @@ String s = (String) o; return "#" + s; } + + @Test + public void test7() { + test("arrayFill", profile(), new Object[100], "111"); + } + + public static Object[] arrayFill(Object[] arr, Object value) { + for (int i = 0; i < arr.length; i++) { + arr[i] = value; + } + return arr; + } }
--- a/src/share/vm/graal/graalCompilerToVM.cpp Fri May 11 16:38:22 2012 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon May 14 22:07:14 2012 +0200 @@ -1047,7 +1047,7 @@ if (jap.get_ret_type() == T_VOID) { return NULL; - } else if (jap.get_ret_type() == T_OBJECT) { + } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) { return JNIHandles::make_local((oop) result.get_jobject()); } else { oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL);