/*
 * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package org.graalvm.compiler.hotspot.meta;

import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
import static org.graalvm.compiler.core.common.GraalOptions.VerifyPhases;
import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;

import java.util.ListIterator;
import org.graalvm.compiler.debug.Assertions;

import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.HotSpotBackend;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling;
import org.graalvm.compiler.hotspot.lir.VerifyMaxRegisterSizePhase;
import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase;
import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase;
import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase;
import org.graalvm.compiler.hotspot.phases.WriteBarrierVerificationPhase;
import org.graalvm.compiler.hotspot.phases.aot.AOTInliningPolicy;
import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase;
import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase;
import org.graalvm.compiler.hotspot.phases.profiling.FinalizeProfileNodesPhase;
import org.graalvm.compiler.java.GraphBuilderPhase;
import org.graalvm.compiler.java.SuitesProviderBase;
import org.graalvm.compiler.lir.phases.LIRSuites;
import org.graalvm.compiler.nodes.EncodedGraph;
import org.graalvm.compiler.nodes.GraphEncoder;
import org.graalvm.compiler.nodes.SimplifyingGraphDecoder;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.phases.BasePhase;
import org.graalvm.compiler.phases.PhaseSuite;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.tiers.MidTierContext;
import org.graalvm.compiler.phases.tiers.Suites;
import org.graalvm.compiler.phases.tiers.SuitesCreator;

HotSpot implementation of SuitesCreator.
/** * HotSpot implementation of {@link SuitesCreator}. */
public class HotSpotSuitesProvider extends SuitesProviderBase { protected final GraalHotSpotVMConfig config; protected final HotSpotGraalRuntimeProvider runtime; private final SuitesCreator defaultSuitesCreator; public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime) { this.defaultSuitesCreator = defaultSuitesCreator; this.config = config; this.runtime = runtime; this.defaultGraphBuilderSuite = createGraphBuilderSuite(); } @Override public Suites createSuites(OptionValues options) { Suites ret = defaultSuitesCreator.createSuites(options); if (ImmutableCode.getValue(options)) { // lowering introduces class constants, therefore it must be after lowering ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config)); if (VerifyPhases.getValue(options)) { ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); } if (GeneratePIC.getValue(options)) { ListIterator<BasePhase<? super HighTierContext>> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); highTierLowering.previous(); highTierLowering.add(new EliminateRedundantInitializationPhase()); if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); } ListIterator<BasePhase<? super MidTierContext>> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class); midTierLowering.add(new ReplaceConstantNodesPhase()); // Replace inlining policy if (Inline.getValue(options)) { ListIterator<BasePhase<? super HighTierContext>> iter = ret.getHighTier().findPhase(InliningPhase.class); InliningPhase inlining = (InliningPhase) iter.previous(); CanonicalizerPhase canonicalizer = inlining.getCanonicalizer(); iter.set(new InliningPhase(new AOTInliningPolicy(null), canonicalizer)); } } } ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase(config)); if (VerifyPhases.getValue(options)) { ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config)); } return ret; } protected PhaseSuite<HighTierContext> createGraphBuilderSuite() { PhaseSuite<HighTierContext> suite = defaultSuitesCreator.getDefaultGraphBuilderSuite().copy(); assert appendGraphEncoderTest(suite); return suite; }
When assertions are enabled, we encode and decode every parsed graph, to ensure that the encoding and decoding process work correctly. The decoding performs canonicalization during decoding, so the decoded graph can be different than the encoded graph - we cannot check them for equality here. However, the encoder verifies the encoding itself, i.e., performs a decoding without canonicalization and checks the graphs for equality.
/** * When assertions are enabled, we encode and decode every parsed graph, to ensure that the * encoding and decoding process work correctly. The decoding performs canonicalization during * decoding, so the decoded graph can be different than the encoded graph - we cannot check them * for equality here. However, the encoder {@link GraphEncoder#verifyEncoding verifies the * encoding itself}, i.e., performs a decoding without canonicalization and checks the graphs * for equality. */
private boolean appendGraphEncoderTest(PhaseSuite<HighTierContext> suite) { suite.appendPhase(new BasePhase<HighTierContext>() { @Override protected void run(StructuredGraph graph, HighTierContext context) { EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), graph.getDebug(), AllowAssumptions.YES).method(graph.method()).build(); SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions())); if (graph.trackNodeSourcePosition()) { targetGraph.setTrackNodeSourcePosition(); } graphDecoder.decode(encodedGraph); } @Override protected CharSequence getName() { return "VerifyEncodingDecoding"; } }); return true; }
Modifies a given GraphBuilderConfiguration to record per node source information.
Params:
  • gbs – the current graph builder suite to modify
/** * Modifies a given {@link GraphBuilderConfiguration} to record per node source information. * * @param gbs the current graph builder suite to modify */
public static PhaseSuite<HighTierContext> withNodeSourcePosition(PhaseSuite<HighTierContext> gbs) { PhaseSuite<HighTierContext> newGbs = gbs.copy(); GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig.withNodeSourcePosition(true)); newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); return newGbs; } @Override public LIRSuites createLIRSuites(OptionValues options) { LIRSuites suites = defaultSuitesCreator.createLIRSuites(options); String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(options); if (profileInstructions != null) { suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); } if (Assertions.detailedAssertionsEnabled(options)) { suites.getPostAllocationOptimizationStage().appendPhase(new VerifyMaxRegisterSizePhase(config.maxVectorSize)); } return suites; } }