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.replacements;
  24 
  25 import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID;
  26 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
  27 
  28 import java.util.HashMap;
  29 import java.util.Map;
  30 
  31 import org.graalvm.compiler.bytecode.BytecodeProvider;
  32 import org.graalvm.compiler.debug.Debug;
  33 import org.graalvm.compiler.java.GraphBuilderPhase;
  34 import org.graalvm.compiler.nodes.EncodedGraph;
  35 import org.graalvm.compiler.nodes.GraphEncoder;
  36 import org.graalvm.compiler.nodes.StructuredGraph;
  37 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  38 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  39 import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext;
  40 import org.graalvm.compiler.phases.OptimisticOptimizations;
  41 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  42 import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase;
  43 import org.graalvm.compiler.phases.tiers.PhaseContext;
  44 import org.graalvm.compiler.phases.util.Providers;
  45 
  46 import jdk.vm.ci.code.Architecture;
  47 import jdk.vm.ci.meta.ResolvedJavaMethod;
  48 
  49 /**
  50  * A graph decoder that provides all necessary encoded graphs on-the-fly (by parsing the methods and
  51  * encoding the graphs).
  52  */
  53 public class CachingPEGraphDecoder extends PEGraphDecoder {
  54 
  55     protected final Providers providers;
  56     protected final GraphBuilderConfiguration graphBuilderConfig;
  57     protected final OptimisticOptimizations optimisticOpts;
  58     private final AllowAssumptions allowAssumptions;
  59     private final Map<ResolvedJavaMethod, EncodedGraph> graphCache;
  60 
  61     public CachingPEGraphDecoder(Providers providers, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, AllowAssumptions allowAssumptions,
  62                     Architecture architecture) {
  63         super(providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getStampProvider(), architecture);
  64 
  65         this.providers = providers;
  66         this.graphBuilderConfig = graphBuilderConfig;
  67         this.optimisticOpts = optimisticOpts;
  68         this.allowAssumptions = allowAssumptions;
  69         this.graphCache = new HashMap<>();
  70     }
  71 
  72     protected GraphBuilderPhase.Instance createGraphBuilderPhaseInstance(IntrinsicContext initialIntrinsicContext) {
  73         return new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), graphBuilderConfig,
  74                         optimisticOpts, initialIntrinsicContext);
  75     }
  76 
  77     @SuppressWarnings("try")
  78     private EncodedGraph createGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider) {
  79         StructuredGraph graph = new StructuredGraph(method, allowAssumptions, INVALID_COMPILATION_ID);
  80         try (Debug.Scope scope = Debug.scope("createGraph", graph)) {
  81             IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null ? new IntrinsicContext(method, method, intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null;
  82             GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext);
  83             graphBuilderPhaseInstance.apply(graph);
  84 
  85             PhaseContext context = new PhaseContext(providers);
  86             new CanonicalizerPhase().apply(graph, context);
  87             /*
  88              * ConvertDeoptimizeToGuardPhase reduces the number of merges in the graph, so that
  89              * fewer frame states will be created. This significantly reduces the number of nodes in
  90              * the initial graph.
  91              */
  92             new ConvertDeoptimizeToGuardPhase().apply(graph, context);
  93 
  94             EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, architecture);
  95             graphCache.put(method, encodedGraph);
  96             return encodedGraph;
  97 
  98         } catch (Throwable ex) {
  99             throw Debug.handle(ex);
 100         }
 101     }
 102 
 103     @Override
 104     protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider) {
 105         EncodedGraph result = graphCache.get(method);
 106         if (result == null && method.hasBytecodes()) {
 107             result = createGraph(method, intrinsicBytecodeProvider);
 108         }
 109         return result;
 110     }
 111 }