# HG changeset patch # User Thomas Wuerthinger # Date 1423577446 -3600 # Node ID 637ca4d37bca01f0dcbf2e42f0e0e66ad451157e # Parent 1a7b33c96c0d8fcdcca2204d5b1fd3c249d0ebdf Extensions and fixes to inline and canonicalize during parsing. diff -r 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Tue Feb 10 15:10:46 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 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java Tue Feb 10 15:10:46 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 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Tue Feb 10 15:10:46 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 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/AbstractBytecodeParser.java Tue Feb 10 15:10:46 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 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Feb 10 15:10:46 2015 +0100 @@ -296,8 +296,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 +523,7 @@ @Override protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) { - return new SubNode(x, y); + return SubNode.create(x, y); } @Override @@ -532,12 +533,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 +665,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 +861,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 +874,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 +959,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())); } } @@ -1065,6 +1093,10 @@ @Override protected 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); } diff -r 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java Tue Feb 10 15:10:46 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 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Tue Feb 10 15:10:46 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 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue Feb 10 15:10:46 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 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfNode.java Tue Feb 10 15:10:46 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 1a7b33c96c0d -r 637ca4d37bca 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 Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Tue Feb 10 15:10:46 2015 +0100 @@ -66,7 +66,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 1a7b33c96c0d -r 637ca4d37bca graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java Fri Feb 06 16:49:34 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java Tue Feb 10 15:10:46 2015 +0100 @@ -88,7 +88,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; } });