/* * 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 or a Stub routine. 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); } }