/*
 * Copyright (c) 2000, 2006, 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 sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.utilities.*;

public class VFrame {
  protected Frame       fr;
  protected RegisterMap regMap;
  protected JavaThread  thread;

  protected VFrame(Frame f, RegisterMap regMap, JavaThread thread) {
    this.regMap = (RegisterMap) regMap.clone();

    if (f != null) {
      // the frame is null if we create a deoptimizedVFrame from a vframeArray
      fr = (Frame) f.clone();
    }

    this.thread = thread;
  }

  /** Factory method for creating vframes. The "unsafe" flag turns off
      an assertion which the runtime system uses to ensure integrity,
      but which must not be applied in the debugging situation. The
      "mayBeImprecise" flag should be set to true for the case of the
      top frame in the debugging system (obtained via
      JavaThread.getCurrentFrameGuess()). */
  public static VFrame newVFrame(Frame f, RegisterMap regMap, JavaThread thread, boolean unsafe, boolean mayBeImprecise) {
    if (f.isInterpretedFrame()) {
      return new InterpretedVFrame(f, regMap, thread);
    }

    if (!VM.getVM().isCore()) {
      CodeBlob cb;
      if (unsafe) {
        cb = VM.getVM().getCodeCache().findBlobUnsafe(f.getPC());
      } else {
        cb = VM.getVM().getCodeCache().findBlob(f.getPC());
      }

      if (cb != null) {
        if (cb.isNMethod()) {
          NMethod nm = (NMethod) cb;
          // Compiled method (native stub or Java code)
          ScopeDesc scope = null;
          // FIXME: should revisit the check of isDebugging(); should not be necessary
          if (mayBeImprecise || VM.getVM().isDebugging()) {
            scope = nm.getScopeDescNearDbg(f.getPC());
          } else {
            scope = nm.getScopeDescAt(f.getPC());
          }
          return new CompiledVFrame(f, regMap, thread, scope, mayBeImprecise);
        }

        if (f.isRuntimeFrame()) {
          // This is a conversion frame. Skip this frame and try again.
          RegisterMap tempMap = regMap.copy();
          Frame s = f.sender(tempMap);
          return newVFrame(s, tempMap, thread, unsafe, false);
        }
      }
    }

    // External frame
    return new ExternalVFrame(f, regMap, thread, mayBeImprecise);
  }

  /** Factory method for creating vframes. This is equivalent to
      calling the above version with the "unsafe" and "imprecise"
      flags set to false. */
  public static VFrame newVFrame(Frame f, RegisterMap regMap, JavaThread thread) {
    return newVFrame(f, regMap, thread, false, false);
  }

  /** Accessors */
  public Frame       getFrame()       { return fr;     }
  public RegisterMap getRegisterMap() { return regMap; }
  public JavaThread  getThread()      { return thread; }

  /** Returns the sender vframe */
  public VFrame sender() {
    if (Assert.ASSERTS_ENABLED) {
      Assert.that(isTop(), "just checking");
    }
    return sender(false);
  }

  /** Returns the sender vframe; takes argument for debugging situation */
  public VFrame sender(boolean mayBeImprecise) {
    RegisterMap tempMap = (RegisterMap) getRegisterMap().clone();
    if (fr.isFirstFrame()) {
      return null;
    }
    Frame s = fr.realSender(tempMap);
    // ia64 in 1.4.1 only has java frames and no entryFrame
    // so "s" can be null here for the first frame.
    if (s == null) {
      Assert.that(VM.getVM().getCPU().equals("ia64"), "Only ia64 should have null here");
      return null;
    }
    if (s.isFirstFrame()) {
      return null;
    }
    return VFrame.newVFrame(s, tempMap, getThread(), VM.getVM().isDebugging(), mayBeImprecise);
  }

  /** Returns the next javaVFrame on the stack (skipping all other
      kinds of frames).  In the debugging situation, allows the
      "imprecise" flag to propagate up the stack. We must not assert
      that a ScopeDesc exists for the topmost compiled frame on the
      stack. */
  public JavaVFrame javaSender() {
    boolean imprecise = false;

    // Hack for debugging
    if (VM.getVM().isDebugging()) {
      if (!isJavaFrame()) {
        imprecise = mayBeImpreciseDbg();
      }
    }
    VFrame f = sender(imprecise);
    while (f != null) {
      if (f.isJavaFrame()) {
        return (JavaVFrame) f;
      }
      f = f.sender(imprecise);
    }
    return null;
  }

  /** Answers if the this is the top vframe in the frame, i.e., if the
      sender vframe is in the caller frame */
  public boolean isTop() {
    return true;
  }

  /** Returns top vframe within same frame (see isTop()) */
  public VFrame top() {
    VFrame vf = this;
    while (!vf.isTop()) {
      vf = vf.sender();
    }
    return vf;
  }

  /** Type testing operations */
  public boolean isEntryFrame()       { return false; }
  public boolean isJavaFrame()        { return false; }
  public boolean isInterpretedFrame() { return false; }
  public boolean isCompiledFrame()    { return false; }
  public boolean isDeoptimized()      { return false; }

  /** An indication of whether this VFrame is "precise" or a best
      guess. This is used in the debugging system to handle the top
      frame on the stack, which, since the system will in general not
      be at a safepoint, has to make some guesses about exactly where
      in the execution it is. Any debugger should indicate to the user
      that the information for this frame may not be 100% correct.
      FIXME: may need to move this up into VFrame instead of keeping
      it in CompiledVFrame. */
  public boolean mayBeImpreciseDbg()  { return false; }

  /** Printing operations */
  public void print() {
    printOn(System.out);
  }

  public void printOn(PrintStream tty) {
    if (VM.getVM().wizardMode()) {
      fr.printValueOn(tty);
    }
  }

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

  public void printValueOn(PrintStream tty) {
    printOn(tty);
  }
}
