1 /*
   2  * Copyright (c) 2012, 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.phases;
  24 
  25 import java.util.EnumSet;
  26 import java.util.Set;
  27 
  28 import org.graalvm.compiler.core.common.GraalOptions;
  29 import org.graalvm.compiler.debug.Debug;
  30 import org.graalvm.compiler.debug.DebugCounter;
  31 
  32 import jdk.vm.ci.meta.DeoptimizationReason;
  33 import jdk.vm.ci.meta.ProfilingInfo;
  34 
  35 public final class OptimisticOptimizations {
  36 
  37     public static final OptimisticOptimizations ALL = new OptimisticOptimizations(EnumSet.allOf(Optimization.class));
  38     public static final OptimisticOptimizations NONE = new OptimisticOptimizations(EnumSet.noneOf(Optimization.class));
  39     private static final DebugCounter disabledOptimisticOptsCounter = Debug.counter("DisabledOptimisticOpts");
  40 
  41     public enum Optimization {
  42         RemoveNeverExecutedCode,
  43         UseTypeCheckedInlining,
  44         UseTypeCheckHints,
  45         UseExceptionProbabilityForOperations,
  46         UseExceptionProbability,
  47         UseLoopLimitChecks
  48     }
  49 
  50     private final Set<Optimization> enabledOpts;
  51 
  52     public OptimisticOptimizations(ProfilingInfo info) {
  53         this.enabledOpts = EnumSet.noneOf(Optimization.class);
  54 
  55         enabledOpts.add(Optimization.UseExceptionProbabilityForOperations);
  56         addOptimization(info, DeoptimizationReason.UnreachedCode, Optimization.RemoveNeverExecutedCode);
  57         addOptimization(info, DeoptimizationReason.TypeCheckedInliningViolated, Optimization.UseTypeCheckedInlining);
  58         addOptimization(info, DeoptimizationReason.OptimizedTypeCheckViolated, Optimization.UseTypeCheckHints);
  59         addOptimization(info, DeoptimizationReason.NotCompiledExceptionHandler, Optimization.UseExceptionProbability);
  60         addOptimization(info, DeoptimizationReason.LoopLimitCheck, Optimization.UseLoopLimitChecks);
  61     }
  62 
  63     private void addOptimization(ProfilingInfo info, DeoptimizationReason deoptReason, Optimization optimization) {
  64         if (checkDeoptimizations(info, deoptReason)) {
  65             enabledOpts.add(optimization);
  66         } else {
  67             disabledOptimisticOptsCounter.increment();
  68         }
  69     }
  70 
  71     public OptimisticOptimizations remove(Optimization... optimizations) {
  72         Set<Optimization> newOptimizations = EnumSet.copyOf(enabledOpts);
  73         for (Optimization o : optimizations) {
  74             newOptimizations.remove(o);
  75         }
  76         return new OptimisticOptimizations(newOptimizations);
  77     }
  78 
  79     public OptimisticOptimizations add(Optimization... optimizations) {
  80         Set<Optimization> newOptimizations = EnumSet.copyOf(enabledOpts);
  81         for (Optimization o : optimizations) {
  82             newOptimizations.add(o);
  83         }
  84         return new OptimisticOptimizations(newOptimizations);
  85     }
  86 
  87     private OptimisticOptimizations(Set<Optimization> enabledOpts) {
  88         this.enabledOpts = enabledOpts;
  89     }
  90 
  91     public boolean removeNeverExecutedCode() {
  92         return GraalOptions.RemoveNeverExecutedCode.getValue() && enabledOpts.contains(Optimization.RemoveNeverExecutedCode);
  93     }
  94 
  95     public boolean useTypeCheckHints() {
  96         return GraalOptions.UseTypeCheckHints.getValue() && enabledOpts.contains(Optimization.UseTypeCheckHints);
  97     }
  98 
  99     public boolean inlineMonomorphicCalls() {
 100         return GraalOptions.InlineMonomorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
 101     }
 102 
 103     public boolean inlinePolymorphicCalls() {
 104         return GraalOptions.InlinePolymorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
 105     }
 106 
 107     public boolean inlineMegamorphicCalls() {
 108         return GraalOptions.InlineMegamorphicCalls.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
 109     }
 110 
 111     public boolean devirtualizeInvokes() {
 112         return GraalOptions.OptDevirtualizeInvokesOptimistically.getValue() && enabledOpts.contains(Optimization.UseTypeCheckedInlining);
 113     }
 114 
 115     public boolean useExceptionProbability() {
 116         return GraalOptions.UseExceptionProbability.getValue() && enabledOpts.contains(Optimization.UseExceptionProbability);
 117     }
 118 
 119     public boolean useExceptionProbabilityForOperations() {
 120         return GraalOptions.UseExceptionProbabilityForOperations.getValue() && enabledOpts.contains(Optimization.UseExceptionProbabilityForOperations);
 121     }
 122 
 123     public boolean useLoopLimitChecks() {
 124         return GraalOptions.UseLoopLimitChecks.getValue() && enabledOpts.contains(Optimization.UseLoopLimitChecks);
 125     }
 126 
 127     public boolean lessOptimisticThan(OptimisticOptimizations other) {
 128         for (Optimization opt : Optimization.values()) {
 129             if (!enabledOpts.contains(opt) && other.enabledOpts.contains(opt)) {
 130                 return true;
 131             }
 132         }
 133         return false;
 134     }
 135 
 136     private static boolean checkDeoptimizations(ProfilingInfo profilingInfo, DeoptimizationReason reason) {
 137         return profilingInfo.getDeoptimizationCount(reason) < GraalOptions.DeoptsToDisableOptimisticOptimization.getValue();
 138     }
 139 
 140     @Override
 141     public String toString() {
 142         return enabledOpts.toString();
 143     }
 144 }