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.CompilationIdentifier.INVALID_COMPILATION_ID; 26 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; 27 import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; 28 import static org.graalvm.compiler.core.common.GraalOptions.VerifyPhases; 29 30 import java.util.ListIterator; 31 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.GraalHotSpotVMConfig; 36 import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase; 37 import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; 38 import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; 39 import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase; 40 import org.graalvm.compiler.hotspot.phases.aot.AOTInliningPolicy; 41 import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; 42 import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase; 43 import org.graalvm.compiler.hotspot.phases.profiling.FinalizeProfileNodesPhase; 44 import org.graalvm.compiler.java.GraphBuilderPhase; 45 import org.graalvm.compiler.java.SuitesProviderBase; 46 import org.graalvm.compiler.lir.phases.LIRSuites; 47 import org.graalvm.compiler.nodes.EncodedGraph; 48 import org.graalvm.compiler.nodes.GraphEncoder; 49 import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; 50 import org.graalvm.compiler.nodes.StructuredGraph; 51 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 52 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; 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.LoopSafepointInsertionPhase; 60 import org.graalvm.compiler.phases.common.LoweringPhase; 61 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 62 import org.graalvm.compiler.phases.tiers.HighTierContext; 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 AddressLowering addressLowering; 75 private final SuitesCreator defaultSuitesCreator; 76 77 public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, AddressLowering addressLowering) { 78 this.defaultSuitesCreator = defaultSuitesCreator; 79 this.config = config; 80 this.runtime = runtime; 81 this.addressLowering = addressLowering; 82 this.defaultGraphBuilderSuite = createGraphBuilderSuite(); 83 } 84 85 @Override 86 public Suites createSuites() { 87 Suites ret = defaultSuitesCreator.createSuites(); 88 89 if (ImmutableCode.getValue()) { 90 // lowering introduces class constants, therefore it must be after lowering 91 ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config.classMirrorOffset, config.useCompressedOops ? config.getOopEncoding() : null)); 92 if (VerifyPhases.getValue()) { 93 ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); 94 } 95 if (GeneratePIC.getValue()) { 96 // EliminateRedundantInitializationPhase must happen before the first lowering. 97 ListIterator<BasePhase<? super HighTierContext>> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); 98 highTierLowering.previous(); 99 highTierLowering.add(new EliminateRedundantInitializationPhase()); 100 if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue()) { 101 highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue())); 102 } 103 ret.getMidTier().findPhase(LoopSafepointInsertionPhase.class).add(new ReplaceConstantNodesPhase()); 104 105 // Replace inlining policy 106 ListIterator<BasePhase<? super HighTierContext>> iter = ret.getHighTier().findPhase(InliningPhase.class); 107 InliningPhase inlining = (InliningPhase) iter.previous(); 108 CanonicalizerPhase canonicalizer = inlining.getCanonicalizer(); 109 iter.set(new InliningPhase(new AOTInliningPolicy(null), canonicalizer)); 110 } 111 } 112 113 ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase(config)); 114 if (VerifyPhases.getValue()) { 115 ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config)); 116 } 117 118 ret.getLowTier().findPhase(ExpandLogicPhase.class).add(new AddressLoweringPhase(addressLowering)); 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 canoncialization 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 SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), 144 context.getStampProvider(), !ImmutableCode.getValue(), runtime.getTarget().arch); 145 StructuredGraph targetGraph = new StructuredGraph(graph.method(), AllowAssumptions.YES, INVALID_COMPILATION_ID); 146 graphDecoder.decode(targetGraph, encodedGraph); 147 } 148 149 @Override 150 protected CharSequence getName() { 151 return "VerifyEncodingDecoding"; 152 } 153 }); 154 return true; 155 } 156 157 /** 158 * Modifies a given {@link GraphBuilderConfiguration} to record per node source information. 159 * 160 * @param gbs the current graph builder suite to modify 161 */ 162 public static PhaseSuite<HighTierContext> withNodeSourcePosition(PhaseSuite<HighTierContext> gbs) { 163 PhaseSuite<HighTierContext> newGbs = gbs.copy(); 164 GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); 165 GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); 166 GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig.withNodeSourcePosition(true)); 167 newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); 168 return newGbs; 169 } 170 171 @Override 172 public LIRSuites createLIRSuites() { 173 LIRSuites suites = defaultSuitesCreator.createLIRSuites(); 174 String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(); 175 if (profileInstructions != null) { 176 suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); 177 } 178 return suites; 179 } 180 }