comparison agent/src/share/classes/sun/jvm/hotspot/runtime/Frame.java @ 0:a61af66fc99e jdk7-b24

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