Mercurial > hg > graal-compiler
changeset 22731:a3268580f915
support for optimization aware accurate bytecode based profiling
http://dag.inf.usi.ch/paper/oopsla15-zhengy.pdf
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Wed Sep 30 11:38:20 2015 +0200 @@ -311,4 +311,8 @@ return enabled; } }; + + @Option(help = "Enable compiler decision queries") + public static final OptionValue<Boolean> UseGraalQueries = new OptionValue<>(false); + }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Wed Sep 30 11:38:20 2015 +0200 @@ -24,6 +24,7 @@ import static com.oracle.graal.compiler.GraalCompilerOptions.EmitLIRRepeatCount; import static com.oracle.graal.compiler.common.GraalOptions.RegisterPressure; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; import static com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig.ALL_REGISTERS; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Optional; @@ -75,6 +76,7 @@ import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.common.DeadCodeEliminationPhase; +import com.oracle.graal.phases.common.query.ExtractICGPhase; import com.oracle.graal.phases.schedule.SchedulePhase; import com.oracle.graal.phases.tiers.HighTierContext; import com.oracle.graal.phases.tiers.LowTierContext; @@ -201,6 +203,9 @@ HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts); if (graph.start().next() == null) { graphBuilderSuite.apply(graph, highTierContext); + if (UseGraalQueries.getValue()) { + new ExtractICGPhase().apply(graph, highTierContext); + } new DeadCodeEliminationPhase(Optional).apply(graph); } else { Debug.dump(graph, "initial state");
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Wed Sep 30 11:38:20 2015 +0200 @@ -31,6 +31,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.OptConvertDeoptsToGuards; import static com.oracle.graal.compiler.common.GraalOptions.OptLoopTransform; import static com.oracle.graal.compiler.common.GraalOptions.PartialEscapeAnalysis; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; import static com.oracle.graal.compiler.phases.HighTier.Options.Inline; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Optional; import jdk.internal.jvmci.options.Option; @@ -49,6 +50,7 @@ import com.oracle.graal.phases.common.LoweringPhase; import com.oracle.graal.phases.common.RemoveValueProxyPhase; import com.oracle.graal.phases.common.inlining.InliningPhase; +import com.oracle.graal.phases.common.query.HighTierReconcileICGPhase; import com.oracle.graal.phases.tiers.HighTierContext; import com.oracle.graal.virtual.phases.ea.PartialEscapePhase; @@ -109,5 +111,8 @@ appendPhase(new RemoveValueProxyPhase()); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER)); + if (UseGraalQueries.getValue()) { + appendPhase(new HighTierReconcileICGPhase()); + } } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Wed Sep 30 11:38:20 2015 +0200 @@ -25,6 +25,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.ConditionalElimination; import static com.oracle.graal.compiler.common.GraalOptions.ImmutableCode; import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Required; import jdk.internal.jvmci.options.Option; import jdk.internal.jvmci.options.OptionType; @@ -40,6 +41,7 @@ import com.oracle.graal.phases.common.ProfileCompiledMethodsPhase; import com.oracle.graal.phases.common.RemoveValueProxyPhase; import com.oracle.graal.phases.common.UseTrappingNullChecksPhase; +import com.oracle.graal.phases.common.query.InlineICGPhase; import com.oracle.graal.phases.tiers.LowTierContext; public class LowTier extends PhaseSuite<LowTierContext> { @@ -64,6 +66,9 @@ } appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); + if (UseGraalQueries.getValue()) { + appendPhase(new InlineICGPhase()); + } appendPhase(new RemoveValueProxyPhase());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Wed Sep 30 11:38:20 2015 +0200 @@ -31,6 +31,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.OptPushThroughPi; import static com.oracle.graal.compiler.common.GraalOptions.OptReadElimination; import static com.oracle.graal.compiler.common.GraalOptions.ReassociateInvariants; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; import static com.oracle.graal.compiler.common.GraalOptions.VerifyHeapAtReturn; import com.oracle.graal.loop.phases.LoopSafepointEliminationPhase; @@ -52,6 +53,7 @@ import com.oracle.graal.phases.common.RemoveValueProxyPhase; import com.oracle.graal.phases.common.ValueAnchorCleanupPhase; import com.oracle.graal.phases.common.VerifyHeapAtReturnPhase; +import com.oracle.graal.phases.common.query.MidTierReconcileICGPhase; import com.oracle.graal.phases.tiers.MidTierContext; import com.oracle.graal.virtual.phases.ea.EarlyReadEliminationPhase; @@ -113,6 +115,9 @@ } appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); + if (UseGraalQueries.getValue()) { + appendPhase(new MidTierReconcileICGPhase()); + } appendPhase(new FrameStateAssignmentPhase());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/query/DelimitationAPI.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug.query; + +public class DelimitationAPI { + + /** + * Marks the beginning of the instrumentation boundary. - The target parameter indicates whether + * to associate the instrumentation with the preceding or the following base program IR node. + * Supported values are -1 (predecessor), 1 (successor)}. + */ + public static void instrumentationBegin(@SuppressWarnings("unused") int offset) { + } + + public static void instrumentationBegin(@SuppressWarnings("unused") int offset, @SuppressWarnings("unused") int type) { + } + + /** + * Marks the end of the instrumentation boundary. + */ + public static void instrumentationEnd() { + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/query/GraalQueryAPI.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug.query; + +/** + * NOTE that these queries return fixed constants in the interpreter mode. The Graal option + * RemoveNeverExecutedCode is switched off to prevent de-optimization. + */ +public final class GraalQueryAPI { + + // Static query intrinsics + + /** + * @return true if the enclosing method has been compiled by the dynamic compiler. + */ + public static boolean isMethodCompiled() { + return false; + } + + /** + * @return true if the enclosing method is inlined. + */ + public static boolean isMethodInlined() { + return false; + } + + /** + * @return the name of the root method for the current compilation task. If the enclosing method + * is inlined, this query returns the name of the method into which it is inlined. + */ + public static String getRootName() { + return "unknown"; + } + + // Dynamic query intrinsics + + public static final int ERROR = -1; + + /** + * @return the kind of heap allocation for a directly preceding allocation site. The possible + * return values are {ERROR(-1), TLAB(0), HEAP(1)}. While ERROR denotes either the + * utility is not supported, e.g. in interpreter, or if the allocation site was + * eliminated, the other two represent a TLAB allocation (fast path) or a direct heap + * allocation (slow path). + */ + public static int getAllocationType() { + return ERROR; + } + + /** + * @return the runtime lock type for a directly preceding lock site. The possible return values + * are {ERROR(-1), bias:existing(0), bias:acquired(1), bias:transfer(2), + * stub:revoke_or_stub:epoch-expired(3), stub:failed-cas(4), recursive(5), cas(6)}. + */ + public static int getLockType() { + return ERROR; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/query/SpecialIntrinsicGuard.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.debug.query; + +import jdk.internal.jvmci.meta.ResolvedJavaMethod; + +public class SpecialIntrinsicGuard { + + public static final String CN_DELIMITATIONAPI = DelimitationAPI.class.getName(); + public static final String CN_GRAALQUERYAPI = GraalQueryAPI.class.getName(); + + public static boolean isQueryIntrinsic(ResolvedJavaMethod method) { + String klass = method.getDeclaringClass().toJavaName(); + return CN_DELIMITATIONAPI.equals(klass) || CN_GRAALQUERYAPI.equals(klass); + } + +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java Wed Sep 30 11:38:20 2015 +0200 @@ -46,6 +46,7 @@ import com.oracle.graal.debug.TTY; import com.oracle.graal.debug.TopLevelDebugConfig; import com.oracle.graal.debug.internal.DebugScope; +import com.oracle.graal.debug.query.SpecialIntrinsicGuard; import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.graphbuilderconf.IntrinsicContext; @@ -108,8 +109,10 @@ HotSpotBackend backend = graalRuntime.getHostBackend(); HotSpotProviders providers = backend.getProviders(); final boolean isOSR = entryBCI != Compiler.INVOCATION_ENTRY_BCI; + // avoid compiling the intrinsic graphs for GraalQueryAPI methods + boolean bypassIntrinsic = method.isNative() || isOSR || SpecialIntrinsicGuard.isQueryIntrinsic(method); + StructuredGraph graph = bypassIntrinsic ? null : getIntrinsicGraph(method, providers); - StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers); if (graph == null) { SpeculationLog speculationLog = method.getSpeculationLog(); if (speculationLog != null) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/DelimitationAPISubstitutions.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import com.oracle.graal.api.replacements.ClassSubstitution; +import com.oracle.graal.api.replacements.MethodSubstitution; +import com.oracle.graal.debug.query.DelimitationAPI; +import com.oracle.graal.phases.common.query.nodes.InstrumentationBeginNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationEndNode; + +@ClassSubstitution(DelimitationAPI.class) +public class DelimitationAPISubstitutions { + + @MethodSubstitution(isStatic = true) + public static void instrumentationBegin(int target) { + InstrumentationBeginNode.instantiate(target, 0); + } + + @MethodSubstitution(isStatic = true) + public static void instrumentationBegin(int target, int type) { + InstrumentationBeginNode.instantiate(target, type); + } + + @MethodSubstitution(isStatic = true) + public static void instrumentationEnd() { + InstrumentationEndNode.instantiate(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/GraalQueryAPISubstitutions.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import com.oracle.graal.api.replacements.ClassSubstitution; +import com.oracle.graal.api.replacements.MethodSubstitution; +import com.oracle.graal.debug.query.GraalQueryAPI; +import com.oracle.graal.hotspot.replacements.query.GetRootNameNode; +import com.oracle.graal.hotspot.replacements.query.GetRuntimePathNode; +import com.oracle.graal.hotspot.replacements.query.IsMethodInlinedNode; + +@ClassSubstitution(GraalQueryAPI.class) +public class GraalQueryAPISubstitutions { + + @MethodSubstitution(isStatic = true) + public static boolean isMethodCompiled() { + return true; + } + + @MethodSubstitution(isStatic = true) + public static boolean isMethodInlined() { + return IsMethodInlinedNode.instantiate(); + } + + @MethodSubstitution(isStatic = true) + public static String getRootName() { + return GetRootNameNode.instantiate(); + } + + @MethodSubstitution(isStatic = true) + public static int getAllocationType() { + return GetRuntimePathNode.instantiate(); + } + + @MethodSubstitution(isStatic = true) + public static int getLockType() { + return GetRuntimePathNode.instantiate(); + } + +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java Wed Sep 30 11:38:20 2015 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; import jdk.internal.jvmci.code.TargetDescription; import jdk.internal.jvmci.meta.MetaAccessProvider; import jdk.internal.jvmci.service.ServiceProvider; @@ -29,6 +30,8 @@ import sun.reflect.Reflection; import com.oracle.graal.api.replacements.SnippetReflectionProvider; +import com.oracle.graal.debug.query.DelimitationAPI; +import com.oracle.graal.debug.query.GraalQueryAPI; import com.oracle.graal.nodes.spi.LoweringProvider; import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.nodes.spi.ReplacementsProvider; @@ -42,5 +45,9 @@ replacements.registerSubstitutions(Thread.class, ThreadSubstitutions.class); replacements.registerSubstitutions(Reflection.class, ReflectionSubstitutions.class); replacements.registerSubstitutions(ConstantPool.class, ConstantPoolSubstitutions.class); + if (UseGraalQueries.getValue()) { + replacements.registerSubstitutions(GraalQueryAPI.class, GraalQueryAPISubstitutions.class); + replacements.registerSubstitutions(DelimitationAPI.class, DelimitationAPISubstitutions.class); + } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/query/GetRootNameNode.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements.query; + +import jdk.internal.jvmci.hotspot.HotSpotObjectConstantImpl; +import jdk.internal.jvmci.hotspot.HotSpotResolvedObjectType; +import jdk.internal.jvmci.meta.Constant; +import jdk.internal.jvmci.meta.JavaKind; +import jdk.internal.jvmci.meta.ResolvedJavaMethod; + +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.ConstantNode; +import com.oracle.graal.nodes.FixedNode; +import com.oracle.graal.phases.common.query.nodes.GraalQueryNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; + +@NodeInfo +public final class GetRootNameNode extends GraalQueryNode { + + public static final NodeClass<GetRootNameNode> TYPE = NodeClass.create(GetRootNameNode.class); + + public GetRootNameNode() { + super(TYPE, StampFactory.exactNonNull(HotSpotResolvedObjectType.fromObjectClass(String.class))); + } + + @Override + public void onInlineICG(InstrumentationNode instrumentation, FixedNode position) { + ResolvedJavaMethod method = graph().method(); + String root = method.getDeclaringClass().toJavaName() + "." + method.getName() + method.getSignature().toMethodDescriptor(); + Constant constant = HotSpotObjectConstantImpl.forBoxedValue(JavaKind.Object, root); + ConstantNode constantNode = graph().unique(new ConstantNode(constant, stamp())); + graph().replaceFixedWithFloating(this, constantNode); + } + + @NodeIntrinsic + public static native String instantiate(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/query/GetRuntimePathNode.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements.query; + +import jdk.internal.jvmci.meta.JavaKind; + +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.graph.NodeFlood; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.AbstractEndNode; +import com.oracle.graal.nodes.AbstractMergeNode; +import com.oracle.graal.nodes.ConstantNode; +import com.oracle.graal.nodes.FixedNode; +import com.oracle.graal.nodes.LoopEndNode; +import com.oracle.graal.nodes.ValuePhiNode; +import com.oracle.graal.phases.common.query.nodes.GraalQueryNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; + +@NodeInfo +public final class GetRuntimePathNode extends GraalQueryNode { + + public static final NodeClass<GetRuntimePathNode> TYPE = NodeClass.create(GetRuntimePathNode.class); + + public GetRuntimePathNode() { + super(TYPE, StampFactory.forKind(JavaKind.Int)); + } + + private static boolean isCFGAccessible(FixedNode from, FixedNode to) { + NodeFlood flood = from.graph().createNodeFlood(); + flood.add(from); + for (Node current : flood) { + if (current instanceof LoopEndNode) { + continue; + } else if (current instanceof AbstractEndNode) { + flood.add(((AbstractEndNode) current).merge()); + } else { + flood.addAll(current.successors()); + } + } + return flood.isMarked(to); + } + + @Override + public void onInlineICG(InstrumentationNode instrumentation, FixedNode position) { + if (instrumentation.target() instanceof AbstractMergeNode) { + AbstractMergeNode merge = (AbstractMergeNode) instrumentation.target(); + + if (isCFGAccessible(merge, position)) { + ValuePhiNode phi = graph().addWithoutUnique(new ValuePhiNode(StampFactory.intValue(), merge)); + for (int i = 0; i < merge.cfgPredecessors().count(); i++) { + phi.addInput(ConstantNode.forInt(i, merge.graph())); + } + graph().replaceFixedWithFloating(this, phi); + return; + } + } + graph().replaceFixedWithFloating(this, ConstantNode.forInt(-1, graph())); + } + + @NodeIntrinsic + public static native int instantiate(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/query/IsMethodInlinedNode.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements.query; + +import jdk.internal.jvmci.meta.JavaKind; + +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.ConstantNode; +import com.oracle.graal.nodes.FixedNode; +import com.oracle.graal.phases.common.query.nodes.GraalQueryNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; + +@NodeInfo +public final class IsMethodInlinedNode extends GraalQueryNode { + + public static final NodeClass<IsMethodInlinedNode> TYPE = NodeClass.create(IsMethodInlinedNode.class); + + protected int original; + + public IsMethodInlinedNode() { + super(TYPE, StampFactory.forKind(JavaKind.Boolean)); + } + + @Override + public void onExtractICG(InstrumentationNode instrumentation) { + original = System.identityHashCode(instrumentation.graph()); + } + + @Override + public void onInlineICG(InstrumentationNode instrumentation, FixedNode position) { + graph().replaceFixedWithFloating(this, ConstantNode.forBoolean(original != System.identityHashCode(instrumentation.graph()), graph())); + } + + @NodeIntrinsic + public static native boolean instantiate(); + +}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/InliningUtil.java Wed Sep 30 11:38:20 2015 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.phases.common.inlining; import static com.oracle.graal.compiler.common.GraalOptions.HotSpotPrintInlining; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; import static jdk.internal.jvmci.meta.DeoptimizationAction.InvalidateReprofile; import static jdk.internal.jvmci.meta.DeoptimizationReason.NullCheckException; @@ -94,6 +95,7 @@ import com.oracle.graal.nodes.type.StampTool; import com.oracle.graal.nodes.util.GraphUtil; import com.oracle.graal.phases.common.inlining.info.InlineInfo; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; public class InliningUtil { @@ -363,6 +365,9 @@ unwindNode = (UnwindNode) duplicates.get(unwindNode); } + if (UseGraalQueries.getValue()) { + removeAttachedInstrumentation(invoke); + } finishInlining(invoke, graph, firstCFGNode, returnNodes, unwindNode, inlineGraph.getAssumptions(), inlineGraph, canonicalizedNodes); GraphUtil.killCFG(invokeNode); @@ -753,4 +758,24 @@ throw new GraalGraphJVMCIError(e).addContext(invoke.asNode()).addContext("macroSubstitution", macroNodeClass); } } + + // exclude InstrumentationNode for inlining heuristics + public static int getNodeCount(StructuredGraph graph) { + if (UseGraalQueries.getValue()) { + return graph.getNodeCount() - graph.getNodes().filter(InstrumentationNode.class).count(); + } else { + return graph.getNodeCount(); + } + } + + public static void removeAttachedInstrumentation(Invoke invoke) { + FixedNode invokeNode = invoke.asNode(); + for (InstrumentationNode instrumentation : invokeNode.usages().filter(InstrumentationNode.class)) { + if (instrumentation.target() == invoke) { + GraphUtil.unlinkFixedNode(instrumentation); + instrumentation.safeDelete(); + } + } + } + }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/MultiTypeGuardInlineInfo.java Wed Sep 30 11:38:20 2015 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.phases.common.inlining.info; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; + import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -241,6 +243,9 @@ assert invoke.next() == continuation; invoke.setNext(null); returnMerge.setNext(continuation); + if (UseGraalQueries.getValue()) { + InliningUtil.removeAttachedInstrumentation(invoke); + } if (returnValuePhi != null) { invoke.asNode().replaceAtUsages(returnValuePhi); }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/info/elem/InlineableGraph.java Wed Sep 30 11:38:20 2015 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.phases.common.inlining.info.elem; import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Optional; import java.util.ArrayList; @@ -44,6 +45,7 @@ import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.common.DeadCodeEliminationPhase; import com.oracle.graal.phases.common.inlining.InliningUtil; +import com.oracle.graal.phases.common.query.ExtractICGPhase; import com.oracle.graal.phases.graph.FixedNodeProbabilityCache; import com.oracle.graal.phases.tiers.HighTierContext; @@ -209,6 +211,9 @@ } assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite " + method + ", " + method.canBeInlined(); + if (UseGraalQueries.getValue()) { + new ExtractICGPhase().apply(newGraph, context); + } new DeadCodeEliminationPhase(Optional).apply(newGraph); if (OptCanonicalizer.getValue()) { @@ -223,7 +228,7 @@ @Override public int getNodeCount() { - return graph.getNodeCount(); + return InliningUtil.getNodeCount(graph); } @Override
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/GreedyInliningPolicy.java Wed Sep 30 11:38:20 2015 +0200 @@ -49,7 +49,7 @@ } public boolean continueInlining(StructuredGraph currentGraph) { - if (currentGraph.getNodeCount() >= MaximumDesiredSize.getValue()) { + if (InliningUtil.getNodeCount(currentGraph) >= MaximumDesiredSize.getValue()) { InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize"); metricInliningStoppedByMaxDesiredSize.increment(); return false;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/policy/InlineEverythingPolicy.java Wed Sep 30 11:38:20 2015 +0200 @@ -27,12 +27,13 @@ import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.spi.Replacements; +import com.oracle.graal.phases.common.inlining.InliningUtil; import com.oracle.graal.phases.common.inlining.walker.MethodInvocation; public class InlineEverythingPolicy implements InliningPolicy { public boolean continueInlining(StructuredGraph graph) { - if (graph.getNodeCount() >= MaximumDesiredSize.getValue()) { + if (InliningUtil.getNodeCount(graph) >= MaximumDesiredSize.getValue()) { throw new BailoutException("Inline all calls failed. The resulting graph is too large."); } return true;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/inlining/walker/ComputeInliningRelevance.java Wed Sep 30 11:38:20 2015 +0200 @@ -43,6 +43,7 @@ import com.oracle.graal.nodes.MergeNode; import com.oracle.graal.nodes.StartNode; import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.phases.common.inlining.InliningUtil; public class ComputeInliningRelevance { @@ -83,7 +84,7 @@ rootScope = new Scope(graph.start(), null); } else { if (nodeRelevances == null) { - nodeRelevances = Node.newIdentityMap(EXPECTED_MIN_INVOKE_COUNT + graph.getNodeCount() / EXPECTED_INVOKE_RATIO); + nodeRelevances = Node.newIdentityMap(EXPECTED_MIN_INVOKE_COUNT + InliningUtil.getNodeCount(graph) / EXPECTED_INVOKE_RATIO); } NodeWorkList workList = graph.createNodeWorkList(); Map<LoopBeginNode, Scope> loops = Node.newIdentityMap(EXPECTED_LOOP_COUNT);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/ExtractICGPhase.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query; + +import java.util.Map; + +import com.oracle.graal.debug.Debug; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeBitMap; +import com.oracle.graal.graph.NodeFlood; +import com.oracle.graal.graph.NodePosIterator; +import com.oracle.graal.graph.Position; +import com.oracle.graal.nodeinfo.InputType; +import com.oracle.graal.nodes.AbstractEndNode; +import com.oracle.graal.nodes.AbstractLocalNode; +import com.oracle.graal.nodes.CallTargetNode; +import com.oracle.graal.nodes.FixedNode; +import com.oracle.graal.nodes.FixedWithNextNode; +import com.oracle.graal.nodes.FrameState; +import com.oracle.graal.nodes.LoopEndNode; +import com.oracle.graal.nodes.ParameterNode; +import com.oracle.graal.nodes.ReturnNode; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.java.MonitorEnterNode; +import com.oracle.graal.nodes.java.MonitorIdNode; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.BasePhase; +import com.oracle.graal.phases.common.DeadCodeEliminationPhase; +import com.oracle.graal.phases.common.query.nodes.GraalQueryNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationBeginNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationEndNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; +import com.oracle.graal.phases.common.query.nodes.MonitorProxyNode; +import com.oracle.graal.phases.tiers.HighTierContext; + +public class ExtractICGPhase extends BasePhase<HighTierContext> { + + @Override + protected void run(StructuredGraph graph, HighTierContext context) { + for (InstrumentationBeginNode icgBegin : graph.getNodes().filter(InstrumentationBeginNode.class)) { + Instrumentation instrumentation = new Instrumentation(icgBegin); + InstrumentationNode instrumentationNode = instrumentation.createInstrumentationNode(); + + graph.addBeforeFixed(icgBegin, instrumentationNode); + Debug.dump(instrumentationNode.icg(), "After extracted ICG at " + instrumentation); + + instrumentation.unlink(); + } + + for (InstrumentationNode instrumentationNode : graph.getNodes().filter(InstrumentationNode.class)) { + for (GraalQueryNode query : instrumentationNode.icg().getNodes().filter(GraalQueryNode.class)) { + query.onExtractICG(instrumentationNode); + } + } + } + + static class Instrumentation { + + protected InstrumentationBeginNode icgBegin; + protected InstrumentationEndNode icgEnd; + protected ValueNode target; + protected NodeBitMap icgNodes; + + public Instrumentation(InstrumentationBeginNode icgBegin) { + this.icgBegin = icgBegin; + + resolveICGNodes(); + resolveTarget(); + } + + private static boolean shouldIncludeInput(Node node, NodeBitMap cfgNodes) { + if (node instanceof FloatingNode && !(node instanceof AbstractLocalNode)) { + NodePosIterator iterator = node.inputs().iterator(); + while (iterator.hasNext()) { + Position pos = iterator.nextPosition(); + if (pos.getInputType() == InputType.Value) { + continue; + } + if (!cfgNodes.isMarked(pos.get(node))) { + return false; + } + } + return true; + } + if (node instanceof CallTargetNode || node instanceof MonitorIdNode || node instanceof FrameState) { + return true; + } + return false; + } + + private void resolveICGNodes() { + NodeFlood icgCFG = icgBegin.graph().createNodeFlood(); + icgCFG.add(icgBegin.next()); + for (Node current : icgCFG) { + if (current instanceof InstrumentationEndNode) { + icgEnd = (InstrumentationEndNode) current; + } else if (current instanceof LoopEndNode) { + // do nothing + } else if (current instanceof AbstractEndNode) { + icgCFG.add(((AbstractEndNode) current).merge()); + } else { + icgCFG.addAll(current.successors()); + } + } + + NodeBitMap cfgNodes = icgCFG.getVisited(); + NodeFlood icgDFG = icgBegin.graph().createNodeFlood(); + icgDFG.addAll(cfgNodes); + for (Node current : icgDFG) { + if (current instanceof FrameState) { + continue; + } + for (Node input : current.inputs()) { + if (shouldIncludeInput(input, cfgNodes)) { + icgDFG.add(input); + } + } + } + icgNodes = icgDFG.getVisited(); + } + + private void resolveTarget() { + int offset = icgBegin.getOffset(); + if (offset < 0) { + Node pred = icgBegin; + while (offset < 0) { + pred = pred.predecessor(); + if (pred == null || !(pred instanceof FixedNode)) { + target = null; + return; + } + offset++; + } + target = (FixedNode) pred; + } else if (offset > 0) { + FixedNode next = icgEnd; + while (offset > 0) { + next = ((FixedWithNextNode) next).next(); + if (next == null || !(next instanceof FixedWithNextNode)) { + target = null; + return; + } + offset--; + } + target = next; + } + } + + public InstrumentationNode createInstrumentationNode() { + ValueNode newTarget = target; + // MonitorEnterNode may be deleted during PEA + if (newTarget instanceof MonitorEnterNode) { + newTarget = new MonitorProxyNode(newTarget, ((MonitorEnterNode) newTarget).getMonitorId()); + icgBegin.graph().addWithoutUnique(newTarget); + } + InstrumentationNode instrumentationNode = new InstrumentationNode(newTarget, icgBegin.getOffset(), icgBegin.getType()); + icgBegin.graph().addWithoutUnique(instrumentationNode); + // copy icg nodes to the InstrumentationNode instance + StructuredGraph icg = instrumentationNode.icg(); + Map<Node, Node> replacements = Node.newMap(); + int index = 0; + for (Node current : icgNodes) { + if (current instanceof FrameState) { + continue; + } + for (Node input : current.inputs()) { + if (!(input instanceof ValueNode)) { + continue; + } + if (!icgNodes.isMarked(input) && !replacements.containsKey(input)) { + ParameterNode parameter = new ParameterNode(index++, ((ValueNode) input).stamp()); + icg.addWithoutUnique(parameter); + replacements.put(input, parameter); + instrumentationNode.addInput(input); + } + } + } + replacements = icg.addDuplicates(icgNodes, icgBegin.graph(), icgNodes.count(), replacements); + icg.start().setNext((FixedNode) replacements.get(icgBegin.next())); + replacements.get(icgEnd).replaceAtPredecessor(icg.addWithoutUnique(new ReturnNode(null))); + + new DeadCodeEliminationPhase().apply(icg, false); + return instrumentationNode; + } + + public void unlink() { + FixedNode next = icgEnd.next(); + icgEnd.setNext(null); + icgBegin.replaceAtPredecessor(next); + GraphUtil.killCFG(icgBegin); + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/HighTierReconcileICGPhase.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query; + +import java.util.HashMap; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeFlood; +import com.oracle.graal.nodes.AbstractEndNode; +import com.oracle.graal.nodes.FixedWithNextNode; +import com.oracle.graal.nodes.LoopEndNode; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.java.AccessMonitorNode; +import com.oracle.graal.nodes.java.MonitorIdNode; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.nodes.virtual.AllocatedObjectNode; +import com.oracle.graal.nodes.virtual.CommitAllocationNode; +import com.oracle.graal.nodes.virtual.VirtualObjectNode; +import com.oracle.graal.phases.Phase; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; +import com.oracle.graal.phases.common.query.nodes.MonitorProxyNode; + +public class HighTierReconcileICGPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + for (CommitAllocationNode commit : graph.getNodes().filter(CommitAllocationNode.class)) { + InstrumentationAggregation aggregation = new InstrumentationAggregation(commit); + + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + aggregation.duplicateInstrumentationIfMatch(i -> i.target() == virtual, () -> getAllocatedObject(commit, virtual)); + } + + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + for (MonitorIdNode monitorId : commit.getLocks(objIndex)) { + aggregation.duplicateInstrumentationIfMatch(i -> i.target() instanceof MonitorProxyNode && ((MonitorProxyNode) i.target()).getMonitorId() == monitorId, () -> new MonitorProxyNode( + getAllocatedObject(commit, virtual), monitorId)); + } + } + } + + for (InstrumentationNode instrumentationNode : graph.getNodes().filter(InstrumentationNode.class)) { + ValueNode target = instrumentationNode.target(); + if (target instanceof VirtualObjectNode) { + // at this point, we can remove InstrumentationNode whose target is still virtual. + GraphUtil.unlinkFixedNode(instrumentationNode); + instrumentationNode.safeDelete(); + } else if (target instanceof MonitorProxyNode) { + MonitorProxyNode proxy = (MonitorProxyNode) target; + if (proxy.target() == null || proxy.target().isDeleted()) { + GraphUtil.unlinkFixedNode(instrumentationNode); + instrumentationNode.safeDelete(); + } else if (proxy.target() instanceof AccessMonitorNode) { + // unproxify the target of the InstrumentationNode. + instrumentationNode.replaceFirstInput(proxy, proxy.target()); + } + } + } + } + + class InstrumentationAggregation { + + protected CommitAllocationNode commit; + protected FixedWithNextNode insertingLocation; + + public InstrumentationAggregation(CommitAllocationNode commit) { + this.commit = commit; + this.insertingLocation = commit; + } + + public void insert(InstrumentationNode instrumentationNode) { + commit.graph().addAfterFixed(insertingLocation, instrumentationNode); + insertingLocation = instrumentationNode; + } + + public void duplicateInstrumentationIfMatch(Predicate<InstrumentationNode> guard, Supplier<ValueNode> newTargetSupplier) { + StructuredGraph graph = commit.graph(); + for (InstrumentationNode instrumentationNode : graph.getNodes().filter(InstrumentationNode.class)) { + // insert ICG only if the CommitAllocationNode is accessible from the + // instrumentation node + if (!(isCFGAccessible(instrumentationNode, commit) && guard.test(instrumentationNode))) { + continue; + } + InstrumentationNode clone = (InstrumentationNode) instrumentationNode.copyWithInputs(); + ValueNode newTarget = newTargetSupplier.get(); + if (!newTarget.isAlive()) { + graph.addWithoutUnique(newTarget); + } + clone.replaceFirstInput(clone.target(), newTarget); + updateVirtualInputs(clone); + insert(clone); + } + } + + private void updateVirtualInputs(InstrumentationNode clone) { + for (ValueNode input : clone.getWeakDependencies()) { + if ((input instanceof VirtualObjectNode) && (commit.getVirtualObjects().contains(input))) { + clone.replaceFirstInput(input, getAllocatedObject(commit, (VirtualObjectNode) input)); + } + } + } + + } + + private final HashMap<InstrumentationNode, NodeFlood> cachedNodeFloods = new HashMap<>(); + + private boolean isCFGAccessible(InstrumentationNode from, CommitAllocationNode to) { + // we only insert InstrumentationNode during this phase, so it is fine to reuse cached + // NodeFlood. + NodeFlood flood = cachedNodeFloods.get(from); + if (flood == null) { + flood = from.graph().createNodeFlood(); + flood.add(from); + for (Node current : flood) { + if (current instanceof LoopEndNode) { + continue; + } else if (current instanceof AbstractEndNode) { + flood.add(((AbstractEndNode) current).merge()); + } else { + flood.addAll(current.successors()); + } + } + cachedNodeFloods.put(from, flood); + } + return flood.isMarked(to); + } + + private static AllocatedObjectNode getAllocatedObject(CommitAllocationNode commit, VirtualObjectNode virtual) { + for (AllocatedObjectNode object : commit.graph().getNodes().filter(AllocatedObjectNode.class)) { + if (object.getCommit() == commit && object.getVirtualObject() == virtual) { + return object; + } + } + AllocatedObjectNode object = commit.graph().addWithoutUnique(new AllocatedObjectNode(virtual)); + object.setCommit(commit); + return object; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/InlineICGPhase.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query; + +import java.util.HashSet; +import java.util.Set; + +import com.oracle.graal.nodeinfo.InputType; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.memory.MemoryAnchorNode; +import com.oracle.graal.nodes.spi.LoweringTool; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.BasePhase; +import com.oracle.graal.phases.common.CanonicalizerPhase; +import com.oracle.graal.phases.common.FloatingReadPhase; +import com.oracle.graal.phases.common.FrameStateAssignmentPhase; +import com.oracle.graal.phases.common.GuardLoweringPhase; +import com.oracle.graal.phases.common.LoweringPhase; +import com.oracle.graal.phases.common.query.nodes.GraalQueryNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; +import com.oracle.graal.phases.tiers.LowTierContext; + +public class InlineICGPhase extends BasePhase<LowTierContext> { + + @Override + protected void run(StructuredGraph graph, LowTierContext context) { + // ICG may be shared amongst multiple InstrumentationNode + Set<StructuredGraph> icgs = new HashSet<>(); + for (InstrumentationNode instrumentationNode : graph.getNodes().filter(InstrumentationNode.class)) { + icgs.add(instrumentationNode.icg()); + } + for (StructuredGraph icg : icgs) { + new GuardLoweringPhase().apply(icg, null); + new FrameStateAssignmentPhase().apply(icg, false); + new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.LOW_TIER).apply(icg, context); + new FloatingReadPhase(true, true).apply(icg, false); + + MemoryAnchorNode anchor = icg.add(new MemoryAnchorNode()); + icg.start().replaceAtUsages(InputType.Memory, anchor); + if (anchor.hasNoUsages()) { + anchor.safeDelete(); + } else { + icg.addAfterFixed(icg.start(), anchor); + } + } + + for (InstrumentationNode instrumentationNode : graph.getNodes().filter(InstrumentationNode.class)) { + instrumentationNode.inlineAt(instrumentationNode); + + for (GraalQueryNode query : graph.getNodes().filter(GraalQueryNode.class)) { + query.onInlineICG(instrumentationNode, instrumentationNode); + } + + GraphUtil.unlinkFixedNode(instrumentationNode); + instrumentationNode.clearInputs(); + GraphUtil.killCFG(instrumentationNode); + } + + new CanonicalizerPhase().apply(graph, context); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/MidTierReconcileICGPhase.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query; + +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.extended.FixedValueAnchorNode; +import com.oracle.graal.nodes.java.AccessMonitorNode; +import com.oracle.graal.nodes.util.GraphUtil; +import com.oracle.graal.phases.Phase; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; +import com.oracle.graal.phases.common.query.nodes.MonitorProxyNode; + +public class MidTierReconcileICGPhase extends Phase { + + private static AccessMonitorNode unproxify(MonitorProxyNode proxy) { + for (AccessMonitorNode monitorEnter : proxy.getMonitorId().usages().filter(AccessMonitorNode.class)) { + if (monitorEnter.object() == proxy.target()) { + return monitorEnter; + } + } + return null; + } + + @Override + protected void run(StructuredGraph graph) { + for (InstrumentationNode instrumentationNode : graph.getNodes().filter(InstrumentationNode.class)) { + ValueNode target = instrumentationNode.target(); + if (target instanceof MonitorProxyNode) { + instrumentationNode.replaceFirstInput(target, unproxify((MonitorProxyNode) target)); + } else if (target instanceof FixedValueAnchorNode) { + instrumentationNode.replaceFirstInput(target, GraphUtil.unproxify(target)); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/nodes/GraalQueryNode.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query.nodes; + +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.FixedNode; +import com.oracle.graal.nodes.FixedWithNextNode; + +@NodeInfo +public abstract class GraalQueryNode extends FixedWithNextNode { + + public static final NodeClass<GraalQueryNode> TYPE = NodeClass.create(GraalQueryNode.class); + + public GraalQueryNode(NodeClass<? extends FixedWithNextNode> c, Stamp stamp) { + super(c, stamp); + } + + public void onExtractICG(@SuppressWarnings("unused") InstrumentationNode instrumentation) { + } + + public void onInlineICG(@SuppressWarnings("unused") InstrumentationNode instrumentation, @SuppressWarnings("unused") FixedNode position) { + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/nodes/InstrumentationBeginNode.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query.nodes; + +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.FixedWithNextNode; + +@NodeInfo +public final class InstrumentationBeginNode extends FixedWithNextNode { + + public static final NodeClass<InstrumentationBeginNode> TYPE = NodeClass.create(InstrumentationBeginNode.class); + + protected final int offset; + protected final int type; + + public InstrumentationBeginNode(int offset, int type) { + super(TYPE, StampFactory.forVoid()); + this.offset = offset; + this.type = type; + } + + public int getOffset() { + return offset; + } + + public int getType() { + return type; + } + + @NodeIntrinsic + public static native void instantiate(@ConstantNodeParameter int offset, @ConstantNodeParameter int type); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/nodes/InstrumentationEndNode.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query.nodes; + +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.FixedWithNextNode; + +@NodeInfo +public final class InstrumentationEndNode extends FixedWithNextNode { + + public static final NodeClass<InstrumentationEndNode> TYPE = NodeClass.create(InstrumentationEndNode.class); + + public InstrumentationEndNode() { + super(TYPE, StampFactory.forVoid()); + } + + @NodeIntrinsic + public static native void instantiate(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/nodes/InstrumentationNode.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query.nodes; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map; + +import jdk.internal.jvmci.meta.JavaConstant; +import jdk.internal.jvmci.meta.JavaKind; + +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.graph.Graph.DuplicationReplacement; +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.graph.NodeInputList; +import com.oracle.graal.nodeinfo.InputType; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.AbstractBeginNode; +import com.oracle.graal.nodes.AbstractMergeNode; +import com.oracle.graal.nodes.ConstantNode; +import com.oracle.graal.nodes.EndNode; +import com.oracle.graal.nodes.FixedNode; +import com.oracle.graal.nodes.FixedWithNextNode; +import com.oracle.graal.nodes.FrameState; +import com.oracle.graal.nodes.MergeNode; +import com.oracle.graal.nodes.ParameterNode; +import com.oracle.graal.nodes.ReturnNode; +import com.oracle.graal.nodes.StartNode; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.spi.Virtualizable; +import com.oracle.graal.nodes.spi.VirtualizerTool; +import com.oracle.graal.nodes.virtual.EscapeObjectState; +import com.oracle.graal.nodes.virtual.VirtualObjectNode; + +@NodeInfo +public class InstrumentationNode extends FixedWithNextNode implements Virtualizable { + + public static final NodeClass<InstrumentationNode> TYPE = NodeClass.create(InstrumentationNode.class); + + @OptionalInput(value = InputType.Association) protected ValueNode target; + @OptionalInput protected NodeInputList<ValueNode> weakDependencies; + + protected StructuredGraph icg; + protected final int offset; + protected final int type; + + public InstrumentationNode(ValueNode target, int offset, int type) { + super(TYPE, StampFactory.forVoid()); + + this.target = target; + this.icg = new StructuredGraph(AllowAssumptions.YES); + this.offset = offset; + this.type = type; + + this.weakDependencies = new NodeInputList<>(this); + } + + public boolean addInput(Node node) { + return weakDependencies.add(node); + } + + public ValueNode target() { + return target; + } + + public StructuredGraph icg() { + return icg; + } + + public int offset() { + return offset; + } + + public int type() { + return type; + } + + public NodeInputList<ValueNode> getWeakDependencies() { + return weakDependencies; + } + + public void virtualize(VirtualizerTool tool) { + // InstrumentationNode allows non-materialized inputs. During the inlining of the + // InstrumentationNode, non-materialized inputs will be replaced by null. + if (target != null) { + ValueNode alias = tool.getAlias(target); + if (alias instanceof VirtualObjectNode) { + tool.replaceFirstInput(target, alias); + } + } + for (ValueNode input : weakDependencies) { + ValueNode alias = tool.getAlias(input); + if (alias instanceof VirtualObjectNode) { + tool.replaceFirstInput(input, alias); + } + } + } + + public void inlineAt(FixedNode position) { + ArrayList<Node> nodes = new ArrayList<>(icg.getNodes().count()); + final StartNode entryPointNode = icg.start(); + FixedNode firstCFGNode = entryPointNode.next(); + ArrayList<ReturnNode> returnNodes = new ArrayList<>(4); + + for (Node icgnode : icg.getNodes()) { + if (icgnode == entryPointNode || icgnode == entryPointNode.stateAfter() || icgnode instanceof ParameterNode) { + // Do nothing. + } else { + nodes.add(icgnode); + if (icgnode instanceof ReturnNode) { + returnNodes.add((ReturnNode) icgnode); + } + } + } + + final AbstractBeginNode prevBegin = AbstractBeginNode.prevBegin(position); + DuplicationReplacement localReplacement = new DuplicationReplacement() { + + public Node replacement(Node replacement) { + if (replacement instanceof ParameterNode) { + ValueNode value = getWeakDependencies().get(((ParameterNode) replacement).index()); + if (value == null || value.isDeleted() || value instanceof VirtualObjectNode || value.stamp().getStackKind() != JavaKind.Object) { + return graph().unique(new ConstantNode(JavaConstant.NULL_POINTER, ((ParameterNode) replacement).stamp())); + } else { + return value; + } + } else if (replacement == entryPointNode) { + return prevBegin; + } + return replacement; + } + + }; + + Map<Node, Node> duplicates = graph().addDuplicates(nodes, icg, icg.getNodeCount(), localReplacement); + FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); + position.replaceAtPredecessor(firstCFGNodeDuplicate); + + if (!returnNodes.isEmpty()) { + if (returnNodes.size() == 1) { + ReturnNode returnNode = (ReturnNode) duplicates.get(returnNodes.get(0)); + returnNode.replaceAndDelete(position); + } else { + ArrayList<ReturnNode> returnDuplicates = new ArrayList<>(returnNodes.size()); + for (ReturnNode returnNode : returnNodes) { + returnDuplicates.add((ReturnNode) duplicates.get(returnNode)); + } + AbstractMergeNode merge = graph().add(new MergeNode()); + + for (ReturnNode returnNode : returnDuplicates) { + EndNode endNode = graph().add(new EndNode()); + merge.addForwardEnd(endNode); + returnNode.replaceAndDelete(endNode); + } + + merge.setNext(position); + } + } + + // since we may relocate InstrumentationNodes, the FrameState can be invalid + for (Node replacee : duplicates.values()) { + if (replacee instanceof FrameState) { + FrameState oldState = (FrameState) replacee; + FrameState newState = new FrameState(null, oldState.method(), oldState.bci, 0, 0, 0, oldState.rethrowException(), oldState.duringCall(), null, + Collections.<EscapeObjectState> emptyList()); + graph().addWithoutUnique(newState); + oldState.replaceAtUsages(newState); + } + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/query/nodes/MonitorProxyNode.java Wed Sep 30 11:38:20 2015 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.phases.common.query.nodes; + +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodeinfo.InputType; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.java.MonitorIdNode; + +@NodeInfo +public class MonitorProxyNode extends ValueNode { + + public static final NodeClass<MonitorProxyNode> TYPE = NodeClass.create(MonitorProxyNode.class); + + @OptionalInput(value = InputType.Association) protected ValueNode target; + @OptionalInput(value = InputType.Association) protected MonitorIdNode monitorId; + + public MonitorProxyNode(ValueNode target, MonitorIdNode monitorId) { + super(TYPE, StampFactory.forVoid()); + + this.target = target; + this.monitorId = monitorId; + } + + public ValueNode target() { + return target; + } + + public MonitorIdNode getMonitorId() { + return monitorId; + } + +}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed Sep 30 11:38:20 2015 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.replacements; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; import static com.oracle.graal.debug.Debug.applyFormattingFlagsAndWidth; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Required; import static com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates.UseSnippetTemplateCache; @@ -117,6 +118,7 @@ import com.oracle.graal.phases.common.GuardLoweringPhase; import com.oracle.graal.phases.common.LoweringPhase; import com.oracle.graal.phases.common.inlining.InliningUtil; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; import com.oracle.graal.phases.tiers.PhaseContext; import com.oracle.graal.phases.util.Providers; import com.oracle.graal.replacements.Snippet.ConstantParameter; @@ -1336,6 +1338,20 @@ updateStamps(replacee, duplicates); + if (UseGraalQueries.getValue()) { + for (InstrumentationNode instrumentation : replaceeGraph.getNodes().filter(InstrumentationNode.class)) { + if (instrumentation.target() == replacee) { + if (instrumentation.offset() < 0) { + ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode); + FixedWithNextNode pred = (FixedWithNextNode) returnDuplicate.predecessor(); + instrumentation.replaceFirstInput(replacee, pred); + } else { + instrumentation.replaceFirstInput(replacee, firstCFGNodeDuplicate); + } + } + } + } + rewireMemoryGraph(replacee, duplicates); // Replace all usages of the replacee with the value returned by the snippet
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Sep 29 22:19:45 2015 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Wed Sep 30 11:38:20 2015 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.virtual.phases.ea; +import static com.oracle.graal.compiler.common.GraalOptions.UseGraalQueries; + import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -71,6 +73,7 @@ import com.oracle.graal.nodes.spi.VirtualizableAllocation; import com.oracle.graal.nodes.spi.VirtualizerTool; import com.oracle.graal.nodes.virtual.VirtualObjectNode; +import com.oracle.graal.phases.common.query.nodes.InstrumentationNode; import com.oracle.graal.phases.schedule.SchedulePhase; public abstract class PartialEscapeClosure<BlockT extends PartialEscapeBlockState<BlockT>> extends EffectsClosure<BlockT> { @@ -187,6 +190,10 @@ return true; } } + if (UseGraalQueries.getValue() && (node instanceof InstrumentationNode)) { + // ignore inputs for InstrumentationNode + return false; + } processNodeInputs((ValueNode) node, nextFixedNode, state, effects); }