# HG changeset patch # User Thomas Wuerthinger # Date 1376483272 -7200 # Node ID 2a26b86d7724f2ffba1d27d3c5caeaa9ee5d8c6d # Parent edf7e09ad382016ef879c59b1f126e57ed2cae40# Parent fcb4cf14a3c3a0bc98f36dc135c461540d134326 Merge. diff -r fcb4cf14a3c3 -r 2a26b86d7724 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Wed Aug 14 11:24:11 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Wed Aug 14 14:27:52 2013 +0200 @@ -488,16 +488,36 @@ ResolvedJavaType type = state.getNodeType(object); if (isNull || (type != null && checkCast.type().isAssignableFrom(type))) { boolean nonNull = state.isNonNull(object); - ValueAnchorNode anchor = graph.add(new ValueAnchorNode()); + GuardingNode replacementAnchor = null; + if (nonNull) { + // Search for valid instanceof anchor. + for (InstanceOfNode instanceOfNode : object.usages().filter(InstanceOfNode.class)) { + if (instanceOfNode.type() == checkCast.type() && state.trueConditions.containsKey(instanceOfNode)) { + ValueNode v = state.trueConditions.get(instanceOfNode); + if (v instanceof GuardingNode) { + replacementAnchor = (GuardingNode) v; + } + } + } + } + ValueAnchorNode anchor = null; + if (replacementAnchor == null) { + anchor = graph.add(new ValueAnchorNode()); + replacementAnchor = anchor; + } PiNode piNode; if (isNull) { ConstantNode nullObject = ConstantNode.forObject(null, metaAccessProvider, graph); - piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), anchor)); + piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), replacementAnchor)); } else { - piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), anchor)); + piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor)); } checkCast.replaceAtUsages(piNode); - graph.replaceFixedWithFixed(checkCast, anchor); + if (anchor != null) { + graph.replaceFixedWithFixed(checkCast, anchor); + } else { + graph.removeFixed(checkCast); + } metricCheckCastRemoved.increment(); } } else if (node instanceof IfNode) { diff -r fcb4cf14a3c3 -r 2a26b86d7724 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Wed Aug 14 11:24:11 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Wed Aug 14 14:27:52 2013 +0200 @@ -26,6 +26,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.graph.Graph.NodeChangedListener; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -34,11 +35,14 @@ public class IterativeConditionalEliminationPhase extends BasePhase { + private static final int MAX_ITERATIONS = 256; + @Override protected void run(StructuredGraph graph, PhaseContext context) { Set canonicalizationRoots = new HashSet<>(); ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(context.getRuntime()); Listener listener = new Listener(canonicalizationRoots); + int count = 0; while (true) { graph.trackInputChange(listener); eliminate.apply(graph); @@ -48,6 +52,9 @@ } new CanonicalizerPhase.Instance(context.getRuntime(), context.getAssumptions(), !AOTCompilation.getValue(), canonicalizationRoots, null).apply(graph); canonicalizationRoots.clear(); + if (++count > MAX_ITERATIONS) { + throw new BailoutException("Number of iterations in conditional elimination phase exceeds " + MAX_ITERATIONS); + } } } diff -r fcb4cf14a3c3 -r 2a26b86d7724 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 Wed Aug 14 11:24:11 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/CompilerDirectives.java Wed Aug 14 14:27:52 2013 +0200 @@ -152,6 +152,52 @@ } /** + * Associates the given type token with the given value for the case that condition is true. + * + * @param condition the custom type check + * @param value the value that is of the given custom type after the check + * @param customType the custom type that should be associated with the value + * @return the type check condition + */ + public static boolean customTypeCheck(boolean condition, Object value, Object customType) { + return condition; + } + + /** + * Treats the given value as a value of the given class. The class must evaluate to a constant. + * If the compiler can prove that the given value is of the given custom type, the cast is safe. + * + * @param value the value that is known to have the specified type + * @param clazz the specified type of the value + * @param customType the custom type that if present on a value makes this unsafe cast safe + * @return the value + */ + @SuppressWarnings("unchecked") + @Unsafe + public static T unsafeCast(Object value, Class clazz, Object customType) { + return (T) value; + } + + /** + * Proxies a sun.misc.Unsafe instance into an instance that adds a custom location identity on + * its accesses. This means that the accesses on these kind of location identities can only + * alias among themselves. It also allows to specify a custom type for the receiver values of + * follow-up unsafe accesses. Both the custom type and the location identity must evaluate to a + * constant. Furthermore, you should use the new sun.misc.Unsafe instance immediately for one + * read or write access via a sun.misc.Unsafe method and not store it anywhere. + * + * @param unsafe the instance of sun.misc.Unsafe + * @param customType the expected type of the receiver object of follow-up unsafe accesses + * @param locationIdentity the location identity token that can be used for improved global + * value numbering or null + * @return the accessed value + */ + @Unsafe + public static sun.misc.Unsafe unsafeCustomization(sun.misc.Unsafe unsafe, Object customType, Object locationIdentity) { + return unsafe; + } + + /** * Marks methods that are considered slowpath and should therefore not be inlined by default. */ @Retention(RetentionPolicy.RUNTIME)