/*
 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.runtime;

import java.io.*;
import java.util.*;
import sun.jvm.hotspot.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*;
import sun.jvm.hotspot.c1.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.sparc.SPARCFrame;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;

/** <P> A frame represents a physical stack frame (an activation).
    Frames can be C or Java frames, and the Java frames can be
    interpreted or compiled. In contrast, vframes represent
    source-level activations, so that one physical frame can
    correspond to multiple source level frames because of inlining.
    </P>

    <P> NOTE that this is not a VMObject and does not wrap an Address
    -- this is an actual port of the VM's Frame code to Java. </P>

    <P> NOTE also that this is incomplete -- just trying to get
    reading of interpreted frames working for now, so all non-core and
    setter methods are removed for now. (FIXME) </P> */

public abstract class Frame implements Cloneable {
  /** A raw stack pointer. The accessor getSP() will return a real (usable)
      stack pointer (e.g. from Thread::last_Java_sp) */
  protected Address raw_sp;

  /** Program counter (the next instruction after the call) */
  protected Address pc;
  protected boolean deoptimized;

  public Frame() {
    deoptimized = false;
  }

  static {
    VM.registerVMInitializedObserver(new Observer() {
        public void update(Observable o, Object data) {
          initialize(VM.getVM().getTypeDataBase());
        }
      });
  }

  /** Size of ConstMethod for computing BCI from BCP (FIXME: hack) */
  private static long    ConstMethodSize;

  private static int pcReturnOffset;

  public static int pcReturnOffset() {
    return pcReturnOffset;
  }

  private static synchronized void initialize(TypeDataBase db) {
    Type ConstMethodType = db.lookupType("ConstMethod");
    // FIXME: not sure whether alignment here is correct or how to
    // force it (round up to address size?)
    ConstMethodSize = ConstMethodType.getSize();

    pcReturnOffset = db.lookupIntConstant("frame::pc_return_offset").intValue();
  }

  protected int bcpToBci(Address bcp, ConstMethod cm) {
    // bcp will be null for interpreter native methods
    // in addition depending on where we catch the system the value can
    // be a bcp or a bci.
    if (bcp == null) return 0;
    long bci = bcp.minus(null);
    if (bci >= 0 && bci < cm.getCodeSize()) return (int) bci;
    return (int) (bcp.minus(cm.getAddress()) - ConstMethodSize);
  }

  protected int bcpToBci(Address bcp, Method m) {
    return bcpToBci(bcp, m.getConstMethod());
  }

  public abstract Object clone();

  // Accessors

  /** pc: Returns the pc at which this frame will continue normally.
      It must point at the beginning of the next instruction to
      execute. */
  public Address getPC()              { return pc; }
  public void    setPC(Address newpc) { pc = newpc; }
  public boolean isDeoptimized()      { return deoptimized; }

  public CodeBlob cb() {
    return VM.getVM().getCodeCache().findBlob(getPC());
  }

  public abstract Address getSP();
  public abstract Address getID();
  public abstract Address getFP();

  /** testers -- platform dependent */
  public abstract boolean equals(Object arg);

  /** type testers */
  public boolean isInterpretedFrame()           { return VM.getVM().getInterpreter().contains(getPC()); }
  public boolean isJavaFrame() {
    if (isInterpretedFrame()) return true;
    if (!VM.getVM().isCore()) {
      if (isCompiledFrame())    return true;
    }
    return false;
  }

  /** Java frame called from C? */
  public boolean isEntryFrame()                 { return VM.getVM().getStubRoutines().returnsToCallStub(getPC()); }
  public boolean isNativeFrame() {
    if (!VM.getVM().isCore()) {
      CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
      return (cb != null && cb.isNativeMethod());
    } else {
      return false;
    }
  }

  public boolean isCompiledFrame() {
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(!VM.getVM().isCore(), "noncore builds only");
    }
    CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
    return (cb != null && cb.isJavaMethod());
  }

  public boolean isRuntimeFrame() {
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(!VM.getVM().isCore(), "noncore builds only");
    }
    CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
    if (cb == null) {
      return false;
    }
    if (cb.isRuntimeStub()) return true;
    else return false;
  }

  /** oldest frame? (has no sender) FIXME: this is modified from the
      C++ code to handle the debugging situation where we try to
      traverse the stack for, for example, the signal thread, and
      don't find any valid Java frames. Would really like to put the
      second half of the conditional in some sort of debugging-only if
      statement. */
  // *** FIXME: THE CALL TO isJavaFrame() IS WAY TOO EXPENSIVE!!!!! ***
  public boolean isFirstFrame()                 { return ((isEntryFrame() && entryFrameIsFirst()) ||
                                                          (!isJavaFrame() && !hasSenderPD()));       }
  /** same for Java frame */
  public boolean isFirstJavaFrame()             { throw new RuntimeException("not yet implemented"); }

  /** This is an addition for debugging purposes on platforms which
      have the notion of signals. */
  public abstract boolean isSignalHandlerFrameDbg();

  /** If this is a signal handler frame (again, on a platform with a
      notion of signals), get the signal number. */
  public abstract int getSignalNumberDbg();

  /** If this is a signal handler frame (again, on a platform with a
      notion of signals), get the name of the signal. */
  public abstract String getSignalNameDbg();

  /** performs sanity checks on interpreted frames. */
  public abstract boolean isInterpretedFrameValid();

  /** tells whether this frame is marked for deoptimization */
  public boolean shouldBeDeoptimized()          { throw new RuntimeException("not yet implemented"); }

  /** tells whether this frame can be deoptimized */
  public boolean canBeDeoptimized()             { throw new RuntimeException("not yet implemented"); }

  /** returns the sending frame */
  public abstract Frame sender(RegisterMap map, CodeBlob nm);

  /** equivalent to sender(map, null) */
  public Frame sender(RegisterMap map)          { return sender(map, null); }

  /** returns the sender, but skips conversion frames */
  public Frame realSender(RegisterMap map) {
    if (!VM.getVM().isCore()) {
      Frame result = sender(map);
      while (result.isRuntimeFrame()) {
        result = result.sender(map);
      }
      return result;
    } else {
      return sender(map);
    }
  }

  /** Platform-dependent query indicating whether this frame has a
      sender. Should return true if it is possible to call sender() at
      all on this frame. (This is currently only needed for the
      debugging system, if a stack trace is attempted for a Java
      thread which has no Java frames, i.e., the signal thread; we
      have to know to stop traversal at the bottom frame.) */
  protected abstract boolean hasSenderPD();

  //--------------------------------------------------------------------------------
  // All frames:
  // A low-level interface for vframes:

  /** Returns the address of the requested "slot" on the stack. Slots
      are as wide as addresses, so are 32 bits wide on a 32-bit
      machine and 64 bits wide on a 64-bit machine. */
  public Address   addressOfStackSlot(int slot)              { return getFP().addOffsetTo(slot * VM.getVM().getAddressSize()); }

  /** Fetches the OopHandle at the requested slot */
  public OopHandle getOopHandleAt(int slot)                  { return addressOfStackSlot(slot).getOopHandleAt(0);              }
  /** Fetches the OopHandle at the slot, adjusted for compiler frames */
  // FIXME: looks like this is only used for compiled frames
  //  public OopHandle getOopHandleAtAdjusted(MethodOop method, int slot) { return addressOfStackSlot(slot).getOopHandleAt(0); }
  // FIXME: Not yet implementable
  //  public void  setOopHandleAt(int slot, OopHandle value) { addressOfStackSlot(slot).setOopHandleAt(0, value);              }

  /** Fetches the (Java) int at the requested slot */
  public int       getIntAt(int slot)                        { return addressOfStackSlot(slot).getJIntAt(0);                   }
  // FIXME: Not yet implementable
  // public void setIntAt(int slot, int value)               { addressOfStackSlot(slot).setJIntAt(0, value);                   }

  /** returns the frame size in stack slots */
  public abstract long frameSize();

  /** Link (i.e., the pointer to the previous frame) */
  public abstract Address getLink();
  //  public abstract void    setLink(Address addr);

  /** Return address */
  public abstract Address getSenderPC();
  // FIXME: currently unimplementable
  //  public abstract void    setSenderPC(Address addr);

  /** The frame's original SP, before any extension by an interpreted
      callee; used for packing debug info into vframeArray objects and
      vframeArray lookup. */
  public abstract Address getUnextendedSP();

  /** Returns the stack pointer of the calling frame */
  public abstract Address getSenderSP();

  //--------------------------------------------------------------------------------
  // Interpreter frames:
  //

  public abstract Address addressOfInterpreterFrameLocals();

  public Address addressOfInterpreterFrameLocal(int slot) {
    return addressOfInterpreterFrameLocals().getAddressAt(0).addOffsetTo(-slot * VM.getVM().getAddressSize());
  }

  // FIXME: not yet implementable
  //  void interpreter_frame_set_locals(intptr_t* locs);

  // NOTE that the accessor "addressOfInterpreterFrameBCX" has
  // necessarily been eliminated. The byte code pointer is inherently
  // an interior pointer to a Method (the bytecodes follow the
  // Method data structure) and therefore acquisition of it in
  // this system can not be allowed. All accesses to interpreter frame
  // byte codes are via the byte code index (BCI).

  /** Byte code index. In the underlying frame, what is actually
      stored is a byte code pointer (BCP), which is converted to a BCI
      and back by the GC when methods are moved. In this system,
      interior pointers are not allowed, so we must make the access to
      the interpreter frame's BCI atomic with respect to GC. This may
      mean implementation with an underlying call through native code
      into the VM or a magic sequence in the compiler. (FIXME) */
  public abstract int     getInterpreterFrameBCI();
  // FIXME: not yet implementable
  // public abstract void setInterpreterFrameBCI(int bci);

  // FIXME: elided for now
  //  public abstract Address addressOfInterpreterCalleeReceiver(Symbol signature);

  /** Find receiver for an invoke when arguments are just pushed on
      stack (i.e., callee stack-frame is not setup) */
  // FIXME: elided for now
  //  public OopHandle getInterpreterCalleeReceiver(SymbolOop signature) { return addressOfInterpreterCalleeReceiver(signature).getOopHandleAt(0); }

  //--------------------------------------------------------------------------------
  // Expression stack (may go up or down, direction == 1 or -1)
  //

  public abstract Address addressOfInterpreterFrameExpressionStack();
  public abstract int     getInterpreterFrameExpressionStackDirection();
  public Address addressOfInterpreterFrameExpressionStackSlot(int slot) {
    return addressOfInterpreterFrameExpressionStack().addOffsetTo(-slot * VM.getVM().getAddressSize());
  }

  /** Top of expression stack */
  public abstract Address addressOfInterpreterFrameTOS();

  /** Expression stack from top down */
  public abstract Address addressOfInterpreterFrameTOSAt(int slot);

  /** FIXME: is this portable? */
  public int getInterpreterFrameExpressionStackSize() {
    return (int) (1 + (getInterpreterFrameExpressionStackDirection() *
                       (addressOfInterpreterFrameTOS().minus(addressOfInterpreterFrameExpressionStack()))));
  }

  public abstract Address getInterpreterFrameSenderSP();
  // FIXME: not yet implementable
  //  public abstract void    setInterpreterFrameSenderSP(Address senderSP);

  //--------------------------------------------------------------------------------
  // BasicObjectLocks:
  //

  public abstract BasicObjectLock interpreterFrameMonitorBegin();
  public abstract BasicObjectLock interpreterFrameMonitorEnd();
  /** NOTE: this returns a size in BYTES in this system! */
  public abstract int     interpreterFrameMonitorSize();
  public          BasicObjectLock nextMonitorInInterpreterFrame(BasicObjectLock cur) {
    return new BasicObjectLock(cur.address().addOffsetTo(interpreterFrameMonitorSize()));
  }
  public          BasicObjectLock previousMonitorInInterpreterFrame(BasicObjectLock cur) {
    return new BasicObjectLock(cur.address().addOffsetTo(-1 * interpreterFrameMonitorSize()));
  }

  // interpreter_frame_monitor_begin is higher in memory than interpreter_frame_monitor_end
  // Interpreter_frame_monitor_begin points to one element beyond the oldest one,
  // interpreter_frame_monitor_end   points to the youngest one, or if there are none,
  //                                 it points to one beyond where the first element will be.
  // interpreter_frame_monitor_size  reports the allocation size of a monitor in the interpreter stack.
  //                                 this value is >= BasicObjectLock::size(), and may be rounded up

  // FIXME: avoiding implementing this for now if possible
  //  public void interpreter_frame_set_monitor_end(BasicObjectLock* value);
  //  public void interpreter_frame_verify_monitor(BasicObjectLock* value) const;
  //
  // Tells whether the current interpreter_frame frame pointer
  // corresponds to the old compiled/deoptimized fp
  // The receiver used to be a top level frame
  // public boolean interpreter_frame_equals_unpacked_fp(intptr_t* fp);

  //--------------------------------------------------------------------------------
  // Method and constant pool cache:
  //

  /** Current method */
  public abstract Address  addressOfInterpreterFrameMethod();

  /** Current method */
  public Method            getInterpreterFrameMethod() {
    return (Method)Metadata.instantiateWrapperFor(addressOfInterpreterFrameMethod().getAddressAt(0));
  }

  /** Current method */
  // FIXME: not yet implementable
  //  public void          setInterpreterFrameMethod(Method method);

  /** Constant pool cache */
  public abstract Address  addressOfInterpreterFrameCPCache();
  /** Constant pool cache */
  public ConstantPoolCache getInterpreterFrameCPCache() {
    return (ConstantPoolCache) Metadata.instantiateWrapperFor(addressOfInterpreterFrameCPCache().getAddressAt(0));
  }

  //--------------------------------------------------------------------------------
  // Entry frames:
  //

  public abstract JavaCallWrapper getEntryFrameCallWrapper();

  // FIXME: add
  //  inline intptr_t* entry_frame_argument_at(int offset) const;


  /** Tells whether there is another chunk of Delta stack above */
  public boolean entryFrameIsFirst()            { return (getEntryFrameCallWrapper().getLastJavaSP() == null); }

  //--------------------------------------------------------------------------------
  // Safepoints:
  //

  protected abstract Address addressOfSavedOopResult();
  protected abstract Address addressOfSavedReceiver();

  public OopHandle getSavedOopResult() {
    return addressOfSavedOopResult().getOopHandleAt(0);
  }

  // FIXME: not yet implementable
  //  public void      setSavedOopResult(OopHandle obj);

  public OopHandle getSavedReceiver() {
    return addressOfSavedReceiver().getOopHandleAt(0);
  }

  // FIXME: not yet implementable
  //  public void      setSavedReceiver(OopHandle obj);

  //--------------------------------------------------------------------------------
  // Oop traversals:
  //

  public void oopsInterpretedArgumentsDo(Symbol signature, boolean isStatic, AddressVisitor f) {
    ArgumentOopFinder finder = new ArgumentOopFinder(signature, isStatic, this, f);
    finder.oopsDo();
  }

  /** Conversion from an VMReg::Name to physical stack location */
  public Address oopMapRegToLocation(VMReg reg, RegisterMap regMap) {
    VMReg stack0 = VM.getVM().getVMRegImplInfo().getStack0();
    if (reg.lessThan(stack0)) {
      // If it is passed in a register, it got spilled in the stub frame.
      return regMap.getLocation(reg);
    } else {
      long spOffset = VM.getVM().getAddressSize() * reg.minus(stack0);
      return getUnextendedSP().addOffsetTo(spOffset);
    }
  }

  public void oopsDo(AddressVisitor oopVisitor, RegisterMap map) {
    if (isInterpretedFrame()) {
      oopsInterpretedDo(oopVisitor, map);
    } else if (isEntryFrame()) {
      oopsEntryDo(oopVisitor, map);
    } else if (VM.getVM().getCodeCache().contains(getPC())) {
      oopsCodeBlobDo(oopVisitor, map);
    } else {
      Assert.that(false, "should not reach here");
    }
  }

  //--------------------------------------------------------------------------------
  // Printing code
  //

  public void printValue() {
    printValueOn(System.out);
  }

  public void printValueOn(PrintStream tty) {
    //    FIXME;
  }

  public void print() {
    printOn(System.out);
  }

  public void printOn(PrintStream tty) {
    //    FIXME;
  }

  public void interpreterFramePrintOn(PrintStream tty) {
    //    FIXME;
  }

  //--------------------------------------------------------------------------------
  // Get/set typed locals from a frame.
  // Respects platform dependent word-ordering.
  //
  // FIXME: avoiding implementing this for now if possible
  //
  // Currently these work only for interpreted frames.
  // Todo: make these work for compiled frames.
  //
  //  oop     get_local_object(jint slot) const;
  //  jint    get_local_int   (jint slot) const;
  //  jlong   get_local_long  (jint slot) const;
  //  jfloat  get_local_float (jint slot) const;
  //  jdouble get_local_double(jint slot) const;
  //
  //  void set_local_object(jint slot, oop     obj);
  //  void set_local_int   (jint slot, jint    i);
  //  void set_local_long  (jint slot, jlong   l);
  //  void set_local_float (jint slot, jfloat  f);
  //  void set_local_double(jint slot, jdouble d);

  // FIXME: add safepoint code, oops_do, etc.
  // FIXME: NOT FINISHED





  //--------------------------------------------------------------------------------
  // Internals only below this point
  //

  //   /** Helper method for better factored code in frame::sender */
  //   private frame sender_for_entry_frame(RegisterMap* map)        { throw new RuntimeException("not yet implemented"); }
  //   private frame sender_for_interpreter_frame(RegisterMap* map)  { throw new RuntimeException("not yet implemented"); }

  //
  // Oop iteration (FIXME: NOT FINISHED)
  //


  private static class InterpVisitor implements OopMapVisitor {
    private AddressVisitor addressVisitor;

    public InterpVisitor(AddressVisitor oopVisitor) {
      setAddressVisitor(oopVisitor);
    }

    public void setAddressVisitor(AddressVisitor addressVisitor) {
      this.addressVisitor = addressVisitor;
    }

    public void visitOopLocation(Address oopAddr) {
      addressVisitor.visitAddress(oopAddr);
    }

    public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {
      if (VM.getVM().isClientCompiler()) {
        Assert.that(false, "should not reach here");
      } else if (VM.getVM().isServerCompiler() &&
                 VM.getVM().useDerivedPointerTable()) {
        Assert.that(false, "FIXME: add derived pointer table");
      }
    }

    public void visitValueLocation(Address valueAddr) {
    }

    public void visitNarrowOopLocation(Address compOopAddr) {
      addressVisitor.visitCompOopAddress(compOopAddr);
    }
  }

  private void oopsInterpretedDo(AddressVisitor oopVisitor, RegisterMap map) {
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(map != null, "map must be set");
    }
    Method m = getInterpreterFrameMethod();
    int bci  = getInterpreterFrameBCI();

    // FIXME: Seeing this sometimes
    if (VM.getVM().isDebugging()) {
      if (bci < 0 || bci >= m.getCodeSize()) return;
    }

    if (Assert.ASSERTS_ENABLED) {
      //      Assert.that(VM.getVM().getUniverse().heap().isIn(m), "method must be valid oop");
      Assert.that((m.isNative() && (bci == 0)) || ((bci >= 0) && (bci < m.getCodeSize())), "invalid bci value");
    }

    // Handle the monitor elements in the activation
    // FIXME: monitor information not yet exposed
    //    for (
    //      BasicObjectLock* current = interpreter_frame_monitor_end();
    //      current < interpreter_frame_monitor_begin();
    //      current = next_monitor_in_interpreter_frame(current)
    //    ) {
    //#ifdef ASSERT
    //      interpreter_frame_verify_monitor(current);
    //#endif
    //      current->oops_do(f);
    //    }

    // process fixed part
    // FIXME: these are no longer oops, so should anything be visitied?
    // oopVisitor.visitAddress(addressOfInterpreterFrameMethod());
    // oopVisitor.visitAddress(addressOfInterpreterFrameCPCache());

    // FIXME: expose interpreterFrameMirrorOffset
    //    if (m.isNative() && m.isStatic()) {
    //      oopVisitor.visitAddress(getFP().addOffsetTo(interpreterFrameMirrorOffset));
    //    }

    int maxLocals = (int) (m.isNative() ? m.getSizeOfParameters() : m.getMaxLocals());
    InterpreterFrameClosure blk = new InterpreterFrameClosure(this, maxLocals, (int) m.getMaxStack(), oopVisitor);

    // process locals & expression stack
    OopMapCacheEntry mask = m.getMaskFor(bci);
    mask.iterateOop(blk);

    // process a callee's arguments if we are at a call site
    // (i.e., if we are at an invoke bytecode)
    if (map.getIncludeArgumentOops() && !m.isNative()) {
      BytecodeInvoke call = BytecodeInvoke.atCheck(m, bci);
      if (call != null && getInterpreterFrameExpressionStackSize() > 0) {
        // we are at a call site & the expression stack is not empty
        // => process callee's arguments
        //
        // Note: The expression stack can be empty if an exception
        //       occured during method resolution/execution. In all
        //       cases we empty the expression stack completely be-
        //       fore handling the exception (the exception handling
        //       code in the interpreter calls a blocking runtime
        //       routine which can cause this code to be executed).
        //       (was bug gri 7/27/98)
        oopsInterpretedArgumentsDo(call.signature(), call.isInvokestatic(), oopVisitor);
      }
    }
  }

  private void oopsEntryDo      (AddressVisitor oopVisitor, RegisterMap regMap) {}
  private void oopsCodeBlobDo   (AddressVisitor oopVisitor, RegisterMap regMap) {
    CodeBlob cb = VM.getVM().getCodeCache().findBlob(getPC());
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(cb != null, "sanity check");
    }
    if (cb.getOopMaps() != null) {
      OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging());

      // FIXME: add in traversal of argument oops (skipping this for
      // now until we have the other stuff tested)

    }

    // FIXME: would add this in in non-debugging system

    // If we see an activation belonging to a non_entrant nmethod, we mark it.
    //    if (cb->is_nmethod() && ((nmethod *)cb)->is_not_entrant()) {
    //      ((nmethod*)cb)->mark_as_seen_on_stack();
    //    }
  }

  // FIXME: implement the above routines, plus add
  // oops_interpreted_arguments_do and oops_compiled_arguments_do
}

//
// Only used internally, to iterate through oop slots in interpreted
// frames
//
class InterpreterFrameClosure implements OffsetClosure {
  // Used for debugging this code
  private static final boolean DEBUG = false;

  private Frame fr;
  private AddressVisitor f;
  private int maxLocals;
  private int maxStack;

  InterpreterFrameClosure(Frame fr, int maxLocals, int maxStack, AddressVisitor f) {
    this.fr = fr;
    this.maxLocals = maxLocals;
    this.maxStack = maxStack;
    this.f = f;
  }

  public void offsetDo(int offset) {
    if (DEBUG) {
      System.err.println("Visiting offset " + offset + ", maxLocals = " + maxLocals +
                         " for frame " + fr + ", method " +
                         fr.getInterpreterFrameMethod().getMethodHolder().getName().asString() +
                         fr.getInterpreterFrameMethod().getName().asString());
    }
    Address addr;
    if (offset < maxLocals) {
      addr = fr.addressOfInterpreterFrameLocal(offset);
      if (Assert.ASSERTS_ENABLED) {
        Assert.that(AddressOps.gte(addr, fr.getSP()), "must be inside the frame");
      }
      if (DEBUG) {
        System.err.println("  Visiting local at addr " + addr);
      }
      f.visitAddress(addr);
    } else {
      addr = fr.addressOfInterpreterFrameExpressionStackSlot(offset - maxLocals);
      if (DEBUG) {
        System.err.println("  Address of expression stack slot: " + addr + ", TOS = " +
                           fr.addressOfInterpreterFrameTOS());
      }
      // In case of exceptions, the expression stack is invalid and the esp will be reset to express
      // this condition. Therefore, we call f only if addr is 'inside' the stack (i.e., addr >= esp for Intel).
      boolean inStack;
      if (fr.getInterpreterFrameExpressionStackDirection() > 0) {
        inStack = AddressOps.lte(addr, fr.addressOfInterpreterFrameTOS());
      } else {
        inStack = AddressOps.gte(addr, fr.addressOfInterpreterFrameTOS());
      }
      if (inStack) {
        if (DEBUG) {
          System.err.println("  In stack; visiting location.");
        }
        f.visitAddress(addr);
      } else if (DEBUG) {
        System.err.println("  *** WARNING: Address is out of bounds");
      }
    }
  }
}

// Only used internally, to find arguments in interpreted frames
class ArgumentOopFinder extends SignatureInfo {
  private AddressVisitor f;
  private int            offset;
  private boolean        isStatic;
  private Frame          fr;

  protected void set(int size, int type) {
    offset -= size;
    if (type == BasicType.getTObject() || type == BasicType.getTArray()) oopOffsetDo();
  }

  private void oopOffsetDo() {
    f.visitAddress(fr.addressOfInterpreterFrameTOSAt(offset));
  }

  public ArgumentOopFinder(Symbol signature, boolean isStatic, Frame fr, AddressVisitor f) {
    super(signature);

    // compute size of arguments
    int argsSize = new ArgumentSizeComputer(signature).size() + (isStatic ? 0 : 1);
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(!fr.isInterpretedFrame() ||
                  argsSize <= fr.getInterpreterFrameExpressionStackSize(), "args cannot be on stack anymore");
    }
    // initialize ArgumentOopFinder
    this.f        = f;
    this.fr       = fr;
    this.offset   = argsSize;
    this.isStatic = isStatic;
  }

  public void oopsDo() {
    if (!isStatic) {
      --offset;
      oopOffsetDo();
    }
    iterateParameters();
  }
}
