# HG changeset patch # User Michael Van De Vanter # Date 1423098151 28800 # Node ID b8b8f0fcb8c371581c74917e3b269ab005fb0e9e # Parent f10ca512eb40df3f9bc165e65ca7eaafb0f24aec# Parent 41af11212ed308e59dbd87fe1b5c4dfc790cbba3 Merge with 41af11212ed308e59dbd87fe1b5c4dfc790cbba3 diff -r f10ca512eb40 -r b8b8f0fcb8c3 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Wed Feb 04 17:02:31 2015 -0800 @@ -298,6 +298,8 @@ NodeMap canonicalId = graph.createNodeMap(); int nextId = 0; + List constantsLines = new ArrayList<>(); + StringBuilder result = new StringBuilder(); for (Block block : schedule.getCFG().getBlocks()) { result.append("Block " + block + " "); @@ -312,20 +314,36 @@ for (Node node : schedule.getBlockToNodesMap().get(block)) { if (node.isAlive()) { if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode)) { - int id; - if (canonicalId.get(node) != null) { - id = canonicalId.get(node); + if (node instanceof ConstantNode) { + String name = checkConstants ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); + String str = name + (excludeVirtual ? "\n" : " (" + node.getUsageCount() + ")\n"); + constantsLines.add(str); } else { - id = nextId++; - canonicalId.set(node, id); + int id; + if (canonicalId.get(node) != null) { + id = canonicalId.get(node); + } else { + id = nextId++; + canonicalId.set(node, id); + } + String name = node.getClass().getSimpleName(); + String str = " " + id + "|" + name + (excludeVirtual ? "\n" : " (" + node.getUsageCount() + ")\n"); + result.append(str); } - String name = node instanceof ConstantNode && checkConstants ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); - result.append(" " + id + "|" + name + (excludeVirtual ? "\n" : " (" + node.getUsageCount() + ")\n")); } } } } - return result.toString(); + + StringBuilder constantsLinesResult = new StringBuilder(); + constantsLinesResult.append(constantsLines.size() + " constants:\n"); + Collections.sort(constantsLines); + for (String s : constantsLines) { + constantsLinesResult.append(s); + constantsLinesResult.append("\n"); + } + + return constantsLines.toString() + result.toString(); } protected Backend getBackend() { diff -r f10ca512eb40 -r b8b8f0fcb8c3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Wed Feb 04 17:02:31 2015 -0800 @@ -26,11 +26,14 @@ import java.util.function.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.java.*; import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode; +import com.oracle.graal.java.GraphBuilderPlugins.InlineInvokePlugin; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; @@ -84,7 +87,12 @@ protected PhaseSuite createGraphBuilderSuite() { PhaseSuite suite = new PhaseSuite<>(); GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); - config = config.withInlineTrivial(true); + config.setInlineInvokePlugin(new InlineInvokePlugin() { + public boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth) { + return GraalOptions.InlineDuringParsing.getValue() && method.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && + depth < GraalOptions.InlineDuringParsingMaxDepth.getValue(); + } + }); suite.appendPhase(new GraphBuilderPhase(config)); return suite; } diff -r f10ca512eb40 -r b8b8f0fcb8c3 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Wed Feb 04 17:02:31 2015 -0800 @@ -36,9 +36,9 @@ private final ResolvedJavaType[] skippedExceptionTypes; private final DebugInfoMode debugInfoMode; private final boolean doLivenessAnalysis; - private final boolean inlineTrivial; private GraphBuilderPlugins.LoadFieldPlugin loadFieldPlugin; private GraphBuilderPlugins.ParameterPlugin parameterPlugin; + private GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin; public static enum DebugInfoMode { SafePointsOnly, @@ -64,41 +64,35 @@ Full, } - protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes, boolean doLivenessAnalysis, - boolean inlineTrivial) { + protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes, boolean doLivenessAnalysis) { this.eagerResolving = eagerResolving; this.omitAllExceptionEdges = omitAllExceptionEdges; this.debugInfoMode = debugInfoMode; this.skippedExceptionTypes = skippedExceptionTypes; this.doLivenessAnalysis = doLivenessAnalysis; - this.inlineTrivial = inlineTrivial; } public GraphBuilderConfiguration copy() { - GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis, inlineTrivial); + GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis); result.loadFieldPlugin = loadFieldPlugin; return result; } public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) { - return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis, inlineTrivial); + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis); } public GraphBuilderConfiguration withOmitAllExceptionEdges(boolean newOmitAllExceptionEdges) { - return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis, inlineTrivial); + return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis); } public GraphBuilderConfiguration withDebugInfoMode(DebugInfoMode newDebugInfoMode) { ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length); - return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newDebugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis, inlineTrivial); + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newDebugInfoMode, newSkippedExceptionTypes, doLivenessAnalysis); } public GraphBuilderConfiguration withDoLivenessAnalysis(boolean newLivenessAnalysis) { - return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis, inlineTrivial); - } - - public GraphBuilderConfiguration withInlineTrivial(boolean newInlineTrivial) { - return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, doLivenessAnalysis, newInlineTrivial); + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, debugInfoMode, skippedExceptionTypes, newLivenessAnalysis); } public GraphBuilderPlugins.LoadFieldPlugin getLoadFieldPlugin() { @@ -134,19 +128,19 @@ } public static GraphBuilderConfiguration getDefault() { - return new GraphBuilderConfiguration(false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), false); + return new GraphBuilderConfiguration(false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue()); } public static GraphBuilderConfiguration getEagerDefault() { - return new GraphBuilderConfiguration(true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), false); + return new GraphBuilderConfiguration(true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue()); } public static GraphBuilderConfiguration getSnippetDefault() { - return new GraphBuilderConfiguration(true, true, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), false); + return new GraphBuilderConfiguration(true, true, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptLivenessAnalysis.getValue()); } public static GraphBuilderConfiguration getFullDebugDefault() { - return new GraphBuilderConfiguration(true, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptLivenessAnalysis.getValue(), false); + return new GraphBuilderConfiguration(true, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptLivenessAnalysis.getValue()); } /** @@ -158,10 +152,6 @@ return eagerResolving; } - public boolean shouldInlineTrivial() { - return inlineTrivial; - } - public GraphBuilderPlugins.ParameterPlugin getParameterPlugin() { return parameterPlugin; } @@ -169,4 +159,12 @@ public void setParameterPlugin(GraphBuilderPlugins.ParameterPlugin parameterPlugin) { this.parameterPlugin = parameterPlugin; } + + public GraphBuilderPlugins.InlineInvokePlugin getInlineInvokePlugin() { + return inlineInvokePlugin; + } + + public void setInlineInvokePlugin(GraphBuilderPlugins.InlineInvokePlugin inlineInvokePlugin) { + this.inlineInvokePlugin = inlineInvokePlugin; + } } diff -r f10ca512eb40 -r b8b8f0fcb8c3 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 Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Feb 04 17:02:31 2015 -0800 @@ -42,7 +42,7 @@ import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.java.BciBlockMapping.LocalLiveness; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugins.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.calc.*; @@ -760,7 +760,18 @@ } } - private void appendInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args) { + private void appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) { + ResolvedJavaMethod targetMethod = initialTargetMethod; + InvokeKind invokeKind = initialInvokeKind; + if (initialInvokeKind.isIndirect()) { + ResolvedJavaType contextType = this.frameState.method.getDeclaringClass(); + ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(initialInvokeKind, args[0], initialTargetMethod, assumptions, contextType); + if (specialCallTarget != null) { + invokeKind = InvokeKind.Special; + targetMethod = specialCallTarget; + } + } + Kind resultType = targetMethod.getSignature().getReturnKind(); if (DeoptALot.getValue()) { append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint)); @@ -779,55 +790,26 @@ args[0] = TypeProfileProxyNode.proxify(args[0], profile); } } - if (GraalOptions.InlineDuringParsing.getValue() && invokeKind.isDirect()) { - if (graphBuilderPlugins != null) { - InvocationPlugin plugin = graphBuilderPlugins.lookupInvocation(targetMethod); - if (plugin != null) { - int beforeStackSize = frameState.stackSize; - if (plugin.apply(this, args)) { - assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize; - return; - } - assert beforeStackSize == frameState.stackSize; - } - } - - if (targetMethod.canBeInlined() && targetMethod.hasBytecodes()) { - if (targetMethod.getCode().length <= GraalOptions.TrivialInliningSize.getValue() && currentDepth < GraalOptions.InlineDuringParsingMaxDepth.getValue() && - graphBuilderConfig.shouldInlineTrivial()) { - BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, StructuredGraph.INVOCATION_ENTRY_BCI); - final FrameState[] lazyFrameState = new FrameState[1]; - HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, () -> { - if (lazyFrameState[0] == null) { - lazyFrameState[0] = frameState.create(bci()); - } - return lazyFrameState[0]; - }); - startFrameState.initializeFromArgumentsArray(args); - parser.build(currentDepth + 1, this.lastInstr, startFrameState); - - FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode(); - this.lastInstr = calleeBeforeReturnNode; - if (calleeBeforeReturnNode != null) { - ValueNode calleeReturnValue = parser.getReturnValue(); - if (calleeReturnValue != null) { - frameState.push(calleeReturnValue.getKind().getStackKind(), calleeReturnValue); - } - } - - FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode(); - if (calleeBeforeUnwindNode != null) { - ValueNode calleeUnwindValue = parser.getUnwindValue(); - assert calleeUnwindValue != null; - calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci())); - } - + if (graphBuilderPlugins != null) { + InvocationPlugin plugin = graphBuilderPlugins.lookupInvocation(targetMethod); + if (plugin != null) { + int beforeStackSize = frameState.stackSize; + if (plugin.apply(this, args)) { + assert beforeStackSize + resultType.getSlotCount() == frameState.stackSize; return; } + assert beforeStackSize == frameState.stackSize; } } + InlineInvokePlugin inlineInvokePlugin = graphBuilderConfig.getInlineInvokePlugin(); + if (inlineInvokePlugin != null && invokeKind.isDirect() && targetMethod.canBeInlined() && targetMethod.hasBytecodes() && + inlineInvokePlugin.shouldInlineInvoke(targetMethod, currentDepth)) { + parseAndInlineCallee(targetMethod, args); + return; + } + MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); // be conservative if information was not recorded (could result in endless @@ -842,6 +824,35 @@ } } + private void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args) { + BytecodeParser parser = new BytecodeParser(metaAccess, targetMethod, graphBuilderConfig, optimisticOpts, StructuredGraph.INVOCATION_ENTRY_BCI); + final FrameState[] lazyFrameState = new FrameState[1]; + HIRFrameStateBuilder startFrameState = new HIRFrameStateBuilder(targetMethod, currentGraph, () -> { + if (lazyFrameState[0] == null) { + lazyFrameState[0] = frameState.create(bci()); + } + return lazyFrameState[0]; + }); + startFrameState.initializeFromArgumentsArray(args); + parser.build(currentDepth + 1, this.lastInstr, startFrameState); + + FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode(); + this.lastInstr = calleeBeforeReturnNode; + if (calleeBeforeReturnNode != null) { + ValueNode calleeReturnValue = parser.getReturnValue(); + if (calleeReturnValue != null) { + frameState.push(calleeReturnValue.getKind().getStackKind(), calleeReturnValue); + } + } + + FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode(); + if (calleeBeforeUnwindNode != null) { + ValueNode calleeUnwindValue = parser.getUnwindValue(); + assert calleeUnwindValue != null; + calleeBeforeUnwindNode.setNext(handleException(calleeUnwindValue, bci())); + } + } + protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType) { return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType); } diff -r f10ca512eb40 -r b8b8f0fcb8c3 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Wed Feb 04 17:02:31 2015 -0800 @@ -45,6 +45,10 @@ FloatingNode interceptParameter(int index); } + public interface InlineInvokePlugin extends GraphBuilderPlugin { + boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth); + } + /** * Plugin for handling a method invocation. */ diff -r f10ca512eb40 -r b8b8f0fcb8c3 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 Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/StandardGraphBuilderPluginsProvider.java Wed Feb 04 17:02:31 2015 -0800 @@ -22,14 +22,21 @@ */ package com.oracle.graal.java; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.compiler.common.type.StampFactory.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; import com.oracle.graal.java.GraphBuilderPlugins.Registration; import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.type.*; /** * Provider of non-runtime specific {@link GraphBuilderPlugin}s. @@ -86,7 +93,14 @@ } public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.push(kind, builder.append(new UnboxNode(value, kind))); + ValueNode nonNullValue = value; + ObjectStamp receiverStamp = (ObjectStamp) value.stamp(); + if (!StampTool.isPointerNonNull(receiverStamp)) { + IsNullNode condition = builder.append(new IsNullNode(value)); + Stamp stamp = receiverStamp.join(objectNonNull()); + nonNullValue = builder.append(new GuardingPiNode(value, condition, true, NullCheckException, InvalidateReprofile, stamp)); + } + builder.push(kind.getStackKind(), builder.append(new UnboxNode(nonNullValue, kind))); return true; } diff -r f10ca512eb40 -r b8b8f0fcb8c3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/CallTargetNode.java Wed Feb 04 17:02:31 2015 -0800 @@ -55,6 +55,10 @@ public boolean isIndirect() { return !direct; } + + public boolean isInterface() { + return this == InvokeKind.Interface; + } } @Input protected NodeInputList arguments; diff -r f10ca512eb40 -r b8b8f0fcb8c3 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 Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Wed Feb 04 17:02:31 2015 -0800 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -93,67 +94,79 @@ } } + public static ResolvedJavaMethod findSpecialCallTarget(InvokeKind invokeKind, ValueNode receiver, ResolvedJavaMethod targetMethod, Assumptions assumptions, ResolvedJavaType contextType) { + if (invokeKind.isDirect()) { + return null; + } + + // check for trivial cases (e.g. final methods, nonvirtual methods) + if (targetMethod.canBeStaticallyBound()) { + return targetMethod; + } + + ResolvedJavaType type = StampTool.typeOrNull(receiver); + if (type == null && invokeKind == InvokeKind.Virtual) { + // For virtual calls, we are guaranteed to receive a correct receiver type. + type = targetMethod.getDeclaringClass(); + } + + if (type != null) { + /* + * either the holder class is exact, or the receiver object has an exact type, or it's + * an array type + */ + ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(targetMethod, contextType); + if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) { + return resolvedMethod; + } + if (assumptions != null && assumptions.useOptimisticAssumptions()) { + ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); + if (uniqueConcreteType != null) { + ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod, contextType); + if (methodFromUniqueType != null) { + assumptions.recordConcreteSubtype(type, uniqueConcreteType); + return methodFromUniqueType; + } + } + + ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod); + if (uniqueConcreteMethod != null) { + assumptions.recordConcreteMethod(targetMethod, type, uniqueConcreteMethod); + return uniqueConcreteMethod; + } + } + } + + return null; + } + @Override public void simplify(SimplifierTool tool) { - if (invokeKind().isIndirect()) { - // attempt to devirtualize the call + // attempt to devirtualize the call + ResolvedJavaType contextType = (invoke().stateAfter() == null && invoke().stateDuring() == null) ? null : invoke().getContextType(); + ResolvedJavaMethod specialCallTarget = findSpecialCallTarget(invokeKind, receiver(), targetMethod, tool.assumptions(), contextType); + if (specialCallTarget != null) { + this.setTargetMethod(specialCallTarget); + setInvokeKind(InvokeKind.Special); + return; + } - // check for trivial cases (e.g. final methods, nonvirtual methods) - if (targetMethod().canBeStaticallyBound()) { - setInvokeKind(InvokeKind.Special); - return; - } + if (invokeKind().isIndirect() && invokeKind().isInterface()) { // check if the type of the receiver can narrow the result ValueNode receiver = receiver(); - ResolvedJavaType type = StampTool.typeOrNull(receiver); - if (type == null && invokeKind == InvokeKind.Virtual) { - // For virtual calls, we are guaranteed to receive a correct receiver type. - type = targetMethod.getDeclaringClass(); - } - if (type != null && (invoke().stateAfter() != null || invoke().stateDuring() != null)) { - /* - * either the holder class is exact, or the receiver object has an exact type, or - * it's an array type - */ - ResolvedJavaMethod resolvedMethod = type.resolveConcreteMethod(targetMethod(), invoke().getContextType()); - if (resolvedMethod != null && (resolvedMethod.canBeStaticallyBound() || StampTool.isExactType(receiver) || type.isArray())) { - setInvokeKind(InvokeKind.Special); - setTargetMethod(resolvedMethod); - return; - } - if (tool.assumptions() != null && tool.assumptions().useOptimisticAssumptions()) { - ResolvedJavaType uniqueConcreteType = type.findUniqueConcreteSubtype(); - if (uniqueConcreteType != null) { - ResolvedJavaMethod methodFromUniqueType = uniqueConcreteType.resolveConcreteMethod(targetMethod(), invoke().getContextType()); - if (methodFromUniqueType != null) { - tool.assumptions().recordConcreteSubtype(type, uniqueConcreteType); - setInvokeKind(InvokeKind.Special); - setTargetMethod(methodFromUniqueType); - return; - } - } - ResolvedJavaMethod uniqueConcreteMethod = type.findUniqueConcreteMethod(targetMethod()); - if (uniqueConcreteMethod != null) { - tool.assumptions().recordConcreteMethod(targetMethod(), type, uniqueConcreteMethod); - setInvokeKind(InvokeKind.Special); - setTargetMethod(uniqueConcreteMethod); - return; - } - } - } // try to turn a interface call into a virtual call ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass(); /* * We need to check the invoke kind to avoid recursive simplification for virtual * interface methods calls. */ - if (declaredReceiverType.isInterface() && !invokeKind().equals(InvokeKind.Virtual)) { + if (declaredReceiverType.isInterface()) { tryCheckCastSingleImplementor(receiver, declaredReceiverType); } - if (invokeKind().equals(InvokeKind.Interface) && receiver instanceof UncheckedInterfaceProvider) { + if (receiver instanceof UncheckedInterfaceProvider) { UncheckedInterfaceProvider uncheckedInterfaceProvider = (UncheckedInterfaceProvider) receiver; Stamp uncheckedStamp = uncheckedInterfaceProvider.uncheckedStamp(); if (uncheckedStamp != null) { diff -r f10ca512eb40 -r b8b8f0fcb8c3 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 Wed Feb 04 16:38:09 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Wed Feb 04 17:02:31 2015 -0800 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.internal.*; @@ -59,6 +60,7 @@ import com.oracle.graal.truffle.phases.*; import com.oracle.graal.virtual.phases.ea.*; import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.nodes.*; /** @@ -175,12 +177,27 @@ } } + private class InlineInvokePlugin implements GraphBuilderPlugins.InlineInvokePlugin { + + public boolean shouldInlineInvoke(ResolvedJavaMethod method, int depth) { + return method.getAnnotation(TruffleBoundary.class) == null; + } + + } + @SuppressWarnings("unused") private void fastPartialEvaluation(OptimizedCallTarget callTarget, Assumptions assumptions, StructuredGraph graph, PhaseContext baseContext, HighTierContext tierContext) { GraphBuilderConfiguration newConfig = configForRoot.copy(); newConfig.setLoadFieldPlugin(new InterceptLoadFieldPlugin()); newConfig.setParameterPlugin(new InterceptReceiverPlugin(callTarget)); - new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), newConfig, TruffleCompilerImpl.Optimizations).apply(graph); + newConfig.setInlineInvokePlugin(new InlineInvokePlugin()); + DefaultGraphBuilderPlugins plugins = new DefaultGraphBuilderPlugins(); + Iterable sl = Services.load(GraphBuilderPluginsProvider.class); + for (GraphBuilderPluginsProvider p : sl) { + p.registerPlugins(providers.getMetaAccess(), plugins); + } + new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), newConfig, plugins, + TruffleCompilerImpl.Optimizations).apply(graph); Debug.dump(graph, "After FastPE"); }