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