1 /* 2 * Copyright (c) 2015, 2016, 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 package org.graalvm.compiler.hotspot.meta; 24 25 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 26 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; 27 import static org.graalvm.compiler.core.common.GraalOptions.VerifyPhases; 28 29 import java.util.ListIterator; 30 31 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 32 import org.graalvm.compiler.hotspot.HotSpotBackend; 33 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; 34 import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling; 35 import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase; 36 import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; 37 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; 38 import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase; 39 import org.graalvm.compiler.hotspot.phases.aot.AOTInliningPolicy; 40 import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; 41 import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase; 42 import org.graalvm.compiler.hotspot.phases.profiling.FinalizeProfileNodesPhase; 43 import org.graalvm.compiler.java.GraphBuilderPhase; 44 import org.graalvm.compiler.java.SuitesProviderBase; 45 import org.graalvm.compiler.lir.phases.LIRSuites; 46 import org.graalvm.compiler.nodes.EncodedGraph; 47 import org.graalvm.compiler.nodes.GraphEncoder; 48 import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; 49 import org.graalvm.compiler.nodes.StructuredGraph; 50 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 51 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 52 import org.graalvm.compiler.options.OptionValues; 53 import org.graalvm.compiler.phases.BasePhase; 54 import org.graalvm.compiler.phases.PhaseSuite; 55 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 56 import org.graalvm.compiler.phases.common.LoweringPhase; 57 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 58 import org.graalvm.compiler.phases.tiers.HighTierContext; 59 import org.graalvm.compiler.phases.tiers.MidTierContext; 60 import org.graalvm.compiler.phases.tiers.Suites; 61 import org.graalvm.compiler.phases.tiers.SuitesCreator; 62 63 /** 64 * HotSpot implementation of {@link SuitesCreator}. 65 */ 66 public class HotSpotSuitesProvider extends SuitesProviderBase { 67 68 protected final GraalHotSpotVMConfig config; 69 protected final HotSpotGraalRuntimeProvider runtime; 70 71 private final SuitesCreator defaultSuitesCreator; 72 73 public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime) { 74 this.defaultSuitesCreator = defaultSuitesCreator; 75 this.config = config; 76 this.runtime = runtime; 77 this.defaultGraphBuilderSuite = createGraphBuilderSuite(); 78 } 79 80 @Override 81 public Suites createSuites(OptionValues options) { 82 Suites ret = defaultSuitesCreator.createSuites(options); 83 84 if (ImmutableCode.getValue(options)) { 85 // lowering introduces class constants, therefore it must be after lowering 86 ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config)); 87 if (VerifyPhases.getValue(options)) { 88 ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); 89 } 90 if (GeneratePIC.getValue(options)) { 91 ListIterator<BasePhase<? super HighTierContext>> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); 92 highTierLowering.previous(); 93 highTierLowering.add(new EliminateRedundantInitializationPhase()); 94 if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { 95 highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); 96 } 97 ListIterator<BasePhase<? super MidTierContext>> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class); 98 midTierLowering.add(new ReplaceConstantNodesPhase()); 99 100 // Replace inlining policy 101 ListIterator<BasePhase<? super HighTierContext>> iter = ret.getHighTier().findPhase(InliningPhase.class); 102 InliningPhase inlining = (InliningPhase) iter.previous(); 103 CanonicalizerPhase canonicalizer = inlining.getCanonicalizer(); 104 iter.set(new InliningPhase(new AOTInliningPolicy(null), canonicalizer)); 105 } 106 } 107 108 ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase(config)); 109 if (VerifyPhases.getValue(options)) { 110 ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config)); 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(), AllowAssumptions.YES).method(graph.method()).build(); 137 SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(), 138 context.getConstantFieldProvider(), context.getStampProvider(), !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 return suites; 172 } 173 }