Mercurial > hg > truffle
comparison agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java @ 3939:f6f3bb0ee072
7088955: add C2 IR support to the SA
Reviewed-by: kvn
author | never |
---|---|
date | Sun, 11 Sep 2011 14:48:24 -0700 |
parents | c18cbe5936b8 |
children | da91efe96a93 |
comparison
equal
deleted
inserted
replaced
3938:e6b1331a51d2 | 3939:f6f3bb0ee072 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
32 import sun.jvm.hotspot.utilities.*; | 32 import sun.jvm.hotspot.utilities.*; |
33 | 33 |
34 // A MethodData provides interpreter profiling information | 34 // A MethodData provides interpreter profiling information |
35 | 35 |
36 public class MethodData extends Oop { | 36 public class MethodData extends Oop { |
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 | |
37 static { | 123 static { |
38 VM.registerVMInitializedObserver(new Observer() { | 124 VM.registerVMInitializedObserver(new Observer() { |
39 public void update(Observable o, Object data) { | 125 public void update(Observable o, Object data) { |
40 initialize(VM.getVM().getTypeDataBase()); | 126 initialize(VM.getVM().getTypeDataBase()); |
41 } | 127 } |
46 Type type = db.lookupType("methodDataOopDesc"); | 132 Type type = db.lookupType("methodDataOopDesc"); |
47 baseOffset = type.getSize(); | 133 baseOffset = type.getSize(); |
48 | 134 |
49 size = new CIntField(type.getCIntegerField("_size"), 0); | 135 size = new CIntField(type.getCIntegerField("_size"), 0); |
50 method = new OopField(type.getOopField("_method"), 0); | 136 method = new OopField(type.getOopField("_method"), 0); |
51 // FIXME: add more fields and accessors | 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 } | |
52 } | 189 } |
53 | 190 |
54 MethodData(OopHandle handle, ObjectHeap heap) { | 191 MethodData(OopHandle handle, ObjectHeap heap) { |
55 super(handle, heap); | 192 super(handle, heap); |
56 } | 193 } |
58 public boolean isMethodData() { return true; } | 195 public boolean isMethodData() { return true; } |
59 | 196 |
60 private static long baseOffset; | 197 private static long baseOffset; |
61 private static CIntField size; | 198 private static CIntField size; |
62 private static OopField method; | 199 private static OopField method; |
200 private static CIntField dataSize; | |
201 private static AddressField data; | |
202 | |
203 public static int sizeofMethodDataOopDesc; | |
204 public static int cellSize; | |
63 | 205 |
64 public long getObjectSize() { | 206 public long getObjectSize() { |
65 return alignObjectSize(size.getValue(this)); | 207 return alignObjectSize(size.getValue(this)); |
66 } | 208 } |
67 | 209 |
79 if (doVMFields) { | 221 if (doVMFields) { |
80 visitor.doOop(method, true); | 222 visitor.doOop(method, true); |
81 visitor.doCInt(size, true); | 223 visitor.doCInt(size, true); |
82 } | 224 } |
83 } | 225 } |
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 } | |
84 } | 341 } |