1 /* 2 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.hotspot.meta; 26 27 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 28 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; 29 import static org.graalvm.compiler.core.common.GraalOptions.VerifyPhases; 30 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline; 31 32 import java.util.ListIterator; 33 34 import org.graalvm.compiler.debug.Assertions; 35 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 36 import org.graalvm.compiler.hotspot.HotSpotBackend; 37 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 38 import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling; 39 import org.graalvm.compiler.hotspot.lir.VerifyMaxRegisterSizePhase; 40 import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase; 41 import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; 42 import org.graalvm.compiler.hotspot.phases.aot.AOTInliningPolicy; 43 import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; 44 import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase; 45 import org.graalvm.compiler.hotspot.phases.profiling.FinalizeProfileNodesPhase; 46 import org.graalvm.compiler.java.GraphBuilderPhase; 47 import org.graalvm.compiler.java.SuitesProviderBase; 48 import org.graalvm.compiler.lir.phases.LIRSuites; 49 import org.graalvm.compiler.nodes.EncodedGraph; 50 import org.graalvm.compiler.nodes.GraphEncoder; 51 import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; 52 import org.graalvm.compiler.nodes.StructuredGraph; 53 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 54 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 55 import org.graalvm.compiler.options.OptionValues; 56 import org.graalvm.compiler.phases.BasePhase; 57 import org.graalvm.compiler.phases.PhaseSuite; 58 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 59 import org.graalvm.compiler.phases.common.LoweringPhase; 60 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 61 import org.graalvm.compiler.phases.tiers.HighTierContext; 62 import org.graalvm.compiler.phases.tiers.MidTierContext; 63 import org.graalvm.compiler.phases.tiers.Suites; 64 import org.graalvm.compiler.phases.tiers.SuitesCreator; 65 66 /** 67 * HotSpot implementation of {@link SuitesCreator}. 68 */ 69 public class HotSpotSuitesProvider extends SuitesProviderBase { 70 71 protected final GraalHotSpotVMConfig config; 72 protected final HotSpotGraalRuntimeProvider runtime; 73 74 private final SuitesCreator defaultSuitesCreator; 75 76 public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime) { 77 this.defaultSuitesCreator = defaultSuitesCreator; 78 this.config = config; 79 this.runtime = runtime; 80 this.defaultGraphBuilderSuite = createGraphBuilderSuite(); 81 } 82 83 @Override 84 public Suites createSuites(OptionValues options) { 85 Suites ret = defaultSuitesCreator.createSuites(options); 86 87 if (ImmutableCode.getValue(options)) { 88 // lowering introduces class constants, therefore it must be after lowering 89 ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config)); 90 if (VerifyPhases.getValue(options)) { 91 ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); 92 } 93 if (GeneratePIC.getValue(options)) { 94 ListIterator<BasePhase<? super HighTierContext>> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); 95 highTierLowering.previous(); 96 highTierLowering.add(new EliminateRedundantInitializationPhase()); 97 if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { 98 highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); 99 } 100 ListIterator<BasePhase<? super MidTierContext>> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class); 101 midTierLowering.add(new ReplaceConstantNodesPhase()); 102 103 // Replace inlining policy 104 if (Inline.getValue(options)) { 105 ListIterator<BasePhase<? super HighTierContext>> iter = ret.getHighTier().findPhase(InliningPhase.class); 106 InliningPhase inlining = (InliningPhase) iter.previous(); 107 CanonicalizerPhase canonicalizer = inlining.getCanonicalizer(); 108 iter.set(new InliningPhase(new AOTInliningPolicy(null), canonicalizer)); 109 } 110 } 111 } 112 113 return ret; 114 } 115 116 protected PhaseSuite<HighTierContext> createGraphBuilderSuite() { 117 PhaseSuite<HighTierContext> suite = defaultSuitesCreator.getDefaultGraphBuilderSuite().copy(); 118 assert appendGraphEncoderTest(suite); 119 return suite; 120 } 121 122 /** 123 * When assertions are enabled, we encode and decode every parsed graph, to ensure that the 124 * encoding and decoding process work correctly. The decoding performs canonicalization during 125 * decoding, so the decoded graph can be different than the encoded graph - we cannot check them 126 * for equality here. However, the encoder {@link GraphEncoder#verifyEncoding verifies the 127 * encoding itself}, i.e., performs a decoding without canonicalization and checks the graphs 128 * for equality. 129 */ 130 private boolean appendGraphEncoderTest(PhaseSuite<HighTierContext> suite) { 131 suite.appendPhase(new BasePhase<HighTierContext>() { 132 @Override 133 protected void run(StructuredGraph graph, HighTierContext context) { 134 EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); 135 136 StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), graph.getDebug(), AllowAssumptions.YES).method(graph.method()).trackNodeSourcePosition( 137 graph.trackNodeSourcePosition()).build(); 138 SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context, !ImmutableCode.getValue(graph.getOptions())); 139 graphDecoder.decode(encodedGraph); 140 } 141 142 @Override 143 protected CharSequence getName() { 144 return "VerifyEncodingDecoding"; 145 } 146 }); 147 return true; 148 } 149 150 /** 151 * Modifies a given {@link GraphBuilderConfiguration} to record per node source information. 152 * 153 * @param gbs the current graph builder suite to modify 154 */ 155 public static PhaseSuite<HighTierContext> withNodeSourcePosition(PhaseSuite<HighTierContext> gbs) { 156 PhaseSuite<HighTierContext> newGbs = gbs.copy(); 157 GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); 158 GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); 159 GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig.withNodeSourcePosition(true)); 160 newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); 161 return newGbs; 162 } 163 164 @Override 165 public LIRSuites createLIRSuites(OptionValues options) { 166 LIRSuites suites = defaultSuitesCreator.createLIRSuites(options); 167 String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(options); 168 if (profileInstructions != null) { 169 suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); 170 } 171 if (Assertions.detailedAssertionsEnabled(options)) { 172 suites.getPostAllocationOptimizationStage().appendPhase(new VerifyMaxRegisterSizePhase(config.maxVectorSize)); 173 } 174 return suites; 175 } 176 }