blob: ea1ec197c6e64ffe2c080f4277eb8d93a292e99e [file] [log] [blame]
/*
* 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);
}
}