Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java
+++ new/agent/src/share/classes/sun/jvm/hotspot/code/NMethod.java
1 1 /*
2 - * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
2 + * Copyright 2000-2010 Sun Microsystems, Inc. All Rights Reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation.
8 8 *
9 9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 12 * version 2 for more details (a copy is included in the LICENSE file that
13 13 * accompanied this code).
14 14 *
15 15 * You should have received a copy of the GNU General Public License version
16 16 * 2 along with this work; if not, write to the Free Software Foundation,
17 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 18 *
19 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 21 * have any questions.
22 22 *
23 23 */
24 24
25 25 package sun.jvm.hotspot.code;
26 26
27 27 import java.io.*;
28 28 import java.util.*;
29 29 import sun.jvm.hotspot.debugger.*;
30 30 import sun.jvm.hotspot.memory.*;
31 31 import sun.jvm.hotspot.oops.*;
32 32 import sun.jvm.hotspot.runtime.*;
33 33 import sun.jvm.hotspot.types.*;
34 34 import sun.jvm.hotspot.utilities.*;
35 35
36 36 public class NMethod extends CodeBlob {
37 37 private static long pcDescSize;
38 38 private static CIntegerField zombieInstructionSizeField;
39 39 private static sun.jvm.hotspot.types.OopField methodField;
40 40 /** != InvocationEntryBci if this nmethod is an on-stack replacement method */
41 41 private static CIntegerField entryBCIField;
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
42 42 /** To support simple linked-list chaining of nmethods */
43 43 private static AddressField osrLinkField;
44 44 private static AddressField scavengeRootLinkField;
45 45 private static JByteField scavengeRootStateField;
46 46
47 47 /** Offsets for different nmethod parts */
48 48 private static CIntegerField exceptionOffsetField;
49 49 private static CIntegerField deoptOffsetField;
50 50 private static CIntegerField origPCOffsetField;
51 51 private static CIntegerField stubOffsetField;
52 + private static CIntegerField oopsOffsetField;
52 53 private static CIntegerField scopesDataOffsetField;
53 54 private static CIntegerField scopesPCsOffsetField;
54 55 private static CIntegerField dependenciesOffsetField;
55 56 private static CIntegerField handlerTableOffsetField;
56 57 private static CIntegerField nulChkTableOffsetField;
57 58 private static CIntegerField nmethodEndOffsetField;
58 59
59 60 /** Offsets for entry points */
60 61 /** Entry point with class check */
61 62 private static AddressField entryPointField;
62 63 /** Entry point without class check */
63 64 private static AddressField verifiedEntryPointField;
64 65 /** Entry point for on stack replacement */
65 66 private static AddressField osrEntryPointField;
66 67
67 68 // FIXME: add access to flags (how?)
68 69
69 70 /** NMethod Flushing lock (if non-zero, then the nmethod is not removed) */
70 71 private static JIntField lockCountField;
71 72
72 73 /** not_entrant method removal. Each mark_sweep pass will update
73 74 this mark to current sweep invocation count if it is seen on the
74 75 stack. An not_entrant method can be removed when there is no
75 76 more activations, i.e., when the _stack_traversal_mark is less than
76 77 current sweep traversal index. */
77 78 private static CIntegerField stackTraversalMarkField;
78 79
79 80 static {
80 81 VM.registerVMInitializedObserver(new Observer() {
81 82 public void update(Observable o, Object data) {
82 83 initialize(VM.getVM().getTypeDataBase());
83 84 }
84 85 });
85 86 }
86 87
87 88 private static void initialize(TypeDataBase db) {
88 89 Type type = db.lookupType("nmethod");
89 90
90 91 zombieInstructionSizeField = type.getCIntegerField("_zombie_instruction_size");
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
91 92 methodField = type.getOopField("_method");
92 93 entryBCIField = type.getCIntegerField("_entry_bci");
93 94 osrLinkField = type.getAddressField("_osr_link");
94 95 scavengeRootLinkField = type.getAddressField("_scavenge_root_link");
95 96 scavengeRootStateField = type.getJByteField("_scavenge_root_state");
96 97
97 98 exceptionOffsetField = type.getCIntegerField("_exception_offset");
98 99 deoptOffsetField = type.getCIntegerField("_deoptimize_offset");
99 100 origPCOffsetField = type.getCIntegerField("_orig_pc_offset");
100 101 stubOffsetField = type.getCIntegerField("_stub_offset");
102 + oopsOffsetField = type.getCIntegerField("_oops_offset");
101 103 scopesDataOffsetField = type.getCIntegerField("_scopes_data_offset");
102 104 scopesPCsOffsetField = type.getCIntegerField("_scopes_pcs_offset");
103 105 dependenciesOffsetField = type.getCIntegerField("_dependencies_offset");
104 106 handlerTableOffsetField = type.getCIntegerField("_handler_table_offset");
105 107 nulChkTableOffsetField = type.getCIntegerField("_nul_chk_table_offset");
106 108 nmethodEndOffsetField = type.getCIntegerField("_nmethod_end_offset");
107 109 entryPointField = type.getAddressField("_entry_point");
108 110 verifiedEntryPointField = type.getAddressField("_verified_entry_point");
109 111 osrEntryPointField = type.getAddressField("_osr_entry_point");
110 112 lockCountField = type.getJIntField("_lock_count");
111 113 stackTraversalMarkField = type.getCIntegerField("_stack_traversal_mark");
112 114
113 115 pcDescSize = db.lookupType("PcDesc").getSize();
114 116 }
115 117
116 118 public NMethod(Address addr) {
117 119 super(addr);
118 120 }
119 121
120 122
121 123 // Accessors
122 124 public Address getAddress() {
123 125 return addr;
124 126 }
125 127
126 128 public Method getMethod() {
127 129 return (Method) VM.getVM().getObjectHeap().newOop(methodField.getValue(addr));
128 130 }
129 131
130 132 // Type info
131 133 public boolean isNMethod() { return true; }
132 134 public boolean isJavaMethod() { return !getMethod().isNative(); }
133 135 public boolean isNativeMethod() { return getMethod().isNative(); }
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
134 136 public boolean isOSRMethod() { return getEntryBCI() != VM.getVM().getInvocationEntryBCI(); }
135 137
136 138 /** Boundaries for different parts */
137 139 public Address constantsBegin() { return instructionsBegin(); }
138 140 public Address constantsEnd() { return getEntryPoint(); }
139 141 public Address codeBegin() { return getEntryPoint(); }
140 142 public Address codeEnd() { return headerBegin().addOffsetTo(getStubOffset()); }
141 143 public Address exceptionBegin() { return headerBegin().addOffsetTo(getExceptionOffset()); }
142 144 public Address deoptBegin() { return headerBegin().addOffsetTo(getDeoptOffset()); }
143 145 public Address stubBegin() { return headerBegin().addOffsetTo(getStubOffset()); }
144 - public Address stubEnd() { return headerBegin().addOffsetTo(getScopesDataOffset()); }
146 + public Address stubEnd() { return headerBegin().addOffsetTo(getOopsOffset()); }
147 + public Address oopsBegin() { return headerBegin().addOffsetTo(getOopsOffset()); }
148 + public Address oopsEnd() { return headerBegin().addOffsetTo(getScopesDataOffset()); }
145 149 public Address scopesDataBegin() { return headerBegin().addOffsetTo(getScopesDataOffset()); }
146 150 public Address scopesDataEnd() { return headerBegin().addOffsetTo(getScopesPCsOffset()); }
147 151 public Address scopesPCsBegin() { return headerBegin().addOffsetTo(getScopesPCsOffset()); }
148 152 public Address scopesPCsEnd() { return headerBegin().addOffsetTo(getDependenciesOffset()); }
149 153 public Address dependenciesBegin() { return headerBegin().addOffsetTo(getDependenciesOffset()); }
150 154 public Address dependenciesEnd() { return headerBegin().addOffsetTo(getHandlerTableOffset()); }
151 155 public Address handlerTableBegin() { return headerBegin().addOffsetTo(getHandlerTableOffset()); }
152 156 public Address handlerTableEnd() { return headerBegin().addOffsetTo(getNulChkTableOffset()); }
153 157 public Address nulChkTableBegin() { return headerBegin().addOffsetTo(getNulChkTableOffset()); }
154 158 public Address nulChkTableEnd() { return headerBegin().addOffsetTo(getNMethodEndOffset()); }
155 159
156 160 public int constantsSize() { return (int) constantsEnd() .minus(constantsBegin()); }
157 161 public int codeSize() { return (int) codeEnd() .minus(codeBegin()); }
158 162 public int stubSize() { return (int) stubEnd() .minus(stubBegin()); }
163 + public int oopsSize() { return (int) oopsEnd() .minus(oopsBegin()); }
159 164 public int scopesDataSize() { return (int) scopesDataEnd() .minus(scopesDataBegin()); }
160 165 public int scopesPCsSize() { return (int) scopesPCsEnd() .minus(scopesPCsBegin()); }
161 166 public int dependenciesSize() { return (int) dependenciesEnd().minus(dependenciesBegin()); }
162 167 public int handlerTableSize() { return (int) handlerTableEnd().minus(handlerTableBegin()); }
163 168 public int nulChkTableSize() { return (int) nulChkTableEnd() .minus(nulChkTableBegin()); }
164 169 public int origPCOffset() { return (int) origPCOffsetField.getValue(addr); }
165 170
166 171 public int totalSize() {
167 172 return
168 173 constantsSize() +
169 174 codeSize() +
170 175 stubSize() +
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
171 176 scopesDataSize() +
172 177 scopesPCsSize() +
173 178 dependenciesSize() +
174 179 handlerTableSize() +
175 180 nulChkTableSize();
176 181 }
177 182
178 183 public boolean constantsContains (Address addr) { return constantsBegin() .lessThanOrEqual(addr) && constantsEnd() .greaterThan(addr); }
179 184 public boolean codeContains (Address addr) { return codeBegin() .lessThanOrEqual(addr) && codeEnd() .greaterThan(addr); }
180 185 public boolean stubContains (Address addr) { return stubBegin() .lessThanOrEqual(addr) && stubEnd() .greaterThan(addr); }
186 + public boolean oopsContains (Address addr) { return oopsBegin() .lessThanOrEqual(addr) && oopsEnd() .greaterThan(addr); }
181 187 public boolean scopesDataContains (Address addr) { return scopesDataBegin() .lessThanOrEqual(addr) && scopesDataEnd() .greaterThan(addr); }
182 188 public boolean scopesPCsContains (Address addr) { return scopesPCsBegin() .lessThanOrEqual(addr) && scopesPCsEnd() .greaterThan(addr); }
183 189 public boolean handlerTableContains(Address addr) { return handlerTableBegin().lessThanOrEqual(addr) && handlerTableEnd().greaterThan(addr); }
184 190 public boolean nulChkTableContains (Address addr) { return nulChkTableBegin() .lessThanOrEqual(addr) && nulChkTableEnd() .greaterThan(addr); }
185 191
186 192 /** Entry points */
187 193 public Address getEntryPoint() { return entryPointField.getValue(addr); }
188 194 public Address getVerifiedEntryPoint() { return verifiedEntryPointField.getValue(addr); }
189 195
196 + /** Support for oops in scopes and relocs. Note: index 0 is reserved for null. */
197 + public OopHandle getOopAt(int index) {
198 + if (index == 0) return null;
199 + if (Assert.ASSERTS_ENABLED) {
200 + Assert.that(index > 0 && index <= oopsSize(), "must be a valid non-zero index");
201 + }
202 + return oopsBegin().getOopHandleAt((index - 1) * VM.getVM().getOopSize());
203 + }
204 +
190 205 // FIXME: add interpreter_entry_point()
191 206 // FIXME: add lazy_interpreter_entry_point() for C2
192 207
193 208 // **********
194 209 // * FIXME: * ADD ACCESS TO FLAGS!!!!
195 210 // **********
196 211 // public boolean isInUse();
197 212 // public boolean isAlive();
198 213 // public boolean isNotEntrant();
199 214 // public boolean isZombie();
200 215
201 216 // ********************************
202 217 // * MAJOR FIXME: MAJOR HACK HERE *
203 218 // ********************************
204 219 public boolean isZombie() { return false; }
205 220
206 221 // public boolean isUnloaded();
207 222 // public boolean isYoung();
208 223 // public boolean isOld();
209 224 // public int age();
210 225 // public boolean isMarkedForDeoptimization();
211 226 // public boolean isMarkedForUnloading();
212 227 // public boolean isMarkedForReclamation();
213 228 // public int level();
214 229 // public int version();
215 230
216 231 // FIXME: add mutators for above
217 232 // FIXME: add exception cache access?
218 233
219 234 /** On-stack replacement support */
220 235 // FIXME: add mutators
221 236 public int getOSREntryBCI() {
222 237 if (Assert.ASSERTS_ENABLED) {
223 238 Assert.that(getEntryBCI() != VM.getVM().getInvocationEntryBCI(), "wrong kind of nmethod");
224 239 }
225 240 return getEntryBCI();
226 241 }
227 242
228 243 public NMethod getOSRLink() {
229 244 return (NMethod) VMObjectFactory.newObject(NMethod.class, osrLinkField.getValue(addr));
230 245 }
231 246
232 247 public NMethod getScavengeRootLink() {
233 248 return (NMethod) VMObjectFactory.newObject(NMethod.class, scavengeRootLinkField.getValue(addr));
234 249 }
235 250
236 251 public int getScavengeRootState() {
237 252 return (int) scavengeRootStateField.getValue(addr);
238 253 }
239 254
240 255
241 256 /** Tells whether frames described by this nmethod can be
242 257 deoptimized. Note: native wrappers cannot be deoptimized. */
243 258 public boolean canBeDeoptimized() { return isJavaMethod(); }
244 259
245 260 // FIXME: add inline cache support
246 261 // FIXME: add flush()
247 262
248 263 public boolean isLockedByVM() { return lockCountField.getValue(addr) > 0; }
249 264
250 265 // FIXME: add mark_as_seen_on_stack
251 266 // FIXME: add can_not_entrant_be_converted
252 267
253 268 // FIXME: add GC support
254 269 // void follow_roots_or_mark_for_unloading(bool unloading_occurred, bool& marked_for_unloading);
255 270 // void follow_root_or_mark_for_unloading(oop* root, bool unloading_occurred, bool& marked_for_unloading);
256 271 // void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, void f(oop*));
257 272 // void adjust_pointers();
258 273
259 274 /** Finds a PCDesc with real-pc equal to "pc" */
260 275 public PCDesc getPCDescAt(Address pc) {
261 276 // FIXME: consider adding cache like the one down in the VM
262 277 for (Address p = scopesPCsBegin(); p.lessThan(scopesPCsEnd()); p = p.addOffsetTo(pcDescSize)) {
263 278 PCDesc pcDesc = new PCDesc(p);
264 279 if (pcDesc.getRealPC(this).equals(pc)) {
265 280 return pcDesc;
266 281 }
267 282 }
268 283 return null;
269 284 }
270 285
271 286 /** ScopeDesc for an instruction */
272 287 public ScopeDesc getScopeDescAt(Address pc) {
273 288 PCDesc pd = getPCDescAt(pc);
274 289 if (Assert.ASSERTS_ENABLED) {
275 290 Assert.that(pd != null, "scope must be present");
276 291 }
277 292 return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute());
278 293 }
279 294
280 295 /** This is only for use by the debugging system, and is only
281 296 intended for use in the topmost frame, where we are not
282 297 guaranteed to be at a PC for which we have a PCDesc. It finds
283 298 the PCDesc with realPC closest to the current PC. */
284 299 public PCDesc getPCDescNearDbg(Address pc) {
285 300 PCDesc bestGuessPCDesc = null;
286 301 long bestDistance = 0;
287 302 for (Address p = scopesPCsBegin(); p.lessThan(scopesPCsEnd()); p = p.addOffsetTo(pcDescSize)) {
288 303 PCDesc pcDesc = new PCDesc(p);
289 304 // In case pc is null
290 305 long distance = -pcDesc.getRealPC(this).minus(pc);
291 306 if ((bestGuessPCDesc == null) ||
292 307 ((distance >= 0) && (distance < bestDistance))) {
293 308 bestGuessPCDesc = pcDesc;
294 309 bestDistance = distance;
295 310 }
296 311 }
297 312 return bestGuessPCDesc;
298 313 }
299 314
300 315 /** This is only for use by the debugging system, and is only
301 316 intended for use in the topmost frame, where we are not
302 317 guaranteed to be at a PC for which we have a PCDesc. It finds
303 318 the ScopeDesc closest to the current PC. NOTE that this may
304 319 return NULL for compiled methods which don't have any
305 320 ScopeDescs! */
306 321 public ScopeDesc getScopeDescNearDbg(Address pc) {
307 322 PCDesc pd = getPCDescNearDbg(pc);
308 323 if (pd == null) return null;
309 324 return new ScopeDesc(this, pd.getScopeDecodeOffset(), pd.getObjDecodeOffset(), pd.getReexecute());
310 325 }
311 326
312 327 public Map/*<Address, PCDesc>*/ getSafepoints() {
313 328 Map safepoints = new HashMap(); // Map<Address, PCDesc>
314 329 sun.jvm.hotspot.debugger.Address p = null;
315 330 for (p = scopesPCsBegin(); p.lessThan(scopesPCsEnd());
316 331 p = p.addOffsetTo(pcDescSize)) {
317 332 PCDesc pcDesc = new PCDesc(p);
318 333 sun.jvm.hotspot.debugger.Address pc = pcDesc.getRealPC(this);
319 334 safepoints.put(pc, pcDesc);
320 335 }
321 336 return safepoints;
322 337 }
323 338
324 339 // FIXME: add getPCOffsetForBCI()
325 340 // FIXME: add embeddedOopAt()
326 341 // FIXME: add isDependentOn()
327 342 // FIXME: add isPatchableAt()
328 343
329 344 /** Support for code generation. Only here for proof-of-concept. */
330 345 public static int getEntryPointOffset() { return (int) entryPointField.getOffset(); }
↓ open down ↓ |
131 lines elided |
↑ open up ↑ |
331 346 public static int getVerifiedEntryPointOffset() { return (int) verifiedEntryPointField.getOffset(); }
332 347 public static int getOSREntryPointOffset() { return (int) osrEntryPointField.getOffset(); }
333 348 public static int getEntryBCIOffset() { return (int) entryBCIField.getOffset(); }
334 349 /** NOTE: renamed from "method_offset_in_bytes" */
335 350 public static int getMethodOffset() { return (int) methodField.getOffset(); }
336 351
337 352 public void print() {
338 353 printOn(System.out);
339 354 }
340 355
356 + protected void printComponentsOn(PrintStream tty) {
357 + // FIXME: add relocation information
358 + tty.println(" instructions: [" + instructionsBegin() + ", " + instructionsEnd() + "), " +
359 + " data: [" + dataBegin() + ", " + dataEnd() + "), " +
360 + " oops: [" + oopsBegin() + ", " + oopsEnd() + "), " +
361 + " frame size: " + getFrameSize());
362 + }
363 +
341 364 public String toString() {
342 365 Method method = getMethod();
343 366 return "NMethod for " +
344 367 method.getMethodHolder().getName().asString() + "." +
345 368 method.getName().asString() + method.getSignature().asString() + "==>n" +
346 369 super.toString();
347 370 }
348 371
349 372 public String flagsToString() {
350 373 // FIXME need access to flags...
351 374 return "";
352 375 }
353 376
354 377 public String getName() {
355 378 Method method = getMethod();
356 379 return "NMethod for " +
357 380 method.getMethodHolder().getName().asString() + "." +
358 381 method.getName().asString() +
359 382 method.getSignature().asString();
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
360 383 }
361 384
362 385 //--------------------------------------------------------------------------------
363 386 // Internals only below this point
364 387 //
365 388
366 389 private int getEntryBCI() { return (int) entryBCIField .getValue(addr); }
367 390 private int getExceptionOffset() { return (int) exceptionOffsetField .getValue(addr); }
368 391 private int getDeoptOffset() { return (int) deoptOffsetField .getValue(addr); }
369 392 private int getStubOffset() { return (int) stubOffsetField .getValue(addr); }
393 + private int getOopsOffset() { return (int) oopsOffsetField .getValue(addr); }
370 394 private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); }
371 395 private int getScopesPCsOffset() { return (int) scopesPCsOffsetField .getValue(addr); }
372 396 private int getDependenciesOffset() { return (int) dependenciesOffsetField.getValue(addr); }
373 397 private int getHandlerTableOffset() { return (int) handlerTableOffsetField.getValue(addr); }
374 398 private int getNulChkTableOffset() { return (int) nulChkTableOffsetField .getValue(addr); }
375 399 private int getNMethodEndOffset() { return (int) nmethodEndOffsetField .getValue(addr); }
376 400 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX