View Javadoc
1   /*
2    * Copyright (c) 2000, 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20   * or visit www.oracle.com if you need additional information or have any
21   * 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.runtime.sparc.SPARCFrame;
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 ConstMethod for computing BCI from BCP (FIXME: hack) */
76    private static long    ConstMethodSize;
77  
78    private static int pcReturnOffset;
79  
80    public static int pcReturnOffset() {
81      return pcReturnOffset;
82    }
83  
84    private static synchronized void initialize(TypeDataBase db) {
85      Type ConstMethodType = db.lookupType("ConstMethod");
86      // FIXME: not sure whether alignment here is correct or how to
87      // force it (round up to address size?)
88      ConstMethodSize = ConstMethodType.getSize();
89  
90      pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue();
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.getAddress()) - ConstMethodSize);
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 
118   public CodeBlob cb() {
119     return VM.getVM().getCodeCache().findBlob(getPC());
120   }
121 
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 
158   public boolean isRuntimeFrame() {
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);
213       while (result.isRuntimeFrame()) {
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
288   // Method data structure) and therefore acquisition of it in
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() {
377     return (Method)Metadata.instantiateWrapperFor(addressOfInterpreterFrameMethod().getAddressAt(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() {
388     return (ConstantPoolCache) Metadata.instantiateWrapperFor(addressOfInterpreterFrameCPCache().getAddressAt(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 
550     public void visitNarrowOopLocation(Address compOopAddr) {
551       addressVisitor.visitCompOopAddress(compOopAddr);
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
586     // FIXME: these are no longer oops, so should anything be visitied?
587     // oopVisitor.visitAddress(addressOfInterpreterFrameMethod());
588     // oopVisitor.visitAddress(addressOfInterpreterFrameCPCache());
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 }