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.WriteBarrierAdditionPhase; 43 import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase; 44 import org.graalvm.compiler.hotspot.phases.aot.AOTInliningPolicy; 45 import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; 46 import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase; 47 import org.graalvm.compiler.hotspot.phases.profiling.FinalizeProfileNodesPhase; 48 import org.graalvm.compiler.java.GraphBuilderPhase; 49 import org.graalvm.compiler.java.SuitesProviderBase; 50 import org.graalvm.compiler.lir.phases.LIRSuites; 51 import org.graalvm.compiler.nodes.EncodedGraph; 52 import org.graalvm.compiler.nodes.GraphEncoder; 53 import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; 54 import org.graalvm.compiler.nodes.StructuredGraph; 55 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 56 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 57 import org.graalvm.compiler.options.OptionValues; 58 import org.graalvm.compiler.phases.BasePhase; 59 import org.graalvm.compiler.phases.PhaseSuite; 60 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 61 import org.graalvm.compiler.phases.common.LoweringPhase; 62 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 63 import org.graalvm.compiler.phases.tiers.HighTierContext; 64 import org.graalvm.compiler.phases.tiers.MidTierContext; 65 import org.graalvm.compiler.phases.tiers.Suites; 66 import org.graalvm.compiler.phases.tiers.SuitesCreator; 67 68 /** 69 * HotSpot implementation of {@link SuitesCreator}. 70 */ 71 public class HotSpotSuitesProvider extends SuitesProviderBase { 72 73 protected final GraalHotSpotVMConfig config; 74 protected final HotSpotGraalRuntimeProvider runtime; 75 76 private final SuitesCreator defaultSuitesCreator; 77 78 public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime) { 79 this.defaultSuitesCreator = defaultSuitesCreator; 80 this.config = config; 81 this.runtime = runtime; 82 this.defaultGraphBuilderSuite = createGraphBuilderSuite(); 83 } 84 85 @Override 86 public Suites createSuites(OptionValues options) { 87 Suites ret = defaultSuitesCreator.createSuites(options); 88 89 if (ImmutableCode.getValue(options)) { 90 // lowering introduces class constants, therefore it must be after lowering 91 ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config)); 92 if (VerifyPhases.getValue(options)) { 93 ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); 94 } 95 if (GeneratePIC.getValue(options)) { 96 ListIterator<BasePhase<? super HighTierContext>> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); 97 highTierLowering.previous(); 98 highTierLowering.add(new EliminateRedundantInitializationPhase()); 99 if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { 100 highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); 101 } 102 ListIterator<BasePhase<? super MidTierContext>> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class); 103 midTierLowering.add(new ReplaceConstantNodesPhase()); 104 105 // Replace inlining policy 106 if (Inline.getValue(options)) { 107 ListIterator<BasePhase<? super HighTierContext>> iter = ret.getHighTier().findPhase(InliningPhase.class); 108 InliningPhase inlining = (InliningPhase) iter.previous(); 109 CanonicalizerPhase canonicalizer = inlining.getCanonicalizer(); 110 iter.set(new InliningPhase(new AOTInliningPolicy(null), canonicalizer)); 111 } 112 } 113 } 114 115 ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase(config)); 116 if (VerifyPhases.getValue(options)) { 117 ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config)); 118 } 119 120 return ret; 121 } 122 123 protected PhaseSuite<HighTierContext> createGraphBuilderSuite() { 124 PhaseSuite<HighTierContext> suite = defaultSuitesCreator.getDefaultGraphBuilderSuite().copy(); 125 assert appendGraphEncoderTest(suite); 126 return suite; 127 } 128 129 /** 130 * When assertions are enabled, we encode and decode every parsed graph, to ensure that the 131 * encoding and decoding process work correctly. The decoding performs canonicalization during 132 * decoding, so the decoded graph can be different than the encoded graph - we cannot check them 133 * for equality here. However, the encoder {@link GraphEncoder#verifyEncoding verifies the 134 * encoding itself}, i.e., performs a decoding without canonicalization and checks the graphs 135 * for equality. 136 */ 137 private boolean appendGraphEncoderTest(PhaseSuite<HighTierContext> suite) { 138 suite.appendPhase(new BasePhase<HighTierContext>() { 139 @Override 140 protected void run(StructuredGraph graph, HighTierContext context) { 141 EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); 142 143 StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), graph.getDebug(), AllowAssumptions.YES).method(graph.method()).trackNodeSourcePosition( 144 graph.trackNodeSourcePosition()).build(); 145 SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(), 146 context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions())); 147 graphDecoder.decode(encodedGraph); 148 } 149 150 @Override 151 protected CharSequence getName() { 152 return "VerifyEncodingDecoding"; 153 } 154 }); 155 return true; 156 } 157 158 /** 159 * Modifies a given {@link GraphBuilderConfiguration} to record per node source information. 160 * 161 * @param gbs the current graph builder suite to modify 162 */ 163 public static PhaseSuite<HighTierContext> withNodeSourcePosition(PhaseSuite<HighTierContext> gbs) { 164 PhaseSuite<HighTierContext> newGbs = gbs.copy(); 165 GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); 166 GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); 167 GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig.withNodeSourcePosition(true)); 168 newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); 169 return newGbs; 170 } 171 172 @Override 173 public LIRSuites createLIRSuites(OptionValues options) { 174 LIRSuites suites = defaultSuitesCreator.createLIRSuites(options); 175 String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(options); 176 if (profileInstructions != null) { 177 suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); 178 } 179 if (Assertions.detailedAssertionsEnabled(options)) { 180 suites.getPostAllocationOptimizationStage().appendPhase(new VerifyMaxRegisterSizePhase(config.maxVectorSize)); 181 } 182 return suites; 183 } 184 }