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