Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java @ 3945:8ed53447f690
Merge
author | iveresov |
---|---|
date | Thu, 15 Sep 2011 12:44:09 -0700 |
parents | f6f3bb0ee072 |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
3939 | 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.oops; | |
26 | |
27 import java.io.*; | |
28 import java.util.*; | |
29 import sun.jvm.hotspot.debugger.*; | |
30 import sun.jvm.hotspot.runtime.*; | |
31 import sun.jvm.hotspot.types.*; | |
32 import sun.jvm.hotspot.utilities.*; | |
33 | |
34 // A MethodData provides interpreter profiling information | |
35 | |
36 public class MethodData extends Oop { | |
3939 | 37 static int TypeProfileWidth = 2; |
38 static int BciProfileWidth = 2; | |
39 static int CompileThreshold; | |
40 | |
41 static int Reason_many; // indicates presence of several reasons | |
42 static int Reason_none; // indicates absence of a relevant deopt. | |
43 static int Reason_LIMIT; | |
44 static int Reason_RECORDED_LIMIT; // some are not recorded per bc | |
45 | |
46 private static String[] trapReasonName; | |
47 | |
48 static String trapReasonName(int reason) { | |
49 if (reason == Reason_many) return "many"; | |
50 if (reason < Reason_LIMIT) | |
51 return trapReasonName[reason]; | |
52 return "reason" + reason; | |
53 } | |
54 | |
55 | |
56 static int trapStateReason(int trapState) { | |
57 // This assert provides the link between the width of DataLayout.trapBits | |
58 // and the encoding of "recorded" reasons. It ensures there are enough | |
59 // bits to store all needed reasons in the per-BCI MDO profile. | |
60 // assert(dsReasonMask >= reasonRecordedLimit, "enough bits"); | |
61 int recompileBit = (trapState & dsRecompileBit); | |
62 trapState -= recompileBit; | |
63 if (trapState == dsReasonMask) { | |
64 return Reason_many; | |
65 } else { | |
66 // assert((int)reasonNone == 0, "state=0 => Reason_none"); | |
67 return trapState; | |
68 } | |
69 } | |
70 | |
71 | |
72 static final int dsReasonMask = DataLayout.trapMask >> 1; | |
73 static final int dsRecompileBit = DataLayout.trapMask - dsReasonMask; | |
74 | |
75 static boolean trapStateIsRecompiled(int trapState) { | |
76 return (trapState & dsRecompileBit) != 0; | |
77 } | |
78 | |
79 static boolean reasonIsRecordedPerBytecode(int reason) { | |
80 return reason > Reason_none && reason < Reason_RECORDED_LIMIT; | |
81 } | |
82 static int trapStateAddReason(int trapState, int reason) { | |
83 // assert(reasonIsRecordedPerBytecode((DeoptReason)reason) || reason == reasonMany, "valid reason"); | |
84 int recompileBit = (trapState & dsRecompileBit); | |
85 trapState -= recompileBit; | |
86 if (trapState == dsReasonMask) { | |
87 return trapState + recompileBit; // already at state lattice bottom | |
88 } else if (trapState == reason) { | |
89 return trapState + recompileBit; // the condition is already true | |
90 } else if (trapState == 0) { | |
91 return reason + recompileBit; // no condition has yet been true | |
92 } else { | |
93 return dsReasonMask + recompileBit; // fall to state lattice bottom | |
94 } | |
95 } | |
96 static int trapStateSetRecompiled(int trapState, boolean z) { | |
97 if (z) return trapState | dsRecompileBit; | |
98 else return trapState & ~dsRecompileBit; | |
99 } | |
100 | |
101 static String formatTrapState(int trapState) { | |
102 int reason = trapStateReason(trapState); | |
103 boolean recompFlag = trapStateIsRecompiled(trapState); | |
104 // Re-encode the state from its decoded components. | |
105 int decodedState = 0; | |
106 if (reasonIsRecordedPerBytecode(reason) || reason == Reason_many) | |
107 decodedState = trapStateAddReason(decodedState, reason); | |
108 if (recompFlag) | |
109 decodedState = trapStateSetRecompiled(decodedState, recompFlag); | |
110 // If the state re-encodes properly, format it symbolically. | |
111 // Because this routine is used for debugging and diagnostics, | |
112 // be robust even if the state is a strange value. | |
113 if (decodedState != trapState) { | |
114 // Random buggy state that doesn't decode?? | |
115 return "#" + trapState; | |
116 } else { | |
117 return trapReasonName(reason) + (recompFlag ? " recompiled" : ""); | |
118 } | |
119 } | |
120 | |
121 | |
122 | |
0 | 123 static { |
124 VM.registerVMInitializedObserver(new Observer() { | |
125 public void update(Observable o, Object data) { | |
126 initialize(VM.getVM().getTypeDataBase()); | |
127 } | |
128 }); | |
129 } | |
130 | |
131 private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { | |
132 Type type = db.lookupType("methodDataOopDesc"); | |
133 baseOffset = type.getSize(); | |
134 | |
135 size = new CIntField(type.getCIntegerField("_size"), 0); | |
136 method = new OopField(type.getOopField("_method"), 0); | |
3939 | 137 |
138 VM.Flag[] flags = VM.getVM().getCommandLineFlags(); | |
139 for (int f = 0; f < flags.length; f++) { | |
140 VM.Flag flag = flags[f]; | |
141 if (flag.getName().equals("TypeProfileWidth")) { | |
142 TypeProfileWidth = (int)flag.getIntx(); | |
143 } else if (flag.getName().equals("BciProfileWidth")) { | |
144 BciProfileWidth = (int)flag.getIntx(); | |
145 } else if (flag.getName().equals("CompileThreshold")) { | |
146 CompileThreshold = (int)flag.getIntx(); | |
147 } | |
148 } | |
149 | |
150 cellSize = (int)VM.getVM().getAddressSize(); | |
151 | |
152 dataSize = new CIntField(type.getCIntegerField("_data_size"), 0); | |
153 data = type.getAddressField("_data[0]"); | |
154 | |
155 sizeofMethodDataOopDesc = (int)type.getSize();; | |
156 | |
157 Reason_many = db.lookupIntConstant("Deoptimization::Reason_many").intValue(); | |
158 Reason_none = db.lookupIntConstant("Deoptimization::Reason_none").intValue(); | |
159 Reason_LIMIT = db.lookupIntConstant("Deoptimization::Reason_LIMIT").intValue(); | |
160 Reason_RECORDED_LIMIT = db.lookupIntConstant("Deoptimization::Reason_RECORDED_LIMIT").intValue(); | |
161 | |
162 trapReasonName = new String[Reason_LIMIT]; | |
163 | |
164 // Find Deopt reasons | |
165 Iterator i = db.getIntConstants(); | |
166 String prefix = "Deoptimization::Reason_"; | |
167 while (i.hasNext()) { | |
168 String name = (String)i.next(); | |
169 if (name.startsWith(prefix)) { | |
170 // Strip prefix | |
171 if (!name.endsWith("Reason_many") && | |
172 !name.endsWith("Reason_LIMIT") && | |
173 !name.endsWith("Reason_RECORDED_LIMIT")) { | |
174 String trimmed = name.substring(prefix.length()); | |
175 int value = db.lookupIntConstant(name).intValue(); | |
176 if (trapReasonName[value] != null) { | |
177 throw new InternalError("duplicate reasons: " + trapReasonName[value] + " " + trimmed); | |
178 } | |
179 trapReasonName[value] = trimmed; | |
180 } | |
181 } | |
182 } | |
183 for (int index = 0; index < trapReasonName.length; index++) { | |
184 if (trapReasonName[index] == null) { | |
185 throw new InternalError("missing reason for " + index); | |
186 } | |
187 System.out.println(trapReasonName[index]); | |
188 } | |
0 | 189 } |
190 | |
191 MethodData(OopHandle handle, ObjectHeap heap) { | |
192 super(handle, heap); | |
193 } | |
194 | |
195 public boolean isMethodData() { return true; } | |
196 | |
197 private static long baseOffset; | |
198 private static CIntField size; | |
199 private static OopField method; | |
3939 | 200 private static CIntField dataSize; |
201 private static AddressField data; | |
202 | |
203 public static int sizeofMethodDataOopDesc; | |
204 public static int cellSize; | |
0 | 205 |
206 public long getObjectSize() { | |
207 return alignObjectSize(size.getValue(this)); | |
208 } | |
209 | |
210 public Method getMethod() { | |
211 return (Method) method.getValue(this); | |
212 } | |
213 | |
214 public void printValueOn(PrintStream tty) { | |
215 Method m = getMethod(); | |
216 tty.print("MethodData for " + m.getName().asString() + m.getSignature().asString()); | |
217 } | |
218 | |
219 public void iterateFields(OopVisitor visitor, boolean doVMFields) { | |
220 super.iterateFields(visitor, doVMFields); | |
221 if (doVMFields) { | |
222 visitor.doOop(method, true); | |
223 visitor.doCInt(size, true); | |
224 } | |
225 } | |
3939 | 226 |
227 int dataSize() { | |
228 if (dataSize == null) { | |
229 return 0; | |
230 } else { | |
231 return (int)dataSize.getValue(this); | |
232 } | |
233 } | |
234 | |
235 boolean outOfBounds(int dataIndex) { | |
236 return dataIndex >= dataSize(); | |
237 } | |
238 | |
239 ProfileData dataAt(int dataIndex) { | |
240 if (outOfBounds(dataIndex)) { | |
241 return null; | |
242 } | |
243 DataLayout dataLayout = new DataLayout(this, dataIndex + (int)data.getOffset()); | |
244 | |
245 switch (dataLayout.tag()) { | |
246 case DataLayout.noTag: | |
247 default: | |
248 throw new InternalError(dataIndex + " " + dataSize() + " " + dataLayout.tag()); | |
249 case DataLayout.bitDataTag: | |
250 return new BitData(dataLayout); | |
251 case DataLayout.counterDataTag: | |
252 return new CounterData(dataLayout); | |
253 case DataLayout.jumpDataTag: | |
254 return new JumpData(dataLayout); | |
255 case DataLayout.receiverTypeDataTag: | |
256 return new ReceiverTypeData(dataLayout); | |
257 case DataLayout.virtualCallDataTag: | |
258 return new VirtualCallData(dataLayout); | |
259 case DataLayout.retDataTag: | |
260 return new RetData(dataLayout); | |
261 case DataLayout.branchDataTag: | |
262 return new BranchData(dataLayout); | |
263 case DataLayout.multiBranchDataTag: | |
264 return new MultiBranchData(dataLayout); | |
265 } | |
266 } | |
267 | |
268 int dpToDi(int dp) { | |
269 // this in an offset from the base of the MDO, so convert to offset into _data | |
270 return dp - (int)data.getOffset(); | |
271 } | |
272 | |
273 int firstDi() { return 0; } | |
274 public ProfileData firstData() { return dataAt(firstDi()); } | |
275 public ProfileData nextData(ProfileData current) { | |
276 int currentIndex = dpToDi(current.dp()); | |
277 int nextIndex = currentIndex + current.sizeInBytes(); | |
278 return dataAt(nextIndex); | |
279 } | |
280 boolean isValid(ProfileData current) { return current != null; } | |
281 | |
282 public void printDataOn(PrintStream st) { | |
283 ProfileData data = firstData(); | |
284 for ( ; isValid(data); data = nextData(data)) { | |
285 st.print(dpToDi(data.dp())); | |
286 st.print(" "); | |
287 // st->fillTo(6); | |
288 data.printDataOn(st); | |
289 } | |
290 } | |
291 | |
292 private byte[] fetchDataAt(Address base, long offset, long size) { | |
293 byte[] result = new byte[(int)size]; | |
294 for (int i = 0; i < size; i++) { | |
295 result[i] = base.getJByteAt(offset + i); | |
296 } | |
297 return result; | |
298 } | |
299 | |
300 public byte[] orig() { | |
301 // fetch the orig methodDataOopDesc data between header and dataSize | |
302 return fetchDataAt(this.getHandle(), 0, sizeofMethodDataOopDesc); | |
303 } | |
304 | |
305 public long[] data() { | |
306 // Read the data as an array of intptr_t elements | |
307 OopHandle base = getHandle(); | |
308 long offset = data.getOffset(); | |
309 int elements = dataSize() / cellSize; | |
310 long[] result = new long[elements]; | |
311 for (int i = 0; i < elements; i++) { | |
312 Address value = base.getAddressAt(offset + i * MethodData.cellSize); | |
313 if (value != null) { | |
314 result[i] = value.minus(null); | |
315 } | |
316 } | |
317 return result; | |
318 } | |
319 | |
320 // Get a measure of how much mileage the method has on it. | |
321 int mileageOf(Method method) { | |
322 long mileage = 0; | |
323 int iic = method.interpreterInvocationCount(); | |
324 if (mileage < iic) mileage = iic; | |
325 | |
326 long ic = method.getInvocationCounter(); | |
327 long bc = method.getBackedgeCounter(); | |
328 | |
329 long icval = ic >> 3; | |
330 if ((ic & 4) != 0) icval += CompileThreshold; | |
331 if (mileage < icval) mileage = icval; | |
332 long bcval = bc >> 3; | |
333 if ((bc & 4) != 0) bcval += CompileThreshold; | |
334 if (mileage < bcval) mileage = bcval; | |
335 return (int)mileage; | |
336 } | |
337 | |
338 public int currentMileage() { | |
339 return 20000; | |
340 } | |
0 | 341 } |