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.AddressLoweringPhase; 56 import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering; 57 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 58 import org.graalvm.compiler.phases.common.ExpandLogicPhase; 59 import org.graalvm.compiler.phases.common.FixReadsPhase; 60 import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; 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.LowTierContext; 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 AddressLowering addressLowering; 77 private final SuitesCreator defaultSuitesCreator; 78 79 public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, AddressLowering addressLowering) { 80 this.defaultSuitesCreator = defaultSuitesCreator; 81 this.config = config; 82 this.runtime = runtime; 83 this.addressLowering = addressLowering; 84 this.defaultGraphBuilderSuite = createGraphBuilderSuite(); 85 } 86 87 @Override 88 public Suites createSuites(OptionValues options) { 89 Suites ret = defaultSuitesCreator.createSuites(options); 90 91 if (ImmutableCode.getValue(options)) { 92 // lowering introduces class constants, therefore it must be after lowering 93 ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config.classMirrorOffset, config.useCompressedOops ? config.getOopEncoding() : null)); 94 if (VerifyPhases.getValue(options)) { 95 ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); 96 } 97 if (GeneratePIC.getValue(options)) { 98 // EliminateRedundantInitializationPhase must happen before the first lowering. 99 ListIterator<BasePhase<? super HighTierContext>> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); 100 highTierLowering.previous(); 101 highTierLowering.add(new EliminateRedundantInitializationPhase()); 102 if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { 103 highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); 104 } 105 ret.getMidTier().findPhase(LoopSafepointInsertionPhase.class).add(new ReplaceConstantNodesPhase()); 106 107 // Replace inlining policy 108 ListIterator<BasePhase<? super HighTierContext>> iter = ret.getHighTier().findPhase(InliningPhase.class); 109 InliningPhase inlining = (InliningPhase) iter.previous(); 110 CanonicalizerPhase canonicalizer = inlining.getCanonicalizer(); 111 iter.set(new InliningPhase(new AOTInliningPolicy(null), canonicalizer)); 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 ListIterator<BasePhase<? super LowTierContext>> findPhase = ret.getLowTier().findPhase(FixReadsPhase.class); 121 if (findPhase == null) { 122 findPhase = ret.getLowTier().findPhase(ExpandLogicPhase.class); 123 } 124 findPhase.add(new AddressLoweringPhase(addressLowering)); 125 126 return ret; 127 } 128 129 protected PhaseSuite<HighTierContext> createGraphBuilderSuite() { 130 PhaseSuite<HighTierContext> suite = defaultSuitesCreator.getDefaultGraphBuilderSuite().copy(); 131 assert appendGraphEncoderTest(suite); 132 return suite; 133 } 134 135 /** 136 * When assertions are enabled, we encode and decode every parsed graph, to ensure that the 137 * encoding and decoding process work correctly. The decoding performs canonicalization during 138 * decoding, so the decoded graph can be different than the encoded graph - we cannot check them 139 * for equality here. However, the encoder {@link GraphEncoder#verifyEncoding verifies the 140 * encoding itself}, i.e., performs a decoding without canonicalization and checks the graphs 141 * for equality. 142 */ 143 private boolean appendGraphEncoderTest(PhaseSuite<HighTierContext> suite) { 144 suite.appendPhase(new BasePhase<HighTierContext>() { 145 @Override 146 protected void run(StructuredGraph graph, HighTierContext context) { 147 EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); 148 149 SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), 150 context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions()), runtime.getTarget().arch); 151 StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), AllowAssumptions.YES).method(graph.method()).build(); 152 graphDecoder.decode(targetGraph, encodedGraph); 153 } 154 155 @Override 156 protected CharSequence getName() { 157 return "VerifyEncodingDecoding"; 158 } 159 }); 160 return true; 161 } 162 163 /** 164 * Modifies a given {@link GraphBuilderConfiguration} to record per node source information. 165 * 166 * @param gbs the current graph builder suite to modify 167 */ 168 public static PhaseSuite<HighTierContext> withNodeSourcePosition(PhaseSuite<HighTierContext> gbs) { 169 PhaseSuite<HighTierContext> newGbs = gbs.copy(); 170 GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); 171 GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); 172 GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig.withNodeSourcePosition(true)); 173 newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); 174 return newGbs; 175 } 176 177 @Override 178 public LIRSuites createLIRSuites(OptionValues options) { 179 LIRSuites suites = defaultSuitesCreator.createLIRSuites(options); 180 String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(options); 181 if (profileInstructions != null) { 182 suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); 183 } 184 return suites; 185 } 186 }