View Javadoc
1   /*
2    * Copyright (c) 2000, 2006, 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 sun.jvm.hotspot.code.*;
29  import sun.jvm.hotspot.utilities.*;
30  
31  public class VFrame {
32    protected Frame       fr;
33    protected RegisterMap regMap;
34    protected JavaThread  thread;
35  
36    protected VFrame(Frame f, RegisterMap regMap, JavaThread thread) {
37      this.regMap = (RegisterMap) regMap.clone();
38  
39      if (f != null) {
40        // the frame is null if we create a deoptimizedVFrame from a vframeArray
41        fr = (Frame) f.clone();
42      }
43  
44      this.thread = thread;
45    }
46  
47    /** Factory method for creating vframes. The "unsafe" flag turns off
48        an assertion which the runtime system uses to ensure integrity,
49        but which must not be applied in the debugging situation. The
50        "mayBeImprecise" flag should be set to true for the case of the
51        top frame in the debugging system (obtained via
52        JavaThread.getCurrentFrameGuess()). */
53    public static VFrame newVFrame(Frame f, RegisterMap regMap, JavaThread thread, boolean unsafe, boolean mayBeImprecise) {
54      if (f.isInterpretedFrame()) {
55        return new InterpretedVFrame(f, regMap, thread);
56      }
57  
58      if (!VM.getVM().isCore()) {
59        CodeBlob cb;
60        if (unsafe) {
61          cb = VM.getVM().getCodeCache().findBlobUnsafe(f.getPC());
62        } else {
63          cb = VM.getVM().getCodeCache().findBlob(f.getPC());
64        }
65  
66        if (cb != null) {
67          if (cb.isNMethod()) {
68            NMethod nm = (NMethod) cb;
69            // Compiled method (native stub or Java code)
70            ScopeDesc scope = null;
71            // FIXME: should revisit the check of isDebugging(); should not be necessary
72            if (mayBeImprecise || VM.getVM().isDebugging()) {
73              scope = nm.getScopeDescNearDbg(f.getPC());
74            } else {
75              scope = nm.getScopeDescAt(f.getPC());
76            }
77            return new CompiledVFrame(f, regMap, thread, scope, mayBeImprecise);
78          }
79  
80          if (f.isRuntimeFrame()) {
81            // This is a conversion frame. Skip this frame and try again.
82            RegisterMap tempMap = regMap.copy();
83            Frame s = f.sender(tempMap);
84            return newVFrame(s, tempMap, thread, unsafe, false);
85          }
86        }
87      }
88  
89      // External frame
90      return new ExternalVFrame(f, regMap, thread, mayBeImprecise);
91    }
92  
93    /** Factory method for creating vframes. This is equivalent to
94        calling the above version with the "unsafe" and "imprecise"
95        flags set to false. */
96    public static VFrame newVFrame(Frame f, RegisterMap regMap, JavaThread thread) {
97      return newVFrame(f, regMap, thread, false, false);
98    }
99  
100   /** Accessors */
101   public Frame       getFrame()       { return fr;     }
102   public RegisterMap getRegisterMap() { return regMap; }
103   public JavaThread  getThread()      { return thread; }
104 
105   /** Returns the sender vframe */
106   public VFrame sender() {
107     if (Assert.ASSERTS_ENABLED) {
108       Assert.that(isTop(), "just checking");
109     }
110     return sender(false);
111   }
112 
113   /** Returns the sender vframe; takes argument for debugging situation */
114   public VFrame sender(boolean mayBeImprecise) {
115     RegisterMap tempMap = (RegisterMap) getRegisterMap().clone();
116     if (fr.isFirstFrame()) {
117       return null;
118     }
119     Frame s = fr.realSender(tempMap);
120     // ia64 in 1.4.1 only has java frames and no entryFrame
121     // so "s" can be null here for the first frame.
122     if (s == null) {
123       Assert.that(VM.getVM().getCPU().equals("ia64"), "Only ia64 should have null here");
124       return null;
125     }
126     if (s.isFirstFrame()) {
127       return null;
128     }
129     return VFrame.newVFrame(s, tempMap, getThread(), VM.getVM().isDebugging(), mayBeImprecise);
130   }
131 
132   /** Returns the next javaVFrame on the stack (skipping all other
133       kinds of frames).  In the debugging situation, allows the
134       "imprecise" flag to propagate up the stack. We must not assert
135       that a ScopeDesc exists for the topmost compiled frame on the
136       stack. */
137   public JavaVFrame javaSender() {
138     boolean imprecise = false;
139 
140     // Hack for debugging
141     if (VM.getVM().isDebugging()) {
142       if (!isJavaFrame()) {
143         imprecise = mayBeImpreciseDbg();
144       }
145     }
146     VFrame f = sender(imprecise);
147     while (f != null) {
148       if (f.isJavaFrame()) {
149         return (JavaVFrame) f;
150       }
151       f = f.sender(imprecise);
152     }
153     return null;
154   }
155 
156   /** Answers if the this is the top vframe in the frame, i.e., if the
157       sender vframe is in the caller frame */
158   public boolean isTop() {
159     return true;
160   }
161 
162   /** Returns top vframe within same frame (see isTop()) */
163   public VFrame top() {
164     VFrame vf = this;
165     while (!vf.isTop()) {
166       vf = vf.sender();
167     }
168     return vf;
169   }
170 
171   /** Type testing operations */
172   public boolean isEntryFrame()       { return false; }
173   public boolean isJavaFrame()        { return false; }
174   public boolean isInterpretedFrame() { return false; }
175   public boolean isCompiledFrame()    { return false; }
176   public boolean isDeoptimized()      { return false; }
177 
178   /** An indication of whether this VFrame is "precise" or a best
179       guess. This is used in the debugging system to handle the top
180       frame on the stack, which, since the system will in general not
181       be at a safepoint, has to make some guesses about exactly where
182       in the execution it is. Any debugger should indicate to the user
183       that the information for this frame may not be 100% correct.
184       FIXME: may need to move this up into VFrame instead of keeping
185       it in CompiledVFrame. */
186   public boolean mayBeImpreciseDbg()  { return false; }
187 
188   /** Printing operations */
189   public void print() {
190     printOn(System.out);
191   }
192 
193   public void printOn(PrintStream tty) {
194     if (VM.getVM().wizardMode()) {
195       fr.printValueOn(tty);
196     }
197   }
198 
199   public void printValue() {
200     printValueOn(System.out);
201   }
202 
203   public void printValueOn(PrintStream tty) {
204     printOn(tty);
205   }
206 }