Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | f6f3bb0ee072 |
children | bd7a7ce2e264 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
2 * Copyright (c) 2000, 2012, 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 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
36 public class MethodData extends Metadata { |
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 { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
132 Type type = db.lookupType("MethodData"); |
0 | 133 baseOffset = type.getSize(); |
134 | |
135 size = new CIntField(type.getCIntegerField("_size"), 0); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
136 method = new MetadataField(type.getAddressField("_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 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
191 public MethodData(Address addr) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
192 super(addr); |
0 | 193 } |
194 | |
195 public boolean isMethodData() { return true; } | |
196 | |
197 private static long baseOffset; | |
198 private static CIntField size; | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
199 private static MetadataField 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 Method getMethod() { | |
207 return (Method) method.getValue(this); | |
208 } | |
209 | |
210 public void printValueOn(PrintStream tty) { | |
211 Method m = getMethod(); | |
212 tty.print("MethodData for " + m.getName().asString() + m.getSignature().asString()); | |
213 } | |
214 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
215 public void iterateFields(MetadataVisitor visitor) { |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
216 super.iterateFields(visitor); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
217 visitor.doMetadata(method, true); |
0 | 218 visitor.doCInt(size, true); |
219 } | |
3939 | 220 |
221 int dataSize() { | |
222 if (dataSize == null) { | |
223 return 0; | |
224 } else { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
225 return (int)dataSize.getValue(getAddress()); |
3939 | 226 } |
227 } | |
228 | |
229 boolean outOfBounds(int dataIndex) { | |
230 return dataIndex >= dataSize(); | |
231 } | |
232 | |
233 ProfileData dataAt(int dataIndex) { | |
234 if (outOfBounds(dataIndex)) { | |
235 return null; | |
236 } | |
237 DataLayout dataLayout = new DataLayout(this, dataIndex + (int)data.getOffset()); | |
238 | |
239 switch (dataLayout.tag()) { | |
240 case DataLayout.noTag: | |
241 default: | |
242 throw new InternalError(dataIndex + " " + dataSize() + " " + dataLayout.tag()); | |
243 case DataLayout.bitDataTag: | |
244 return new BitData(dataLayout); | |
245 case DataLayout.counterDataTag: | |
246 return new CounterData(dataLayout); | |
247 case DataLayout.jumpDataTag: | |
248 return new JumpData(dataLayout); | |
249 case DataLayout.receiverTypeDataTag: | |
250 return new ReceiverTypeData(dataLayout); | |
251 case DataLayout.virtualCallDataTag: | |
252 return new VirtualCallData(dataLayout); | |
253 case DataLayout.retDataTag: | |
254 return new RetData(dataLayout); | |
255 case DataLayout.branchDataTag: | |
256 return new BranchData(dataLayout); | |
257 case DataLayout.multiBranchDataTag: | |
258 return new MultiBranchData(dataLayout); | |
259 } | |
260 } | |
261 | |
262 int dpToDi(int dp) { | |
263 // this in an offset from the base of the MDO, so convert to offset into _data | |
264 return dp - (int)data.getOffset(); | |
265 } | |
266 | |
267 int firstDi() { return 0; } | |
268 public ProfileData firstData() { return dataAt(firstDi()); } | |
269 public ProfileData nextData(ProfileData current) { | |
270 int currentIndex = dpToDi(current.dp()); | |
271 int nextIndex = currentIndex + current.sizeInBytes(); | |
272 return dataAt(nextIndex); | |
273 } | |
274 boolean isValid(ProfileData current) { return current != null; } | |
275 | |
276 public void printDataOn(PrintStream st) { | |
277 ProfileData data = firstData(); | |
278 for ( ; isValid(data); data = nextData(data)) { | |
279 st.print(dpToDi(data.dp())); | |
280 st.print(" "); | |
281 // st->fillTo(6); | |
282 data.printDataOn(st); | |
283 } | |
284 } | |
285 | |
286 private byte[] fetchDataAt(Address base, long offset, long size) { | |
287 byte[] result = new byte[(int)size]; | |
288 for (int i = 0; i < size; i++) { | |
289 result[i] = base.getJByteAt(offset + i); | |
290 } | |
291 return result; | |
292 } | |
293 | |
294 public byte[] orig() { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
295 // fetch the orig MethodData data between header and dataSize |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
296 return fetchDataAt(getAddress(), 0, sizeofMethodDataOopDesc); |
3939 | 297 } |
298 | |
299 public long[] data() { | |
300 // Read the data as an array of intptr_t elements | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
3939
diff
changeset
|
301 Address base = getAddress(); |
3939 | 302 long offset = data.getOffset(); |
303 int elements = dataSize() / cellSize; | |
304 long[] result = new long[elements]; | |
305 for (int i = 0; i < elements; i++) { | |
306 Address value = base.getAddressAt(offset + i * MethodData.cellSize); | |
307 if (value != null) { | |
308 result[i] = value.minus(null); | |
309 } | |
310 } | |
311 return result; | |
312 } | |
313 | |
314 // Get a measure of how much mileage the method has on it. | |
315 int mileageOf(Method method) { | |
316 long mileage = 0; | |
317 int iic = method.interpreterInvocationCount(); | |
318 if (mileage < iic) mileage = iic; | |
319 | |
320 long ic = method.getInvocationCounter(); | |
321 long bc = method.getBackedgeCounter(); | |
322 | |
323 long icval = ic >> 3; | |
324 if ((ic & 4) != 0) icval += CompileThreshold; | |
325 if (mileage < icval) mileage = icval; | |
326 long bcval = bc >> 3; | |
327 if ((bc & 4) != 0) bcval += CompileThreshold; | |
328 if (mileage < bcval) mileage = bcval; | |
329 return (int)mileage; | |
330 } | |
331 | |
332 public int currentMileage() { | |
333 return 20000; | |
334 } | |
0 | 335 } |