gt:                 if (!UseSnippetGraphCache.getValue() || args != null) {
context: /*
   * Copyright (c) 2011, 2016, 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 com.oracle.graal.replacements;
  
  import static com.oracle.graal.compiler.common.GraalOptions.DeoptALot;
  import static com.oracle.graal.compiler.common.GraalOptions.UseSnippetGraphCache;
  import static com.oracle.graal.java.BytecodeParserOptions.InlineDuringParsing;
  import static com.oracle.graal.java.BytecodeParserOptions.InlineIntrinsicsDuringParsing;
  import static com.oracle.graal.nodes.StructuredGraph.NO_PROFILING_INFO;
  import static com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo;
  import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
  import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Required;
  
  import java.util.Map;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.concurrent.ConcurrentMap;
  
  import com.oracle.graal.api.replacements.Fold;
  import com.oracle.graal.api.replacements.MethodSubstitution;
  import com.oracle.graal.api.replacements.SnippetReflectionProvider;
  import com.oracle.graal.api.replacements.SnippetTemplateCache;
  import com.oracle.graal.bytecode.BytecodeProvider;
  import com.oracle.graal.bytecode.ResolvedJavaMethodBytecode;
  import com.oracle.graal.compiler.common.CollectionsFactory;
  import com.oracle.graal.compiler.common.GraalOptions;
  import com.oracle.graal.compiler.common.spi.ConstantFieldProvider;
  import com.oracle.graal.debug.Debug;
  import com.oracle.graal.debug.Debug.Scope;
  import com.oracle.graal.debug.DebugCloseable;
  import com.oracle.graal.debug.DebugTimer;
  import com.oracle.graal.debug.GraalError;
  import com.oracle.graal.graph.Node;
  import com.oracle.graal.graph.Node.NodeIntrinsic;
  import com.oracle.graal.java.GraphBuilderPhase;
  import com.oracle.graal.java.GraphBuilderPhase.Instance;
  import com.oracle.graal.nodes.CallTargetNode;
  import com.oracle.graal.nodes.Invoke;
  import com.oracle.graal.nodes.StateSplit;
  import com.oracle.graal.nodes.StructuredGraph;
  import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
  import com.oracle.graal.nodes.ValueNode;
  import com.oracle.graal.nodes.graphbuilderconf.GeneratedInvocationPlugin;
  import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration;
  import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
  import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext;
  import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin;
  import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext;
  import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin;
  import com.oracle.graal.nodes.graphbuilderconf.MethodSubstitutionPlugin;
  import com.oracle.graal.nodes.java.MethodCallTargetNode;
  import com.oracle.graal.nodes.spi.Replacements;
  import com.oracle.graal.nodes.spi.StampProvider;
  import com.oracle.graal.options.OptionValue;
  import com.oracle.graal.options.OptionValue.OverrideScope;
  import com.oracle.graal.phases.OptimisticOptimizations;
  import com.oracle.graal.phases.common.CanonicalizerPhase;
  import com.oracle.graal.phases.common.ConvertDeoptimizeToGuardPhase;
  import com.oracle.graal.phases.common.DeadCodeEliminationPhase;
  import com.oracle.graal.phases.tiers.PhaseContext;
  import com.oracle.graal.phases.util.Providers;
  import com.oracle.graal.word.Word;
  
  import jdk.vm.ci.code.TargetDescription;
  import jdk.vm.ci.meta.ConstantReflectionProvider;
  import jdk.vm.ci.meta.MetaAccessProvider;
  import jdk.vm.ci.meta.ResolvedJavaMethod;
  import jdk.vm.ci.meta.ResolvedJavaType;
  
  public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
  
      public final Providers providers;
      public final SnippetReflectionProvider snippetReflection;
      public final TargetDescription target;
      private GraphBuilderConfiguration.Plugins graphBuilderPlugins;
  
      /**
       * The preprocessed replacement graphs.
       */
      protected final ConcurrentMap<ResolvedJavaMethod, StructuredGraph> graphs;
  
      protected final BytecodeProvider bytecodeProvider;
  
      public void setGraphBuilderPlugins(GraphBuilderConfiguration.Plugins plugins) {
          assert this.graphBuilderPlugins == null;
          this.graphBuilderPlugins = plugins;
      }
  
      public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() {
          return graphBuilderPlugins;
      }
  
      protected boolean hasGeneratedInvocationPluginAnnotation(ResolvedJavaMethod method) {
          return method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null;
      }
  
      protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) {
          return method.getAnnotation(Word.Operation.class) != null;
      }
  
      private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough
  
      /**
       * Determines whether a given method should be inlined based on whether it has a substitution or
       * whether the inlining context is already within a substitution.
       *
       * @return an object specifying how {@code method} is to be inlined or null if it should not be
       *         inlined based on substitution related criteria
       */
      @Override
      public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
          ResolvedJavaMethod subst = getSubstitutionMethod(method);
          if (subst != null) {
              if (b.parsingIntrinsic() || InlineDuringParsing.getValue() || InlineIntrinsicsDuringParsing.getValue()) {
                  // Forced inlining of intrinsics
                  return createIntrinsicInlineInfo(subst, bytecodeProvider);
              }
              return null;
          }
          if (b.parsingIntrinsic()) {
              if (hasGeneratedInvocationPluginAnnotation(method)) {
                  throw new GraalError("%s should have been handled by a %s", method.format("%H.%n(%p)"), GeneratedInvocationPlugin.class.getSimpleName());
              }
              if (hasGenericInvocationPluginAnnotation(method)) {
                  throw new GraalError("%s should have been handled by %s", method.format("%H.%n(%p)"), WordOperationPlugin.class.getSimpleName());
              }
  
              assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded";
  
              if (method.getName().startsWith("$jacoco")) {
                  throw new GraalError("Found call to JaCoCo instrumentation method " + method.format("%H.%n(%p)") + ". Placing \"//JaCoCo Exclude\" anywhere in " +
                                  b.getMethod().getDeclaringClass().getSourceFileName() + " should fix this.");
              }
  
              // Force inlining when parsing replacements
              return createIntrinsicInlineInfo(method, bytecodeProvider);
          } else {
              assert method.getAnnotation(NodeIntrinsic.class) == null : String.format("@%s method %s must only be called from within a replacement%n%s", NodeIntrinsic.class.getSimpleName(),
                              method.format("%h.%n"), b);
          }
          return null;
      }
  
      @Override
      public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) {
          if (b.parsingIntrinsic()) {
              IntrinsicContext intrinsic = b.getIntrinsic();
              if (!intrinsic.isCallToOriginal(method)) {
                  throw new GraalError("All non-recursive calls in the intrinsic %s must be inlined or intrinsified: found call to %s",
                                  intrinsic.getIntrinsicMethod().format("%H.%n(%p)"), method.format("%h.%n(%p)"));
              }
          }
      }
  
      // This map is key'ed by a class name instead of a Class object so that
      // it is stable across VM executions (in support of replay compilation).
      private final Map<String, SnippetTemplateCache> snippetTemplateCache;
  
      public ReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) {
          this.providers = providers.copyWith(this);
          this.snippetReflection = snippetReflection;
          this.target = target;
          this.graphs = new ConcurrentHashMap<>();
          this.snippetTemplateCache = CollectionsFactory.newMap();
          this.bytecodeProvider = bytecodeProvider;
      }
  
      private static final DebugTimer SnippetPreparationTime = Debug.timer("SnippetPreparationTime");
  
      @Override
      public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args) {
          return getSnippet(method, null, args);
      }
  
      @Override
      @SuppressWarnings("try")
      public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args) {
          assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName();
          assert method.hasBytecodes() : "Snippet must not be abstract or native";
  
          StructuredGraph graph = UseSnippetGraphCache.getValue() ? graphs.get(method) : null;
          if (graph == null) {
              try (DebugCloseable a = SnippetPreparationTime.start()) {
                  StructuredGraph newGraph = makeGraph(method, args, recursiveEntry);
                  Debug.counter("SnippetNodeCount[%#s]", method).add(newGraph.getNodeCount());
  