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 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 
HotSpotProfilingInfo(HotSpotMethodData methodData, HotSpotResolvedJavaMethod method, boolean includeNormal, boolean includeOSR)45     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
getCodeSize()56     public int getCodeSize() {
57         return method.getCodeSize();
58     }
59 
getDecompileCount()60     public int getDecompileCount() {
61         return methodData.getDecompileCount();
62     }
63 
getOverflowRecompileCount()64     public int getOverflowRecompileCount() {
65         return methodData.getOverflowRecompileCount();
66     }
67 
getOverflowTrapCount()68     public int getOverflowTrapCount() {
69         return methodData.getOverflowTrapCount();
70     }
71 
72     @Override
getTypeProfile(int bci)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
getMethodProfile(int bci)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
getBranchTakenProbability(int bci)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
getSwitchProbabilities(int bci)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
getExceptionSeen(int bci)109     public TriState getExceptionSeen(int bci) {
110         findBCI(bci, true);
111         return dataAccessor.getExceptionSeen(methodData, position);
112     }
113 
114     @Override
getNullSeen(int bci)115     public TriState getNullSeen(int bci) {
116         findBCI(bci, false);
117         return dataAccessor.getNullSeen(methodData, position);
118     }
119 
120     @Override
getExecutionCount(int bci)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
getDeoptimizationCount(DeoptimizationReason reason)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 
findBCI(int targetBCI, boolean searchExtraData)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 
normalDataFound(HotSpotMethodDataAccessor data, int pos, int bci)180     private void normalDataFound(HotSpotMethodDataAccessor data, int pos, int bci) {
181         setCurrentData(data, pos);
182         this.hintPosition = position;
183         this.hintBCI = bci;
184     }
185 
extraDataFound(HotSpotMethodDataAccessor data, int pos)186     private void extraDataFound(HotSpotMethodDataAccessor data, int pos) {
187         setCurrentData(data, pos);
188     }
189 
noDataFound(boolean exceptionPossiblyNotRecorded)190     private void noDataFound(boolean exceptionPossiblyNotRecorded) {
191         HotSpotMethodDataAccessor accessor = HotSpotMethodData.getNoDataAccessor(exceptionPossiblyNotRecorded);
192         setCurrentData(accessor, -1);
193     }
194 
setCurrentData(HotSpotMethodDataAccessor dataAccessor, int position)195     private void setCurrentData(HotSpotMethodDataAccessor dataAccessor, int position) {
196         this.dataAccessor = dataAccessor;
197         this.position = position;
198     }
199 
200     @Override
isMature()201     public boolean isMature() {
202         return isMature;
203     }
204 
ignoreMature()205     public void ignoreMature() {
206         isMature = true;
207     }
208 
209     @Override
toString()210     public String toString() {
211         return "HotSpotProfilingInfo<" + this.toString(null, "; ") + ">";
212     }
213 
214     @Override
setMature()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
setCompilerIRSize(Class<?> irType, int size)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
getCompilerIRSize(Class<?> irType)243     public int getCompilerIRSize(Class<?> irType) {
244         if (irType == supportedCompilerIRType) {
245             return methodData.getCompiledIRSize();
246         }
247         return -1;
248     }
249 }
250