# HG changeset patch # User Thomas Wuerthinger # Date 1366913449 -7200 # Node ID 9fde96e0c96b2e6a6eb60a5d688837e71b50ba43 # Parent 46f2b152d249f4d97ce068380f8f179bdf4c72d5# Parent 2e12f1719a42365f9b86f24b1f71e39086bd0f04 Merge. diff -r 2e12f1719a42 -r 9fde96e0c96b graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Apr 25 19:44:58 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Apr 25 20:10:49 2013 +0200 @@ -27,6 +27,7 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.hotspot.amd64.AMD64HotSpotUnwindOp.*; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.amd64.*; @@ -234,6 +235,7 @@ } else { assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); + assert !Modifier.isAbstract(resolvedMethod.getModifiers()) : "Cannot make direct call to abstract method."; Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant(); append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod)); } diff -r 2e12f1719a42 -r 9fde96e0c96b graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java diff -r 2e12f1719a42 -r 9fde96e0c96b graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Thu Apr 25 19:44:58 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Thu Apr 25 20:10:49 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.nodes.java; +import java.lang.reflect.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -102,6 +104,14 @@ for (Node n : usages()) { assertTrue(n instanceof Invoke, "call target can only be used from an invoke (%s)", n); } + if (invokeKind == InvokeKind.Special || invokeKind == InvokeKind.Static) { + assertFalse(Modifier.isAbstract(targetMethod.getModifiers()), "special calls or static calls are only allowed for concrete methods (%s)", targetMethod); + } + if (invokeKind == InvokeKind.Static) { + assertTrue(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for static methods (%s)", targetMethod); + } else { + assertFalse(Modifier.isStatic(targetMethod.getModifiers()), "static calls are only allowed for non-static methods (%s)", targetMethod); + } return super.verify(); } diff -r 2e12f1719a42 -r 9fde96e0c96b graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Thu Apr 25 19:44:58 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Thu Apr 25 20:10:49 2013 +0200 @@ -254,6 +254,10 @@ Class macroNodeClass = getMacroNodeClass(replacements, concrete); StructuredGraph graph = (StructuredGraph) invoke.asNode().graph(); if (macroNodeClass != null) { + if (((MethodCallTargetNode) invoke.callTarget()).targetMethod() != concrete) { + assert ((MethodCallTargetNode) invoke.callTarget()).invokeKind() != InvokeKind.Static; + InliningUtil.replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); + } FixedWithNextNode macroNode; try { macroNode = macroNodeClass.getConstructor(Invoke.class).newInstance(invoke); @@ -294,12 +298,12 @@ } }); } + } - protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) { - MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget(); - MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); - invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget); - } + public static void replaceInvokeCallTarget(Invoke invoke, StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) { + MethodCallTargetNode oldCallTarget = (MethodCallTargetNode) invoke.callTarget(); + MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); + invoke.asNode().replaceFirstInput(oldCallTarget, newCallTarget); } /** @@ -378,7 +382,7 @@ @Override public void tryToDevirtualizeInvoke(StructuredGraph graph, MetaAccessProvider runtime, Assumptions assumptions) { createGuard(graph, runtime); - replaceInvokeCallTarget(graph, InvokeKind.Special, concrete); + replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); } private void createGuard(StructuredGraph graph, MetaAccessProvider runtime) { @@ -730,7 +734,7 @@ ValueNode receiver = ((MethodCallTargetNode) invoke.callTarget()).receiver(); PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false); invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); - replaceInvokeCallTarget(graph, kind, target); + replaceInvokeCallTarget(invoke, graph, kind, target); } private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) { @@ -775,15 +779,13 @@ @Override public void inline(StructuredGraph graph, MetaAccessProvider runtime, Replacements replacements, InliningCallback callback, Assumptions assumptions) { assumptions.record(takenAssumption); - Debug.log("recording assumption: %s", takenAssumption); - super.inline(graph, runtime, replacements, callback, assumptions); } @Override public void tryToDevirtualizeInvoke(StructuredGraph graph, MetaAccessProvider runtime, Assumptions assumptions) { assumptions.record(takenAssumption); - replaceInvokeCallTarget(graph, InvokeKind.Special, concrete); + replaceInvokeCallTarget(invoke, graph, InvokeKind.Special, concrete); } @Override diff -r 2e12f1719a42 -r 9fde96e0c96b graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java Thu Apr 25 19:44:58 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BranchProbabilityNode.java Thu Apr 25 20:10:49 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.replacements.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -32,7 +33,7 @@ * the if node's taken probability. Then the branch probability node will be removed. This node is * intended primarily for snippets, so that they can define their fast and slow paths. */ -public class BranchProbabilityNode extends FixedWithNextNode implements Simplifiable { +public class BranchProbabilityNode extends FixedWithNextNode implements Simplifiable, Lowerable { public static final double LIKELY_PROBABILITY = 0.6; public static final double NOT_LIKELY_PROBABILITY = 1 - LIKELY_PROBABILITY; @@ -46,38 +47,56 @@ public static final double NOT_DEOPT_PATH_PROBABILITY = 0.999; public static final double DEOPT_PATH_PROBABILITY = 1 - NOT_DEOPT_PATH_PROBABILITY; - private final double probability; + @Input private ValueNode probability; - public BranchProbabilityNode(double probability) { + public BranchProbabilityNode(ValueNode probability) { super(StampFactory.forVoid()); - assert probability >= 0 && probability <= 1; this.probability = probability; } @Override public void simplify(SimplifierTool tool) { - FixedNode current = this; - while (!(current instanceof BeginNode)) { - current = (FixedNode) current.predecessor(); + if (probability.isConstant()) { + double probabilityValue = probability.asConstant().asDouble(); + if (probabilityValue < 0.0) { + throw new GraalInternalError("A negative probability of " + probabilityValue + " is not allowed!"); + } else if (probabilityValue > 1.0) { + throw new GraalInternalError("A probability of more than 1.0 (" + probabilityValue + ") is not allowed!"); + } + FixedNode current = this; + while (!(current instanceof BeginNode)) { + current = (FixedNode) current.predecessor(); + } + BeginNode begin = (BeginNode) current; + if (!(begin.predecessor() instanceof IfNode)) { + return; + } + IfNode ifNode = (IfNode) begin.predecessor(); + if (ifNode.trueSuccessor() == begin) { + ifNode.setTrueSuccessorProbability(probabilityValue); + } else { + ifNode.setTrueSuccessorProbability(1 - probabilityValue); + } + + FixedNode next = next(); + setNext(null); + ((FixedWithNextNode) predecessor()).setNext(next); + GraphUtil.killCFG(this); } - BeginNode begin = (BeginNode) current; - assert begin.predecessor() instanceof IfNode : "explicit branch probability cannot follow a merge, only if nodes"; - IfNode ifNode = (IfNode) begin.predecessor(); - if (ifNode.trueSuccessor() == begin) { - ifNode.setTrueSuccessorProbability(probability); - } else { - ifNode.setTrueSuccessorProbability(1 - probability); - } - - FixedNode next = next(); - setNext(null); - ((FixedWithNextNode) predecessor()).setNext(next); - GraphUtil.killCFG(this); } @SuppressWarnings("unused") @NodeIntrinsic - public static void probability(@ConstantNodeParameter double probability) { + public static void probability(double probability) { + } + + @Override + public void lower(LoweringTool tool, LoweringType loweringType) { + if (probability.isConstant()) { + throw new GraalInternalError("Injected branch probability must follow an if node."); + } else { + throw new GraalInternalError("Branch probability could not be injected, because the probability value did not reduce to a constant value."); + } } } diff -r 2e12f1719a42 -r 9fde96e0c96b graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Thu Apr 25 19:44:58 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Thu Apr 25 20:10:49 2013 +0200 @@ -71,6 +71,7 @@ StructuredGraph snippetGraph = getSnippetGraph(tool); InvokeNode invoke = replaceWithInvoke(); + assert invoke.verify(); if (snippetGraph != null) { InliningUtil.inline(invoke, snippetGraph, false); diff -r 2e12f1719a42 -r 9fde96e0c96b graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Thu Apr 25 19:44:58 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Thu Apr 25 20:10:49 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.api; +import java.lang.annotation.*; import java.util.concurrent.*; /** @@ -85,4 +86,13 @@ */ public static void bailout(String reason) { } + + /** + * Marks fields that should be considered final for a Truffle compilation although they are not + * final while executing in the interpreter. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public @interface CompilationFinal { + } }