Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java @ 6972:bd7a7ce2e264
6830717: replay of compilations would help with debugging
Summary: When java process crashed in compiler thread, repeat the compilation process will help finding root cause. This is done with using SA dump application class data and replay data from core dump, then use debug version of jvm to recompile the problematic java method.
Reviewed-by: kvn, twisti, sspitsyn
Contributed-by: yumin.qi@oracle.com
author | minqi |
---|---|
date | Mon, 12 Nov 2012 14:03:53 -0800 |
parents | da91efe96a93 |
children | c5f6a7397eb1 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
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:
196
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
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:
196
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.runtime; | |
26 | |
27 import java.io.*; | |
28 import java.util.*; | |
29 import sun.jvm.hotspot.*; | |
30 import sun.jvm.hotspot.code.*; | |
31 import sun.jvm.hotspot.compiler.*; | |
32 import sun.jvm.hotspot.c1.*; | |
33 import sun.jvm.hotspot.debugger.*; | |
34 import sun.jvm.hotspot.interpreter.*; | |
35 import sun.jvm.hotspot.oops.*; | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
36 import sun.jvm.hotspot.runtime.sparc.SPARCFrame; |
0 | 37 import sun.jvm.hotspot.types.*; |
38 import sun.jvm.hotspot.utilities.*; | |
39 | |
40 /** <P> A frame represents a physical stack frame (an activation). | |
41 Frames can be C or Java frames, and the Java frames can be | |
42 interpreted or compiled. In contrast, vframes represent | |
43 source-level activations, so that one physical frame can | |
44 correspond to multiple source level frames because of inlining. | |
45 </P> | |
46 | |
47 <P> NOTE that this is not a VMObject and does not wrap an Address | |
48 -- this is an actual port of the VM's Frame code to Java. </P> | |
49 | |
50 <P> NOTE also that this is incomplete -- just trying to get | |
51 reading of interpreted frames working for now, so all non-core and | |
52 setter methods are removed for now. (FIXME) </P> */ | |
53 | |
54 public abstract class Frame implements Cloneable { | |
55 /** A raw stack pointer. The accessor getSP() will return a real (usable) | |
56 stack pointer (e.g. from Thread::last_Java_sp) */ | |
57 protected Address raw_sp; | |
58 | |
59 /** Program counter (the next instruction after the call) */ | |
60 protected Address pc; | |
61 protected boolean deoptimized; | |
62 | |
63 public Frame() { | |
64 deoptimized = false; | |
65 } | |
66 | |
67 static { | |
68 VM.registerVMInitializedObserver(new Observer() { | |
69 public void update(Observable o, Object data) { | |
70 initialize(VM.getVM().getTypeDataBase()); | |
71 } | |
72 }); | |
73 } | |
74 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
75 /** Size of ConstMethod for computing BCI from BCP (FIXME: hack) */ |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
76 private static long ConstMethodSize; |
0 | 77 |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
78 private static int pcReturnOffset; |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
79 |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
80 public static int pcReturnOffset() { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
81 return pcReturnOffset; |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
82 } |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
83 |
0 | 84 private static synchronized void initialize(TypeDataBase db) { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
85 Type ConstMethodType = db.lookupType("ConstMethod"); |
0 | 86 // FIXME: not sure whether alignment here is correct or how to |
87 // force it (round up to address size?) | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
88 ConstMethodSize = ConstMethodType.getSize(); |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
89 |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
90 pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue(); |
0 | 91 } |
92 | |
93 protected int bcpToBci(Address bcp, ConstMethod cm) { | |
94 // bcp will be null for interpreter native methods | |
95 // in addition depending on where we catch the system the value can | |
96 // be a bcp or a bci. | |
97 if (bcp == null) return 0; | |
98 long bci = bcp.minus(null); | |
99 if (bci >= 0 && bci < cm.getCodeSize()) return (int) bci; | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
100 return (int) (bcp.minus(cm.getAddress()) - ConstMethodSize); |
0 | 101 } |
102 | |
103 protected int bcpToBci(Address bcp, Method m) { | |
104 return bcpToBci(bcp, m.getConstMethod()); | |
105 } | |
106 | |
107 public abstract Object clone(); | |
108 | |
109 // Accessors | |
110 | |
111 /** pc: Returns the pc at which this frame will continue normally. | |
112 It must point at the beginning of the next instruction to | |
113 execute. */ | |
114 public Address getPC() { return pc; } | |
115 public void setPC(Address newpc) { pc = newpc; } | |
116 public boolean isDeoptimized() { return deoptimized; } | |
117 | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
118 public CodeBlob cb() { |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
119 return VM.getVM().getCodeCache().findBlob(getPC()); |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
120 } |
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
121 |
0 | 122 public abstract Address getSP(); |
123 public abstract Address getID(); | |
124 public abstract Address getFP(); | |
125 | |
126 /** testers -- platform dependent */ | |
127 public abstract boolean equals(Object arg); | |
128 | |
129 /** type testers */ | |
130 public boolean isInterpretedFrame() { return VM.getVM().getInterpreter().contains(getPC()); } | |
131 public boolean isJavaFrame() { | |
132 if (isInterpretedFrame()) return true; | |
133 if (!VM.getVM().isCore()) { | |
134 if (isCompiledFrame()) return true; | |
135 } | |
136 return false; | |
137 } | |
138 | |
139 /** Java frame called from C? */ | |
140 public boolean isEntryFrame() { return VM.getVM().getStubRoutines().returnsToCallStub(getPC()); } | |
141 public boolean isNativeFrame() { | |
142 if (!VM.getVM().isCore()) { | |
143 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); | |
144 return (cb != null && cb.isNativeMethod()); | |
145 } else { | |
146 return false; | |
147 } | |
148 } | |
149 | |
150 public boolean isCompiledFrame() { | |
151 if (Assert.ASSERTS_ENABLED) { | |
152 Assert.that(!VM.getVM().isCore(), "noncore builds only"); | |
153 } | |
154 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); | |
155 return (cb != null && cb.isJavaMethod()); | |
156 } | |
157 | |
3908
7588156f5cf9
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
1552
diff
changeset
|
158 public boolean isRuntimeFrame() { |
0 | 159 if (Assert.ASSERTS_ENABLED) { |
160 Assert.that(!VM.getVM().isCore(), "noncore builds only"); | |
161 } | |
162 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); | |
163 if (cb == null) { | |
164 return false; | |
165 } | |
166 if (cb.isRuntimeStub()) return true; | |
167 else return false; | |
168 } | |
169 | |
170 /** oldest frame? (has no sender) FIXME: this is modified from the | |
171 C++ code to handle the debugging situation where we try to | |
172 traverse the stack for, for example, the signal thread, and | |
173 don't find any valid Java frames. Would really like to put the | |
174 second half of the conditional in some sort of debugging-only if | |
175 statement. */ | |
176 // *** FIXME: THE CALL TO isJavaFrame() IS WAY TOO EXPENSIVE!!!!! *** | |
177 public boolean isFirstFrame() { return ((isEntryFrame() && entryFrameIsFirst()) || | |
178 (!isJavaFrame() && !hasSenderPD())); } | |
179 /** same for Java frame */ | |
180 public boolean isFirstJavaFrame() { throw new RuntimeException("not yet implemented"); } | |
181 | |
182 /** This is an addition for debugging purposes on platforms which | |
183 have the notion of signals. */ | |
184 public abstract boolean isSignalHandlerFrameDbg(); | |
185 | |
186 /** If this is a signal handler frame (again, on a platform with a | |
187 notion of signals), get the signal number. */ | |
188 public abstract int getSignalNumberDbg(); | |
189 | |
190 /** If this is a signal handler frame (again, on a platform with a | |
191 notion of signals), get the name of the signal. */ | |
192 public abstract String getSignalNameDbg(); | |
193 | |
194 /** performs sanity checks on interpreted frames. */ | |
195 public abstract boolean isInterpretedFrameValid(); | |
196 | |
197 /** tells whether this frame is marked for deoptimization */ | |
198 public boolean shouldBeDeoptimized() { throw new RuntimeException("not yet implemented"); } | |
199 | |
200 /** tells whether this frame can be deoptimized */ | |
201 public boolean canBeDeoptimized() { throw new RuntimeException("not yet implemented"); } | |
202 | |
203 /** returns the sending frame */ | |
204 public abstract Frame sender(RegisterMap map, CodeBlob nm); | |
205 | |
206 /** equivalent to sender(map, null) */ | |
207 public Frame sender(RegisterMap map) { return sender(map, null); } | |
208 | |
209 /** returns the sender, but skips conversion frames */ | |
210 public Frame realSender(RegisterMap map) { | |
211 if (!VM.getVM().isCore()) { | |
212 Frame result = sender(map); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
3908
diff
changeset
|
213 while (result.isRuntimeFrame()) { |
0 | 214 result = result.sender(map); |
215 } | |
216 return result; | |
217 } else { | |
218 return sender(map); | |
219 } | |
220 } | |
221 | |
222 /** Platform-dependent query indicating whether this frame has a | |
223 sender. Should return true if it is possible to call sender() at | |
224 all on this frame. (This is currently only needed for the | |
225 debugging system, if a stack trace is attempted for a Java | |
226 thread which has no Java frames, i.e., the signal thread; we | |
227 have to know to stop traversal at the bottom frame.) */ | |
228 protected abstract boolean hasSenderPD(); | |
229 | |
230 //-------------------------------------------------------------------------------- | |
231 // All frames: | |
232 // A low-level interface for vframes: | |
233 | |
234 /** Returns the address of the requested "slot" on the stack. Slots | |
235 are as wide as addresses, so are 32 bits wide on a 32-bit | |
236 machine and 64 bits wide on a 64-bit machine. */ | |
237 public Address addressOfStackSlot(int slot) { return getFP().addOffsetTo(slot * VM.getVM().getAddressSize()); } | |
238 | |
239 /** Fetches the OopHandle at the requested slot */ | |
240 public OopHandle getOopHandleAt(int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); } | |
241 /** Fetches the OopHandle at the slot, adjusted for compiler frames */ | |
242 // FIXME: looks like this is only used for compiled frames | |
243 // public OopHandle getOopHandleAtAdjusted(MethodOop method, int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); } | |
244 // FIXME: Not yet implementable | |
245 // public void setOopHandleAt(int slot, OopHandle value) { addressOfStackSlot(slot).setOopHandleAt(0, value); } | |
246 | |
247 /** Fetches the (Java) int at the requested slot */ | |
248 public int getIntAt(int slot) { return addressOfStackSlot(slot).getJIntAt(0); } | |
249 // FIXME: Not yet implementable | |
250 // public void setIntAt(int slot, int value) { addressOfStackSlot(slot).setJIntAt(0, value); } | |
251 | |
252 /** returns the frame size in stack slots */ | |
253 public abstract long frameSize(); | |
254 | |
255 /** Link (i.e., the pointer to the previous frame) */ | |
256 public abstract Address getLink(); | |
257 // public abstract void setLink(Address addr); | |
258 | |
259 /** Return address */ | |
260 public abstract Address getSenderPC(); | |
261 // FIXME: currently unimplementable | |
262 // public abstract void setSenderPC(Address addr); | |
263 | |
264 /** The frame's original SP, before any extension by an interpreted | |
265 callee; used for packing debug info into vframeArray objects and | |
266 vframeArray lookup. */ | |
267 public abstract Address getUnextendedSP(); | |
268 | |
269 /** Returns the stack pointer of the calling frame */ | |
270 public abstract Address getSenderSP(); | |
271 | |
272 //-------------------------------------------------------------------------------- | |
273 // Interpreter frames: | |
274 // | |
275 | |
276 public abstract Address addressOfInterpreterFrameLocals(); | |
277 | |
278 public Address addressOfInterpreterFrameLocal(int slot) { | |
279 return addressOfInterpreterFrameLocals().getAddressAt(0).addOffsetTo(-slot * VM.getVM().getAddressSize()); | |
280 } | |
281 | |
282 // FIXME: not yet implementable | |
283 // void interpreter_frame_set_locals(intptr_t* locs); | |
284 | |
285 // NOTE that the accessor "addressOfInterpreterFrameBCX" has | |
286 // necessarily been eliminated. The byte code pointer is inherently | |
287 // an interior pointer to a Method (the bytecodes follow the | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
288 // Method data structure) and therefore acquisition of it in |
0 | 289 // this system can not be allowed. All accesses to interpreter frame |
290 // byte codes are via the byte code index (BCI). | |
291 | |
292 /** Byte code index. In the underlying frame, what is actually | |
293 stored is a byte code pointer (BCP), which is converted to a BCI | |
294 and back by the GC when methods are moved. In this system, | |
295 interior pointers are not allowed, so we must make the access to | |
296 the interpreter frame's BCI atomic with respect to GC. This may | |
297 mean implementation with an underlying call through native code | |
298 into the VM or a magic sequence in the compiler. (FIXME) */ | |
299 public abstract int getInterpreterFrameBCI(); | |
300 // FIXME: not yet implementable | |
301 // public abstract void setInterpreterFrameBCI(int bci); | |
302 | |
303 // FIXME: elided for now | |
304 // public abstract Address addressOfInterpreterCalleeReceiver(Symbol signature); | |
305 | |
306 /** Find receiver for an invoke when arguments are just pushed on | |
307 stack (i.e., callee stack-frame is not setup) */ | |
308 // FIXME: elided for now | |
309 // public OopHandle getInterpreterCalleeReceiver(SymbolOop signature) { return addressOfInterpreterCalleeReceiver(signature).getOopHandleAt(0); } | |
310 | |
311 //-------------------------------------------------------------------------------- | |
312 // Expression stack (may go up or down, direction == 1 or -1) | |
313 // | |
314 | |
315 public abstract Address addressOfInterpreterFrameExpressionStack(); | |
316 public abstract int getInterpreterFrameExpressionStackDirection(); | |
317 public Address addressOfInterpreterFrameExpressionStackSlot(int slot) { | |
318 return addressOfInterpreterFrameExpressionStack().addOffsetTo(-slot * VM.getVM().getAddressSize()); | |
319 } | |
320 | |
321 /** Top of expression stack */ | |
322 public abstract Address addressOfInterpreterFrameTOS(); | |
323 | |
324 /** Expression stack from top down */ | |
325 public abstract Address addressOfInterpreterFrameTOSAt(int slot); | |
326 | |
327 /** FIXME: is this portable? */ | |
328 public int getInterpreterFrameExpressionStackSize() { | |
329 return (int) (1 + (getInterpreterFrameExpressionStackDirection() * | |
330 (addressOfInterpreterFrameTOS().minus(addressOfInterpreterFrameExpressionStack())))); | |
331 } | |
332 | |
333 public abstract Address getInterpreterFrameSenderSP(); | |
334 // FIXME: not yet implementable | |
335 // public abstract void setInterpreterFrameSenderSP(Address senderSP); | |
336 | |
337 //-------------------------------------------------------------------------------- | |
338 // BasicObjectLocks: | |
339 // | |
340 | |
341 public abstract BasicObjectLock interpreterFrameMonitorBegin(); | |
342 public abstract BasicObjectLock interpreterFrameMonitorEnd(); | |
343 /** NOTE: this returns a size in BYTES in this system! */ | |
344 public abstract int interpreterFrameMonitorSize(); | |
345 public BasicObjectLock nextMonitorInInterpreterFrame(BasicObjectLock cur) { | |
346 return new BasicObjectLock(cur.address().addOffsetTo(interpreterFrameMonitorSize())); | |
347 } | |
348 public BasicObjectLock previousMonitorInInterpreterFrame(BasicObjectLock cur) { | |
349 return new BasicObjectLock(cur.address().addOffsetTo(-1 * interpreterFrameMonitorSize())); | |
350 } | |
351 | |
352 // interpreter_frame_monitor_begin is higher in memory than interpreter_frame_monitor_end | |
353 // Interpreter_frame_monitor_begin points to one element beyond the oldest one, | |
354 // interpreter_frame_monitor_end points to the youngest one, or if there are none, | |
355 // it points to one beyond where the first element will be. | |
356 // interpreter_frame_monitor_size reports the allocation size of a monitor in the interpreter stack. | |
357 // this value is >= BasicObjectLock::size(), and may be rounded up | |
358 | |
359 // FIXME: avoiding implementing this for now if possible | |
360 // public void interpreter_frame_set_monitor_end(BasicObjectLock* value); | |
361 // public void interpreter_frame_verify_monitor(BasicObjectLock* value) const; | |
362 // | |
363 // Tells whether the current interpreter_frame frame pointer | |
364 // corresponds to the old compiled/deoptimized fp | |
365 // The receiver used to be a top level frame | |
366 // public boolean interpreter_frame_equals_unpacked_fp(intptr_t* fp); | |
367 | |
368 //-------------------------------------------------------------------------------- | |
369 // Method and constant pool cache: | |
370 // | |
371 | |
372 /** Current method */ | |
373 public abstract Address addressOfInterpreterFrameMethod(); | |
374 | |
375 /** Current method */ | |
376 public Method getInterpreterFrameMethod() { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
377 return (Method)Metadata.instantiateWrapperFor(addressOfInterpreterFrameMethod().getAddressAt(0)); |
0 | 378 } |
379 | |
380 /** Current method */ | |
381 // FIXME: not yet implementable | |
382 // public void setInterpreterFrameMethod(Method method); | |
383 | |
384 /** Constant pool cache */ | |
385 public abstract Address addressOfInterpreterFrameCPCache(); | |
386 /** Constant pool cache */ | |
387 public ConstantPoolCache getInterpreterFrameCPCache() { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
388 return (ConstantPoolCache) Metadata.instantiateWrapperFor(addressOfInterpreterFrameCPCache().getAddressAt(0)); |
0 | 389 } |
390 | |
391 //-------------------------------------------------------------------------------- | |
392 // Entry frames: | |
393 // | |
394 | |
395 public abstract JavaCallWrapper getEntryFrameCallWrapper(); | |
396 | |
397 // FIXME: add | |
398 // inline intptr_t* entry_frame_argument_at(int offset) const; | |
399 | |
400 | |
401 /** Tells whether there is another chunk of Delta stack above */ | |
402 public boolean entryFrameIsFirst() { return (getEntryFrameCallWrapper().getLastJavaSP() == null); } | |
403 | |
404 //-------------------------------------------------------------------------------- | |
405 // Safepoints: | |
406 // | |
407 | |
408 protected abstract Address addressOfSavedOopResult(); | |
409 protected abstract Address addressOfSavedReceiver(); | |
410 | |
411 public OopHandle getSavedOopResult() { | |
412 return addressOfSavedOopResult().getOopHandleAt(0); | |
413 } | |
414 | |
415 // FIXME: not yet implementable | |
416 // public void setSavedOopResult(OopHandle obj); | |
417 | |
418 public OopHandle getSavedReceiver() { | |
419 return addressOfSavedReceiver().getOopHandleAt(0); | |
420 } | |
421 | |
422 // FIXME: not yet implementable | |
423 // public void setSavedReceiver(OopHandle obj); | |
424 | |
425 //-------------------------------------------------------------------------------- | |
426 // Oop traversals: | |
427 // | |
428 | |
429 public void oopsInterpretedArgumentsDo(Symbol signature, boolean isStatic, AddressVisitor f) { | |
430 ArgumentOopFinder finder = new ArgumentOopFinder(signature, isStatic, this, f); | |
431 finder.oopsDo(); | |
432 } | |
433 | |
434 /** Conversion from an VMReg::Name to physical stack location */ | |
435 public Address oopMapRegToLocation(VMReg reg, RegisterMap regMap) { | |
436 VMReg stack0 = VM.getVM().getVMRegImplInfo().getStack0(); | |
437 if (reg.lessThan(stack0)) { | |
438 // If it is passed in a register, it got spilled in the stub frame. | |
439 return regMap.getLocation(reg); | |
440 } else { | |
441 long spOffset = VM.getVM().getAddressSize() * reg.minus(stack0); | |
442 return getUnextendedSP().addOffsetTo(spOffset); | |
443 } | |
444 } | |
445 | |
446 public void oopsDo(AddressVisitor oopVisitor, RegisterMap map) { | |
447 if (isInterpretedFrame()) { | |
448 oopsInterpretedDo(oopVisitor, map); | |
449 } else if (isEntryFrame()) { | |
450 oopsEntryDo(oopVisitor, map); | |
451 } else if (VM.getVM().getCodeCache().contains(getPC())) { | |
452 oopsCodeBlobDo(oopVisitor, map); | |
453 } else { | |
454 Assert.that(false, "should not reach here"); | |
455 } | |
456 } | |
457 | |
458 //-------------------------------------------------------------------------------- | |
459 // Printing code | |
460 // | |
461 | |
462 public void printValue() { | |
463 printValueOn(System.out); | |
464 } | |
465 | |
466 public void printValueOn(PrintStream tty) { | |
467 // FIXME; | |
468 } | |
469 | |
470 public void print() { | |
471 printOn(System.out); | |
472 } | |
473 | |
474 public void printOn(PrintStream tty) { | |
475 // FIXME; | |
476 } | |
477 | |
478 public void interpreterFramePrintOn(PrintStream tty) { | |
479 // FIXME; | |
480 } | |
481 | |
482 //-------------------------------------------------------------------------------- | |
483 // Get/set typed locals from a frame. | |
484 // Respects platform dependent word-ordering. | |
485 // | |
486 // FIXME: avoiding implementing this for now if possible | |
487 // | |
488 // Currently these work only for interpreted frames. | |
489 // Todo: make these work for compiled frames. | |
490 // | |
491 // oop get_local_object(jint slot) const; | |
492 // jint get_local_int (jint slot) const; | |
493 // jlong get_local_long (jint slot) const; | |
494 // jfloat get_local_float (jint slot) const; | |
495 // jdouble get_local_double(jint slot) const; | |
496 // | |
497 // void set_local_object(jint slot, oop obj); | |
498 // void set_local_int (jint slot, jint i); | |
499 // void set_local_long (jint slot, jlong l); | |
500 // void set_local_float (jint slot, jfloat f); | |
501 // void set_local_double(jint slot, jdouble d); | |
502 | |
503 // FIXME: add safepoint code, oops_do, etc. | |
504 // FIXME: NOT FINISHED | |
505 | |
506 | |
507 | |
508 | |
509 | |
510 //-------------------------------------------------------------------------------- | |
511 // Internals only below this point | |
512 // | |
513 | |
514 // /** Helper method for better factored code in frame::sender */ | |
515 // private frame sender_for_entry_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); } | |
516 // private frame sender_for_interpreter_frame(RegisterMap* map) { throw new RuntimeException("not yet implemented"); } | |
517 | |
518 // | |
519 // Oop iteration (FIXME: NOT FINISHED) | |
520 // | |
521 | |
522 | |
523 private static class InterpVisitor implements OopMapVisitor { | |
524 private AddressVisitor addressVisitor; | |
525 | |
526 public InterpVisitor(AddressVisitor oopVisitor) { | |
527 setAddressVisitor(oopVisitor); | |
528 } | |
529 | |
530 public void setAddressVisitor(AddressVisitor addressVisitor) { | |
531 this.addressVisitor = addressVisitor; | |
532 } | |
533 | |
534 public void visitOopLocation(Address oopAddr) { | |
535 addressVisitor.visitAddress(oopAddr); | |
536 } | |
537 | |
538 public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) { | |
539 if (VM.getVM().isClientCompiler()) { | |
540 Assert.that(false, "should not reach here"); | |
541 } else if (VM.getVM().isServerCompiler() && | |
542 VM.getVM().useDerivedPointerTable()) { | |
543 Assert.that(false, "FIXME: add derived pointer table"); | |
544 } | |
545 } | |
546 | |
547 public void visitValueLocation(Address valueAddr) { | |
548 } | |
549 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
550 public void visitNarrowOopLocation(Address compOopAddr) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
551 addressVisitor.visitCompOopAddress(compOopAddr); |
0 | 552 } |
553 } | |
554 | |
555 private void oopsInterpretedDo(AddressVisitor oopVisitor, RegisterMap map) { | |
556 if (Assert.ASSERTS_ENABLED) { | |
557 Assert.that(map != null, "map must be set"); | |
558 } | |
559 Method m = getInterpreterFrameMethod(); | |
560 int bci = getInterpreterFrameBCI(); | |
561 | |
562 // FIXME: Seeing this sometimes | |
563 if (VM.getVM().isDebugging()) { | |
564 if (bci < 0 || bci >= m.getCodeSize()) return; | |
565 } | |
566 | |
567 if (Assert.ASSERTS_ENABLED) { | |
568 // Assert.that(VM.getVM().getUniverse().heap().isIn(m), "method must be valid oop"); | |
569 Assert.that((m.isNative() && (bci == 0)) || ((bci >= 0) && (bci < m.getCodeSize())), "invalid bci value"); | |
570 } | |
571 | |
572 // Handle the monitor elements in the activation | |
573 // FIXME: monitor information not yet exposed | |
574 // for ( | |
575 // BasicObjectLock* current = interpreter_frame_monitor_end(); | |
576 // current < interpreter_frame_monitor_begin(); | |
577 // current = next_monitor_in_interpreter_frame(current) | |
578 // ) { | |
579 //#ifdef ASSERT | |
580 // interpreter_frame_verify_monitor(current); | |
581 //#endif | |
582 // current->oops_do(f); | |
583 // } | |
584 | |
585 // process fixed part | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
586 // FIXME: these are no longer oops, so should anything be visitied? |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
587 // oopVisitor.visitAddress(addressOfInterpreterFrameMethod()); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6266
diff
changeset
|
588 // oopVisitor.visitAddress(addressOfInterpreterFrameCPCache()); |
0 | 589 |
590 // FIXME: expose interpreterFrameMirrorOffset | |
591 // if (m.isNative() && m.isStatic()) { | |
592 // oopVisitor.visitAddress(getFP().addOffsetTo(interpreterFrameMirrorOffset)); | |
593 // } | |
594 | |
595 int maxLocals = (int) (m.isNative() ? m.getSizeOfParameters() : m.getMaxLocals()); | |
596 InterpreterFrameClosure blk = new InterpreterFrameClosure(this, maxLocals, (int) m.getMaxStack(), oopVisitor); | |
597 | |
598 // process locals & expression stack | |
599 OopMapCacheEntry mask = m.getMaskFor(bci); | |
600 mask.iterateOop(blk); | |
601 | |
602 // process a callee's arguments if we are at a call site | |
603 // (i.e., if we are at an invoke bytecode) | |
604 if (map.getIncludeArgumentOops() && !m.isNative()) { | |
605 BytecodeInvoke call = BytecodeInvoke.atCheck(m, bci); | |
606 if (call != null && getInterpreterFrameExpressionStackSize() > 0) { | |
607 // we are at a call site & the expression stack is not empty | |
608 // => process callee's arguments | |
609 // | |
610 // Note: The expression stack can be empty if an exception | |
611 // occured during method resolution/execution. In all | |
612 // cases we empty the expression stack completely be- | |
613 // fore handling the exception (the exception handling | |
614 // code in the interpreter calls a blocking runtime | |
615 // routine which can cause this code to be executed). | |
616 // (was bug gri 7/27/98) | |
617 oopsInterpretedArgumentsDo(call.signature(), call.isInvokestatic(), oopVisitor); | |
618 } | |
619 } | |
620 } | |
621 | |
622 private void oopsEntryDo (AddressVisitor oopVisitor, RegisterMap regMap) {} | |
623 private void oopsCodeBlobDo (AddressVisitor oopVisitor, RegisterMap regMap) { | |
624 CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC()); | |
625 if (Assert.ASSERTS_ENABLED) { | |
626 Assert.that(cb != null, "sanity check"); | |
627 } | |
628 if (cb.getOopMaps() != null) { | |
629 OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging()); | |
630 | |
631 // FIXME: add in traversal of argument oops (skipping this for | |
632 // now until we have the other stuff tested) | |
633 | |
634 } | |
635 | |
636 // FIXME: would add this in in non-debugging system | |
637 | |
638 // If we see an activation belonging to a non_entrant nmethod, we mark it. | |
639 // if (cb->is_nmethod() && ((nmethod *)cb)->is_not_entrant()) { | |
640 // ((nmethod*)cb)->mark_as_seen_on_stack(); | |
641 // } | |
642 } | |
643 | |
644 // FIXME: implement the above routines, plus add | |
645 // oops_interpreted_arguments_do and oops_compiled_arguments_do | |
646 } | |
647 | |
648 // | |
649 // Only used internally, to iterate through oop slots in interpreted | |
650 // frames | |
651 // | |
652 class InterpreterFrameClosure implements OffsetClosure { | |
653 // Used for debugging this code | |
654 private static final boolean DEBUG = false; | |
655 | |
656 private Frame fr; | |
657 private AddressVisitor f; | |
658 private int maxLocals; | |
659 private int maxStack; | |
660 | |
661 InterpreterFrameClosure(Frame fr, int maxLocals, int maxStack, AddressVisitor f) { | |
662 this.fr = fr; | |
663 this.maxLocals = maxLocals; | |
664 this.maxStack = maxStack; | |
665 this.f = f; | |
666 } | |
667 | |
668 public void offsetDo(int offset) { | |
669 if (DEBUG) { | |
670 System.err.println("Visiting offset " + offset + ", maxLocals = " + maxLocals + | |
671 " for frame " + fr + ", method " + | |
672 fr.getInterpreterFrameMethod().getMethodHolder().getName().asString() + | |
673 fr.getInterpreterFrameMethod().getName().asString()); | |
674 } | |
675 Address addr; | |
676 if (offset < maxLocals) { | |
677 addr = fr.addressOfInterpreterFrameLocal(offset); | |
678 if (Assert.ASSERTS_ENABLED) { | |
679 Assert.that(AddressOps.gte(addr, fr.getSP()), "must be inside the frame"); | |
680 } | |
681 if (DEBUG) { | |
682 System.err.println(" Visiting local at addr " + addr); | |
683 } | |
684 f.visitAddress(addr); | |
685 } else { | |
686 addr = fr.addressOfInterpreterFrameExpressionStackSlot(offset - maxLocals); | |
687 if (DEBUG) { | |
688 System.err.println(" Address of expression stack slot: " + addr + ", TOS = " + | |
689 fr.addressOfInterpreterFrameTOS()); | |
690 } | |
691 // In case of exceptions, the expression stack is invalid and the esp will be reset to express | |
692 // this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel). | |
693 boolean inStack; | |
694 if (fr.getInterpreterFrameExpressionStackDirection() > 0) { | |
695 inStack = AddressOps.lte(addr, fr.addressOfInterpreterFrameTOS()); | |
696 } else { | |
697 inStack = AddressOps.gte(addr, fr.addressOfInterpreterFrameTOS()); | |
698 } | |
699 if (inStack) { | |
700 if (DEBUG) { | |
701 System.err.println(" In stack; visiting location."); | |
702 } | |
703 f.visitAddress(addr); | |
704 } else if (DEBUG) { | |
705 System.err.println(" *** WARNING: Address is out of bounds"); | |
706 } | |
707 } | |
708 } | |
709 } | |
710 | |
711 // Only used internally, to find arguments in interpreted frames | |
712 class ArgumentOopFinder extends SignatureInfo { | |
713 private AddressVisitor f; | |
714 private int offset; | |
715 private boolean isStatic; | |
716 private Frame fr; | |
717 | |
718 protected void set(int size, int type) { | |
719 offset -= size; | |
720 if (type == BasicType.getTObject() || type == BasicType.getTArray()) oopOffsetDo(); | |
721 } | |
722 | |
723 private void oopOffsetDo() { | |
724 f.visitAddress(fr.addressOfInterpreterFrameTOSAt(offset)); | |
725 } | |
726 | |
727 public ArgumentOopFinder(Symbol signature, boolean isStatic, Frame fr, AddressVisitor f) { | |
728 super(signature); | |
729 | |
730 // compute size of arguments | |
731 int argsSize = new ArgumentSizeComputer(signature).size() + (isStatic ? 0 : 1); | |
732 if (Assert.ASSERTS_ENABLED) { | |
733 Assert.that(!fr.isInterpretedFrame() || | |
734 argsSize <= fr.getInterpreterFrameExpressionStackSize(), "args cannot be on stack anymore"); | |
735 } | |
736 // initialize ArgumentOopFinder | |
737 this.f = f; | |
738 this.fr = fr; | |
739 this.offset = argsSize; | |
740 this.isStatic = isStatic; | |
741 } | |
742 | |
743 public void oopsDo() { | |
744 if (!isStatic) { | |
745 --offset; | |
746 oopOffsetDo(); | |
747 } | |
748 iterateParameters(); | |
749 } | |
750 } |