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