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 jdk.vm.ci.hotspot;
  24 
  25 import jdk.vm.ci.meta.DeoptimizationReason;
  26 import jdk.vm.ci.meta.JavaMethodProfile;
  27 import jdk.vm.ci.meta.JavaTypeProfile;
  28 import jdk.vm.ci.meta.ProfilingInfo;
  29 import jdk.vm.ci.meta.TriState;
  30 
  31 public final class HotSpotProfilingInfo implements ProfilingInfo {
  32 
  33     private final HotSpotMethodData methodData;
  34     private final HotSpotResolvedJavaMethod method;
  35 
  36     private boolean isMature;
  37     private int position;
  38     private int hintPosition;
  39     private int hintBCI;
  40     private HotSpotMethodDataAccessor dataAccessor;
  41 
  42     private boolean includeNormal;
  43     private boolean includeOSR;
  44 
  45     public HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method, boolean includeNormal, boolean includeOSR) {
  46         this.methodData = methodData;
  47         this.method = method;
  48         this.includeNormal = includeNormal;
  49         this.includeOSR = includeOSR;
  50         this.isMature = methodData.isProfileMature();
  51         hintPosition = 0;
  52         hintBCI = -1;
  53     }
  54 
  55     @Override
  56     public int getCodeSize() {
  57         return method.getCodeSize();
  58     }
  59 
  60     public int getDecompileCount() {
  61         return methodData.getDecompileCount();
  62     }
  63 
  64     public int getOverflowRecompileCount() {
  65         return methodData.getOverflowRecompileCount();
  66     }
  67 
  68     public int getOverflowTrapCount() {
  69         return methodData.getOverflowTrapCount();
  70     }
  71 
  72     @Override
  73     public JavaTypeProfile getTypeProfile(int bci) {
  74         if (!isMature) {
  75             return null;
  76         }
  77         findBCI(bci, false);
  78         return dataAccessor.getTypeProfile(methodData, position);
  79     }
  80 
  81     @Override
  82     public JavaMethodProfile getMethodProfile(int bci) {
  83         if (!isMature) {
  84             return null;
  85         }
  86         findBCI(bci, false);
  87         return dataAccessor.getMethodProfile(methodData, position);
  88     }
  89 
  90     @Override
  91     public double getBranchTakenProbability(int bci) {
  92         if (!isMature) {
  93             return -1;
  94         }
  95         findBCI(bci, false);
  96         return dataAccessor.getBranchTakenProbability(methodData, position);
  97     }
  98 
  99     @Override
 100     public double[] getSwitchProbabilities(int bci) {
 101         if (!isMature) {
 102             return null;
 103         }
 104         findBCI(bci, false);
 105         return dataAccessor.getSwitchProbabilities(methodData, position);
 106     }
 107 
 108     @Override
 109     public TriState getExceptionSeen(int bci) {
 110         findBCI(bci, true);
 111         return dataAccessor.getExceptionSeen(methodData, position);
 112     }
 113 
 114     @Override
 115     public TriState getNullSeen(int bci) {
 116         findBCI(bci, false);
 117         return dataAccessor.getNullSeen(methodData, position);
 118     }
 119 
 120     @Override
 121     public int getExecutionCount(int bci) {
 122         if (!isMature) {
 123             return -1;
 124         }
 125         findBCI(bci, false);
 126         return dataAccessor.getExecutionCount(methodData, position);
 127     }
 128 
 129     @Override
 130     public int getDeoptimizationCount(DeoptimizationReason reason) {
 131         int count = 0;
 132         if (includeNormal) {
 133             count += methodData.getDeoptimizationCount(reason);
 134         }
 135         if (includeOSR) {
 136             count += methodData.getOSRDeoptimizationCount(reason);
 137         }
 138         return count;
 139     }
 140 
 141     private void findBCI(int targetBCI, boolean searchExtraData) {
 142         assert targetBCI >= 0 : "invalid BCI";
 143 
 144         if (methodData.hasNormalData()) {
 145             int currentPosition = targetBCI < hintBCI ? 0 : hintPosition;
 146             HotSpotMethodDataAccessor currentAccessor;
 147             while ((currentAccessor = methodData.getNormalData(currentPosition)) != null) {
 148                 int currentBCI = currentAccessor.getBCI(methodData, currentPosition);
 149                 if (currentBCI == targetBCI) {
 150                     normalDataFound(currentAccessor, currentPosition, currentBCI);
 151                     return;
 152                 } else if (currentBCI > targetBCI) {
 153                     break;
 154                 }
 155                 currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition);
 156             }
 157         }
 158 
 159         boolean exceptionPossiblyNotRecorded = false;
 160         if (searchExtraData && methodData.hasExtraData()) {
 161             int currentPosition = methodData.getExtraDataBeginOffset();
 162             HotSpotMethodDataAccessor currentAccessor;
 163             while ((currentAccessor = methodData.getExtraData(currentPosition)) != null) {
 164                 int currentBCI = currentAccessor.getBCI(methodData, currentPosition);
 165                 if (currentBCI == targetBCI) {
 166                     extraDataFound(currentAccessor, currentPosition);
 167                     return;
 168                 }
 169                 currentPosition = currentPosition + currentAccessor.getSize(methodData, currentPosition);
 170             }
 171 
 172             if (!methodData.isWithin(currentPosition)) {
 173                 exceptionPossiblyNotRecorded = true;
 174             }
 175         }
 176 
 177         noDataFound(exceptionPossiblyNotRecorded);
 178     }
 179 
 180     private void normalDataFound(HotSpotMethodDataAccessor data, int pos, int bci) {
 181         setCurrentData(data, pos);
 182         this.hintPosition = position;
 183         this.hintBCI = bci;
 184     }
 185 
 186     private void extraDataFound(HotSpotMethodDataAccessor data, int pos) {
 187         setCurrentData(data, pos);
 188     }
 189 
 190     private void noDataFound(boolean exceptionPossiblyNotRecorded) {
 191         HotSpotMethodDataAccessor accessor = HotSpotMethodData.getNoDataAccessor(exceptionPossiblyNotRecorded);
 192         setCurrentData(accessor, -1);
 193     }
 194 
 195     private void setCurrentData(HotSpotMethodDataAccessor dataAccessor, int position) {
 196         this.dataAccessor = dataAccessor;
 197         this.position = position;
 198     }
 199 
 200     @Override
 201     public boolean isMature() {
 202         return isMature;
 203     }
 204 
 205     public void ignoreMature() {
 206         isMature = true;
 207     }
 208 
 209     @Override
 210     public String toString() {
 211         return "HotSpotProfilingInfo<" + this.toString(null, "; ") + ">";
 212     }
 213 
 214     @Override
 215     public void setMature() {
 216         isMature = true;
 217     }
 218 
 219     /**
 220      * {@code MethodData::_jvmci_ir_size} (currently) supports at most one JVMCI compiler IR type
 221      * which will be determined by the first JVMCI compiler that calls
 222      * {@link #setCompilerIRSize(Class, int)}.
 223      */
 224     private static volatile Class<?> supportedCompilerIRType;
 225 
 226     @Override
 227     public boolean setCompilerIRSize(Class<?> irType, int size) {
 228         if (supportedCompilerIRType == null) {
 229             synchronized (HotSpotProfilingInfo.class) {
 230                 if (supportedCompilerIRType == null) {
 231                     supportedCompilerIRType = irType;
 232                 }
 233             }
 234         }
 235         if (supportedCompilerIRType != irType) {
 236             return false;
 237         }
 238         methodData.setCompiledIRSize(size);
 239         return true;
 240     }
 241 
 242     @Override
 243     public int getCompilerIRSize(Class<?> irType) {
 244         if (irType == supportedCompilerIRType) {
 245             return methodData.getCompiledIRSize();
 246         }
 247         return -1;
 248     }
 249 }