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 }