# HG changeset patch # User Thomas Wuerthinger # Date 1423597448 -3600 # Node ID 51b6ea17aebe1c85f8be6da206c0176bb7bafc56 # Parent 30c8d110b281e910298c553998ab3f6bbd450e96# Parent 5ff79efdd04004fbfec5bbd1b17f7ea716783085 Merge. diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Tue Feb 10 20:44:08 2015 +0100 @@ -63,6 +63,9 @@ @Option(help = "Inlines trivial methods during parsing of the bytecodes.", type = OptionType.Expert) public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(false); + @Option(help = "Traces .", type = OptionType.Debug) + public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); + @Option(help = "Maximum depth when inlining during parsing.", type = OptionType.Debug) public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Tue Feb 10 20:44:08 2015 +0100 @@ -65,6 +65,8 @@ public static final OptionValue SuppressZeroDebugValues = new OptionValue<>(false); @Option(help = "Send Graal IR to dump handlers on error", type = OptionType.Debug) public static final OptionValue DumpOnError = new OptionValue<>(false); + @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) + public static final OptionValue InterceptBailout = new OptionValue<>(false); @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) public static final OptionValue LogVerbose = new OptionValue<>(false); // @formatter:on @@ -254,7 +256,7 @@ @Override public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException) { + if (e instanceof BailoutException && !InterceptBailout.getValue()) { return null; } Debug.setConfig(Debug.fixedConfig(Debug.DEFAULT_LOG_LEVEL, Debug.DEFAULT_LOG_LEVEL, false, false, false, false, dumpHandlers, verifyHandlers, output)); diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Tue Feb 10 20:44:08 2015 +0100 @@ -67,7 +67,7 @@ @Override protected BytecodeFrame computeFrameForState(FrameState state) { - assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI; + assert state.bci >= 0 || state.bci == BytecodeFrame.BEFORE_BCI : state.bci; return super.computeFrameForState(state); } } diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Tue Feb 10 20:44:08 2015 +0100 @@ -24,6 +24,7 @@ package com.oracle.graal.java; import static com.oracle.graal.api.code.TypeCheckHints.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; import static com.oracle.graal.bytecode.Bytecodes.*; import java.util.*; @@ -604,9 +605,19 @@ protected abstract T createNewInstance(ResolvedJavaType type, boolean fillContents); + @SuppressWarnings("unchecked") void genNewInstance(int cpi) { JavaType type = lookupType(cpi, NEW); if (type instanceof ResolvedJavaType && ((ResolvedJavaType) type).isInitialized()) { + ResolvedJavaType[] skippedExceptionTypes = this.graphBuilderConfig.getSkippedExceptionTypes(); + if (skippedExceptionTypes != null) { + for (ResolvedJavaType exceptionType : skippedExceptionTypes) { + if (exceptionType.isAssignableFrom((ResolvedJavaType) type)) { + append((T) new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); + return; + } + } + } frameState.apush(append(createNewInstance((ResolvedJavaType) type, true))); } else { handleUnresolvedNewInstance(type); diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Tue Feb 10 20:44:08 2015 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; @@ -41,6 +42,8 @@ T append(T value); + T append(T value); + StampProvider getStampProvider(); MetaAccessProvider getMetaAccess(); @@ -49,6 +52,8 @@ ConstantReflectionProvider getConstantReflection(); + SnippetReflectionProvider getSnippetReflection(); + void push(Kind kind, ValueNode value); /** diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Feb 10 20:44:08 2015 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.TriState; +import com.oracle.graal.api.replacements.*; import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; @@ -77,7 +78,7 @@ @Override protected void run(StructuredGraph graph, HighTierContext context) { - new Instance(context.getMetaAccess(), context.getStampProvider(), context.getAssumptions(), context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins, + new Instance(context.getMetaAccess(), context.getStampProvider(), context.getAssumptions(), null, context.getConstantReflection(), graphBuilderConfig, graphBuilderPlugins, context.getOptimisticOptimizations()).run(graph); } @@ -103,6 +104,7 @@ private final StampProvider stampProvider; private final Assumptions assumptions; private final ConstantReflectionProvider constantReflection; + private final SnippetReflectionProvider snippetReflectionProvider; /** * Gets the graph being processed by this builder. @@ -111,8 +113,8 @@ return currentGraph; } - public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection, - GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) { + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, SnippetReflectionProvider snippetReflectionProvider, + ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; this.metaAccess = metaAccess; @@ -120,12 +122,13 @@ this.assumptions = assumptions; this.graphBuilderPlugins = graphBuilderPlugins; this.constantReflection = constantReflection; + this.snippetReflectionProvider = snippetReflectionProvider; assert metaAccess != null; } public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - this(metaAccess, stampProvider, assumptions, constantReflection, graphBuilderConfig, null, optimisticOpts); + this(metaAccess, stampProvider, assumptions, null, constantReflection, graphBuilderConfig, null, optimisticOpts); } @Override @@ -296,8 +299,9 @@ processBlock(this, returnBlock); processBlock(this, unwindBlock); - Debug.dump(currentGraph, "After bytecode parsing"); - + if (Debug.isDumpEnabled()) { + Debug.dump(currentGraph, "Bytecodes parsed: " + method.getDeclaringClass().getUnqualifiedName() + "." + method.getName()); + } } } @@ -522,7 +526,7 @@ @Override protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) { - return new SubNode(x, y); + return SubNode.create(x, y); } @Override @@ -532,12 +536,12 @@ @Override protected ValueNode genFloatAdd(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new AddNode(x, y); + return AddNode.create(x, y); } @Override protected ValueNode genFloatSub(Kind kind, ValueNode x, ValueNode y, boolean isStrictFP) { - return new SubNode(x, y); + return SubNode.create(x, y); } @Override @@ -664,12 +668,12 @@ @Override protected ValueNode createCheckCast(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck, boolean forStoreCheck) { - return new CheckCastNode(type, object, profileForTypeCheck, forStoreCheck); + return CheckCastNode.create(type, object, profileForTypeCheck, forStoreCheck); } @Override protected ValueNode createInstanceOf(ResolvedJavaType type, ValueNode object, JavaTypeProfile profileForTypeCheck) { - return new InstanceOfNode(type, object, profileForTypeCheck); + return InstanceOfNode.create(type, object, profileForTypeCheck); } @Override @@ -860,6 +864,12 @@ if (graphBuilderPlugins != null) { if (tryUsingInvocationPlugin(args, targetMethod, resultType)) { + if (GraalOptions.TraceInlineDuringParsing.getValue()) { + for (int i = 0; i < this.currentDepth; ++i) { + TTY.print(' '); + } + TTY.println("Used invocation plugin for " + targetMethod); + } return; } } @@ -867,8 +877,20 @@ InlineInvokePlugin inlineInvokePlugin = graphBuilderConfig.getInlineInvokePlugin(); if (inlineInvokePlugin != null && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes() && inlineInvokePlugin.shouldInlineInvoke(targetMethod, currentDepth)) { + if (GraalOptions.TraceInlineDuringParsing.getValue()) { + int bci = this.bci(); + for (int i = 0; i < this.currentDepth; ++i) { + TTY.print(' '); + } + StackTraceElement stackTraceElement = this.method.asStackTraceElement(bci); + String s = String.format("%s (%s:%d)", method.getName(), stackTraceElement.getFileName(), stackTraceElement.getLineNumber()); + TTY.print(s); + TTY.println(" inlining call " + targetMethod.getName()); + } parseAndInlineCallee(targetMethod, args); return; + } else { + // System.out.println("Could not inline invoke " + targetMethod); } MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); @@ -940,6 +962,15 @@ if (calleeBeforeUnwindNode != null) { ValueNode calleeUnwindValue = parser.getUnwindValue(); assert calleeUnwindValue != null; + if (calleeBeforeUnwindNode instanceof AbstractMergeNode) { + AbstractMergeNode mergeNode = (AbstractMergeNode) calleeBeforeUnwindNode; + HIRFrameStateBuilder dispatchState = frameState.copy(); + dispatchState.clearStack(); + dispatchState.apush(calleeUnwindValue); + dispatchState.setRethrowException(true); + mergeNode.setStateAfter(dispatchState.create(bci())); + + } calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci())); } } @@ -1063,8 +1094,13 @@ return ConstantNode.forConstant(constant, metaAccess, currentGraph); } + @SuppressWarnings("unchecked") @Override - protected ValueNode append(ValueNode v) { + public ValueNode append(ValueNode v) { + if (v.graph() != null) { + // This node was already appended to the graph. + return v; + } if (v instanceof ControlSinkNode) { return append((ControlSinkNode) v); } @@ -1675,6 +1711,10 @@ return constantReflection; } + public SnippetReflectionProvider getSnippetReflection() { + return snippetReflectionProvider; + } + } } } diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java Tue Feb 10 20:44:08 2015 +0100 @@ -88,7 +88,8 @@ } public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(kind.getStackKind(), builder.append(new UnboxNode(nullCheckedValue(builder, value), kind))); + ValueNode valueNode = UnboxNode.create(builder.getMetaAccess(), builder.getConstantReflection(), nullCheckedValue(builder, value), kind); + builder.push(kind.getStackKind(), builder.append(valueNode)); return true; } diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -52,9 +52,7 @@ } public PiNode(ValueNode object, Stamp stamp) { - super(stamp); - this.piStamp = stamp; - this.object = object; + this(object, stamp, null); } public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) { diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -165,32 +165,32 @@ return null; } - public static CompareNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { - return graph.unique(createCompareNode(condition, x, y)); + public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { + return graph.unique(createCompareNode(condition, x, y, constantReflection)); } - public static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) { + public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { assert x.getKind() == y.getKind(); assert condition.isCanonical() : "condition is not canonical: " + condition; assert !x.getKind().isNumericFloat(); - CompareNode comparison; + LogicNode comparison; if (condition == Condition.EQ) { if (x.stamp() instanceof AbstractObjectStamp) { - comparison = new ObjectEqualsNode(x, y); + comparison = ObjectEqualsNode.create(x, y, constantReflection); } else if (x.stamp() instanceof AbstractPointerStamp) { comparison = new PointerEqualsNode(x, y); } else { assert x.getKind().isNumericInteger(); - comparison = new IntegerEqualsNode(x, y); + comparison = IntegerEqualsNode.create(x, y, constantReflection); } } else if (condition == Condition.LT) { assert x.getKind().isNumericInteger(); - comparison = new IntegerLessThanNode(x, y); + comparison = IntegerLessThanNode.create(x, y, constantReflection); } else { assert condition == Condition.BT; assert x.getKind().isNumericInteger(); - comparison = new IntegerBelowNode(x, y); + comparison = IntegerBelowNode.create(x, y, constantReflection); } return comparison; diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -120,7 +120,7 @@ } public ConditionalNode(@InjectedNodeParameter StructuredGraph graph, Condition condition, ValueNode x, ValueNode y) { - this(createCompareNode(graph, condition, x, y)); + this(createCompareNode(graph, condition, x, y, null)); } public ConditionalNode(ValueNode type, ValueNode object) { diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -64,7 +64,7 @@ } if (forX.isConstant() && forX.asJavaConstant().asLong() == 0) { // 0 |<| y is the same as 0 != y - return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY)); + return new LogicNegationNode(CompareNode.createCompareNode(Condition.EQ, forX, forY, tool.getConstantReflection())); } return this; } diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -25,7 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; -import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.Sub; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; @@ -40,6 +40,17 @@ super(ArithmeticOpTable::getSub, x, y); } + public static ValueNode create(ValueNode x, ValueNode y) { + BinaryOp op = ArithmeticOpTable.forStamp(x.stamp()).getSub(); + Stamp stamp = op.foldStamp(x.stamp(), y.stamp()); + ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp); + if (tryConstantFold != null) { + return tryConstantFold; + } else { + return new SubNode(x, y); + } + } + @SuppressWarnings("hiding") @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnboxNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -31,15 +31,23 @@ import com.oracle.graal.nodes.spi.*; @NodeInfo -public class UnboxNode extends UnaryNode implements Virtualizable, Lowerable { +public final class UnboxNode extends UnaryNode implements Virtualizable, Lowerable { protected final Kind boxingKind; - public UnboxNode(ValueNode value, Kind boxingKind) { + protected UnboxNode(ValueNode value, Kind boxingKind) { super(StampFactory.forKind(boxingKind.getStackKind()), value); this.boxingKind = boxingKind; } + public static ValueNode create(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode value, Kind boxingKind) { + ValueNode synonym = findSynonym(metaAccess, constantReflection, value, boxingKind); + if (synonym != null) { + return synonym; + } + return new UnboxNode(value, boxingKind); + } + public Kind getBoxingKind() { return boxingKind; } @@ -63,11 +71,19 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode synonym = findSynonym(tool.getMetaAccess(), tool.getConstantReflection(), forValue, boxingKind); + if (synonym != null) { + return synonym; + } + return this; + } + + private static ValueNode findSynonym(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode forValue, Kind boxingKind) { if (forValue.isConstant()) { JavaConstant constant = forValue.asJavaConstant(); - JavaConstant unboxed = tool.getConstantReflection().unboxPrimitive(constant); + JavaConstant unboxed = constantReflection.unboxPrimitive(constant); if (unboxed != null && unboxed.getKind() == boxingKind) { - return ConstantNode.forConstant(unboxed, tool.getMetaAccess()); + return ConstantNode.forConstant(unboxed, metaAccess); } } else if (forValue instanceof BoxNode) { BoxNode box = (BoxNode) forValue; @@ -75,7 +91,7 @@ return box.getValue(); } } - return this; + return null; } @NodeIntrinsic diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -52,6 +52,11 @@ } public static ValueNode create(ValueNode forValue, ConstantReflectionProvider constantReflection) { + if (forValue instanceof NewArrayNode) { + NewArrayNode newArray = (NewArrayNode) forValue; + return newArray.length(); + } + ValueNode length = readArrayLengthConstant(forValue, constantReflection); if (length != null) { return length; diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -62,6 +62,14 @@ this.forStoreCheck = forStoreCheck; } + public static ValueNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) { + ValueNode synonym = findSynonym(type, object); + if (synonym != null) { + return synonym; + } + return new CheckCastNode(type, object, profile, forStoreCheck); + } + public boolean isForStoreCheck() { return forStoreCheck; } @@ -144,15 +152,9 @@ @Override public Node canonical(CanonicalizerTool tool) { - ResolvedJavaType objectType = StampTool.typeOrNull(object()); - if (objectType != null && type.isAssignableFrom(objectType)) { - // we don't have to check for null types here because they will also pass the - // checkcast. - return object(); - } - - if (StampTool.isPointerAlwaysNull(object())) { - return object(); + ValueNode synonym = findSynonym(type, object()); + if (synonym != null) { + return synonym; } if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { @@ -167,6 +169,20 @@ return this; } + private static ValueNode findSynonym(ResolvedJavaType type, ValueNode object) { + ResolvedJavaType objectType = StampTool.typeOrNull(object); + if (objectType != null && type.isAssignableFrom(objectType)) { + // we don't have to check for null types here because they will also pass the + // checkcast. + return object; + } + + if (StampTool.isPointerAlwaysNull(object)) { + return object; + } + return null; + } + @Override public void simplify(SimplifierTool tool) { // if the previous node is also a checkcast, with a less precise and compatible type, diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -46,6 +46,16 @@ assert type != null; } + public static LogicNode create(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { + ObjectStamp objectStamp = (ObjectStamp) object.stamp(); + LogicNode constantValue = findSynonym(type, objectStamp.type(), objectStamp.nonNull(), objectStamp.isExactType()); + if (constantValue != null) { + return constantValue; + } else { + return new InstanceOfNode(type, object, profile); + } + } + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); @@ -82,7 +92,25 @@ } private ValueNode checkInstanceOf(ValueNode forValue, ResolvedJavaType inputType, boolean nonNull, boolean exactType) { - boolean subType = type().isAssignableFrom(inputType); + ValueNode result = findSynonym(type(), inputType, nonNull, exactType); + if (result != null) { + return result; + } + if (type().isAssignableFrom(inputType)) { + if (!nonNull) { + // the instanceof matches if the object is non-null, so return true + // depending on the null-ness. + return new LogicNegationNode(new IsNullNode(forValue)); + } + } + return null; + } + + public static LogicNode findSynonym(ResolvedJavaType type, ResolvedJavaType inputType, boolean nonNull, boolean exactType) { + if (inputType == null) { + return null; + } + boolean subType = type.isAssignableFrom(inputType); if (subType) { if (nonNull) { // the instanceOf matches, so return true @@ -95,21 +123,14 @@ // also make the check fail. return LogicConstantNode.contradiction(); } else { - boolean superType = inputType.isAssignableFrom(type()); - if (!superType && !inputType.isInterface() && !type().isInterface()) { + boolean superType = inputType.isAssignableFrom(type); + if (!superType && !inputType.isInterface() && !type.isInterface()) { return LogicConstantNode.contradiction(); } // since the subtype comparison was only performed on a declared type we don't // really know if it might be true at run time... } } - if (type().isAssignableFrom(inputType)) { - if (!nonNull) { - // the instanceof matches if the object is non-null, so return true - // depending on the null-ness. - return new LogicNegationNode(new IsNullNode(forValue)); - } - } return null; } diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Tue Feb 10 20:44:08 2015 +0100 @@ -376,7 +376,7 @@ FixedNode lastSucc = successors[concretes.size()]; for (int i = concretes.size() - 1; i >= 0; --i) { LoadMethodNode method = graph.add(new LoadMethodNode(stampProvider.createMethodStamp(), concretes.get(i), receiverType, hub)); - CompareNode methodCheck = CompareNode.createCompareNode(graph, Condition.EQ, method, constantMethods[i]); + LogicNode methodCheck = CompareNode.createCompareNode(graph, Condition.EQ, method, constantMethods[i], null); IfNode ifNode = graph.add(new IfNode(methodCheck, successors[i], lastSucc, probability[i])); method.setNext(ifNode); lastSucc = method; diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/TypeGuardInlineInfo.java Tue Feb 10 20:44:08 2015 +0100 @@ -106,7 +106,7 @@ LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver)); ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(), type.getObjectHub(), providers.getMetaAccess(), graph); - CompareNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub); + LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection()); FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); assert invoke.predecessor() != null; diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InstanceOfSnippetsTemplates.java Tue Feb 10 20:44:08 2015 +0100 @@ -112,7 +112,7 @@ public static final class Instantiation { private ValueNode result; - private CompareNode condition; + private LogicNode condition; private ValueNode trueValue; private ValueNode falseValue; @@ -141,9 +141,9 @@ assert testValue.isConstant(); return LogicConstantNode.forBoolean(result.asConstant().equals(testValue.asConstant()), result.graph()); } - if (condition == null || condition.getY() != testValue) { + if (condition == null || (!(condition instanceof CompareNode)) || ((CompareNode) condition).getY() != testValue) { // Re-use previously generated condition if the trueValue for the test is the same - condition = createCompareNode(result.graph(), Condition.EQ, result, testValue); + condition = createCompareNode(result.graph(), Condition.EQ, result, testValue, null); } return condition; } diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedAssumption.java Tue Feb 10 20:44:08 2015 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; +import com.oracle.truffle.api.*; import com.oracle.truffle.api.CompilerDirectives.*; import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; @@ -50,7 +51,8 @@ @Override public void check() throws InvalidAssumptionException { - if (!isValid) { + if (!this.isValid()) { + CompilerDirectives.transferToInterpreterAndInvalidate(); throw new InvalidAssumptionException(); } } diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue Feb 10 20:44:08 2015 +0100 @@ -219,8 +219,10 @@ p.registerPlugins(providers.getMetaAccess(), plugins); } TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), plugins); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), newConfig, plugins, + long ms = System.currentTimeMillis(); + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(true), this.snippetReflection, providers.getConstantReflection(), newConfig, plugins, TruffleCompilerImpl.Optimizations).apply(graph); + System.out.println("# ms: " + (System.currentTimeMillis() - ms)); Debug.dump(graph, "After FastPE"); // Do single partial escape and canonicalization pass. diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Tue Feb 10 20:44:08 2015 +0100 @@ -68,7 +68,8 @@ private final TruffleCache truffleCache; private final GraalTruffleCompilationListener compilationNotify; - private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class, IllegalArgumentException.class}; + private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{UnexpectedResultException.class, SlowPathException.class, ArithmeticException.class, IllegalArgumentException.class, + VirtualMachineError.class, ClassCastException.class}; public static final OptimisticOptimizations Optimizations = OptimisticOptimizations.ALL.remove(OptimisticOptimizations.Optimization.UseExceptionProbability, OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints); diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadFinalNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -88,7 +88,7 @@ @Override public void lower(LoweringTool tool) { - CompareNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph())); + LogicNode compare = CompareNode.createCompareNode(graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, graph()), tool.getConstantReflection()); LocationIdentity locationIdentity; if (!location.isConstant() || location.isNullConstant()) { locationIdentity = LocationIdentity.ANY_LOCATION; diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/CustomizedUnsafeLoadMacroNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -63,7 +63,7 @@ } else { locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); } - CompareNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true)); + LogicNode compare = CompareNode.createCompareNode(Condition.EQ, conditionArgument, ConstantNode.forBoolean(true), tool.getConstantReflection()); Kind returnKind = this.getTargetMethod().getSignature().getReturnKind(); return new UnsafeLoadNode(objectArgument, offsetArgument, returnKind, locationIdentity, compare); } diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/UnsafeTypeCastMacroNode.java Tue Feb 10 20:44:08 2015 +0100 @@ -64,7 +64,7 @@ } else { Stamp piStamp = StampFactory.declaredTrusted(lookupJavaType, nonNullArgument.asJavaConstant().asInt() != 0); ConditionAnchorNode valueAnchorNode = graph().add( - new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph())))); + new ConditionAnchorNode(CompareNode.createCompareNode(graph(), Condition.EQ, conditionArgument, ConstantNode.forBoolean(true, graph()), tool.getConstantReflection()))); PiNode piCast = graph().unique(new PiNode(objectArgument, piStamp, valueAnchorNode)); replaceAtUsages(piCast); graph().replaceFixedWithFixed(this, valueAnchorNode); diff -r 5ff79efdd040 -r 51b6ea17aebe graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Tue Feb 10 16:03:45 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Tue Feb 10 20:44:08 2015 +0100 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.java.*; @@ -39,6 +40,7 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.nodes.*; +import com.oracle.graal.truffle.nodes.arithmetic.*; import com.oracle.graal.truffle.nodes.frame.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; @@ -49,8 +51,33 @@ public class TruffleGraphBuilderPlugins { public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + // OptimizedAssumption.class + Registration r = new Registration(plugins, metaAccess, OptimizedAssumption.class); + r.register1("isValid", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode arg) { + if (arg.isConstant()) { + Constant constant = arg.asConstant(); + OptimizedAssumption assumption = builder.getSnippetReflection().asObject(OptimizedAssumption.class, (JavaConstant) constant); + builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(assumption.isValid()))); + builder.getAssumptions().record(new AssumptionValidAssumption(assumption)); + } else { + throw new BailoutException("assumption could not be reduced to a constant"); + } + return true; + } + }); + + // ExactMath.class + r = new Registration(plugins, metaAccess, ExactMath.class); + r.register2("addExact", Integer.TYPE, Integer.TYPE, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode x, ValueNode y) { + builder.push(Kind.Int.getStackKind(), builder.append(new IntegerAddExactNode(x, y))); + return true; + } + }); + // CompilerDirectives.class - Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class); + r = new Registration(plugins, metaAccess, CompilerDirectives.class); r.register0("inInterpreter", new InvocationPlugin() { public boolean apply(GraphBuilderContext builder) { builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(false))); @@ -87,7 +114,7 @@ }); r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { - builder.append(new BranchProbabilityNode(probability, condition)); + builder.push(Kind.Boolean.getStackKind(), builder.append(new BranchProbabilityNode(probability, condition))); return true; } }); @@ -134,6 +161,7 @@ }); r.register4("unsafeCast", Object.class, Class.class, boolean.class, boolean.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull) { + System.out.println("unsafe cast with cond: " + condition + " clazz: " + clazz + " nonNull: " + nonNull); if (clazz.isConstant() && nonNull.isConstant()) { ConstantReflectionProvider constantReflection = builder.getConstantReflection(); ResolvedJavaType javaType = constantReflection.asJavaType(clazz.asConstant()); @@ -141,15 +169,24 @@ builder.push(Kind.Object, object); } else { Stamp piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0); - ConditionAnchorNode valueAnchorNode = builder.append(new ConditionAnchorNode(CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, - ConstantNode.forBoolean(true, object.graph())))); + LogicNode compareNode = CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), constantReflection); + boolean skipAnchor = false; + if (compareNode instanceof LogicConstantNode) { + LogicConstantNode logicConstantNode = (LogicConstantNode) compareNode; + if (logicConstantNode.getValue()) { + skipAnchor = true; + } + } + ConditionAnchorNode valueAnchorNode = null; + if (!skipAnchor) { + valueAnchorNode = builder.append(new ConditionAnchorNode(compareNode)); + } PiNode piCast = builder.append(new PiNode(object, piStamp, valueAnchorNode)); builder.push(Kind.Object, piCast); } return true; } - // TODO: should we throw GraalInternalError.shouldNotReachHere() here? - return false; + throw GraalInternalError.shouldNotReachHere("unsafeCast arguments could not reduce to a constant: " + clazz + ", " + nonNull); } }); for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}) { @@ -178,7 +215,7 @@ } else { locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); } - CompareNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()))); + LogicNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), builder.getConstantReflection())); builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); return true; }