annotate agent/src/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java @ 1552:c18cbe5936b8

6941466: Oracle rebranding changes for Hotspot repositories Summary: Change all the Sun copyrights to Oracle copyright Reviewed-by: ohair
author trims
date Thu, 27 May 2010 19:08:38 -0700
parents a61af66fc99e
children 7588156f5cf9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
2 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 package sun.jvm.hotspot.runtime.amd64;
a61af66fc99e Initial load
duke
parents:
diff changeset
26
a61af66fc99e Initial load
duke
parents:
diff changeset
27 import sun.jvm.hotspot.debugger.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
28 import sun.jvm.hotspot.debugger.amd64.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
29 import sun.jvm.hotspot.code.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
30 import sun.jvm.hotspot.interpreter.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
31 import sun.jvm.hotspot.runtime.*;
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33 /** <P> Should be able to be used on all amd64 platforms we support
a61af66fc99e Initial load
duke
parents:
diff changeset
34 (Linux/amd64) to implement JavaThread's
a61af66fc99e Initial load
duke
parents:
diff changeset
35 "currentFrameGuess()" functionality. Input is an AMD64ThreadContext;
a61af66fc99e Initial load
duke
parents:
diff changeset
36 output is SP, FP, and PC for an AMD64Frame. Instantiation of the
a61af66fc99e Initial load
duke
parents:
diff changeset
37 AMD64Frame is left to the caller, since we may need to subclass
a61af66fc99e Initial load
duke
parents:
diff changeset
38 AMD64Frame to support signal handler frames on Unix platforms. </P>
a61af66fc99e Initial load
duke
parents:
diff changeset
39
a61af66fc99e Initial load
duke
parents:
diff changeset
40 <P> Algorithm is to walk up the stack within a given range (say,
a61af66fc99e Initial load
duke
parents:
diff changeset
41 512K at most) looking for a plausible PC and SP for a Java frame,
a61af66fc99e Initial load
duke
parents:
diff changeset
42 also considering those coming in from the context. If we find a PC
a61af66fc99e Initial load
duke
parents:
diff changeset
43 that belongs to the VM (i.e., in generated code like the
a61af66fc99e Initial load
duke
parents:
diff changeset
44 interpreter or CodeCache) then we try to find an associated EBP.
a61af66fc99e Initial load
duke
parents:
diff changeset
45 We repeat this until we either find a complete frame or run out of
a61af66fc99e Initial load
duke
parents:
diff changeset
46 stack to look at. </P> */
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 public class AMD64CurrentFrameGuess {
a61af66fc99e Initial load
duke
parents:
diff changeset
49 private AMD64ThreadContext context;
a61af66fc99e Initial load
duke
parents:
diff changeset
50 private JavaThread thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
51 private Address spFound;
a61af66fc99e Initial load
duke
parents:
diff changeset
52 private Address fpFound;
a61af66fc99e Initial load
duke
parents:
diff changeset
53 private Address pcFound;
a61af66fc99e Initial load
duke
parents:
diff changeset
54
a61af66fc99e Initial load
duke
parents:
diff changeset
55 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.amd64.AMD64Frame.DEBUG")
a61af66fc99e Initial load
duke
parents:
diff changeset
56 != null;
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 public AMD64CurrentFrameGuess(AMD64ThreadContext context,
a61af66fc99e Initial load
duke
parents:
diff changeset
59 JavaThread thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
60 this.context = context;
a61af66fc99e Initial load
duke
parents:
diff changeset
61 this.thread = thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
62 }
a61af66fc99e Initial load
duke
parents:
diff changeset
63
a61af66fc99e Initial load
duke
parents:
diff changeset
64 /** Returns false if not able to find a frame within a reasonable range. */
a61af66fc99e Initial load
duke
parents:
diff changeset
65 public boolean run(long regionInBytesToSearch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 Address sp = context.getRegisterAsAddress(AMD64ThreadContext.RSP);
a61af66fc99e Initial load
duke
parents:
diff changeset
67 Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP);
a61af66fc99e Initial load
duke
parents:
diff changeset
68 Address fp = context.getRegisterAsAddress(AMD64ThreadContext.RBP);
a61af66fc99e Initial load
duke
parents:
diff changeset
69 if (sp == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
70 // Bail out if no last java frame either
a61af66fc99e Initial load
duke
parents:
diff changeset
71 if (thread.getLastJavaSP() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
72 setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
a61af66fc99e Initial load
duke
parents:
diff changeset
73 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
76 }
a61af66fc99e Initial load
duke
parents:
diff changeset
77 Address end = sp.addOffsetTo(regionInBytesToSearch);
a61af66fc99e Initial load
duke
parents:
diff changeset
78 VM vm = VM.getVM();
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 setValues(null, null, null); // Assume we're not going to find anything
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 if (vm.isJavaPCDbg(pc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
83 if (vm.isClientCompiler()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // If the topmost frame is a Java frame, we are (pretty much)
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // guaranteed to have a viable EBP. We should be more robust
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // than this (we have the potential for losing entire threads'
a61af66fc99e Initial load
duke
parents:
diff changeset
87 // stack traces) but need to see how much work we really have
a61af66fc99e Initial load
duke
parents:
diff changeset
88 // to do here. Searching the stack for an (SP, FP) pair is
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // hard since it's easy to misinterpret inter-frame stack
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // pointers as base-of-frame pointers; we also don't know the
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // sizes of C1 frames (not registered in the nmethod) so can't
a61af66fc99e Initial load
duke
parents:
diff changeset
92 // derive them from ESP.
a61af66fc99e Initial load
duke
parents:
diff changeset
93
a61af66fc99e Initial load
duke
parents:
diff changeset
94 setValues(sp, fp, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
95 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
96 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
97 if (vm.getInterpreter().contains(pc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
98 if (DEBUG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
99 System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " +
a61af66fc99e Initial load
duke
parents:
diff changeset
100 sp + ", fp = " + fp + ", pc = " + pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
102 setValues(sp, fp, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
103 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
104 }
a61af66fc99e Initial load
duke
parents:
diff changeset
105
a61af66fc99e Initial load
duke
parents:
diff changeset
106 // For the server compiler, EBP is not guaranteed to be valid
a61af66fc99e Initial load
duke
parents:
diff changeset
107 // for compiled code. In addition, an earlier attempt at a
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // non-searching algorithm (see below) failed because the
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // stack pointer from the thread context was pointing
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // (considerably) beyond the ostensible end of the stack, into
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // garbage; walking from the topmost frame back caused a crash.
a61af66fc99e Initial load
duke
parents:
diff changeset
112 //
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // This algorithm takes the current PC as a given and tries to
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // find the correct corresponding SP by walking up the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // and repeatedly performing stackwalks (very inefficient).
a61af66fc99e Initial load
duke
parents:
diff changeset
116 //
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // FIXME: there is something wrong with stackwalking across
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // adapter frames...this is likely to be the root cause of the
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // failure with the simpler algorithm below.
a61af66fc99e Initial load
duke
parents:
diff changeset
120
a61af66fc99e Initial load
duke
parents:
diff changeset
121 for (long offset = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
122 offset < regionInBytesToSearch;
a61af66fc99e Initial load
duke
parents:
diff changeset
123 offset += vm.getAddressSize()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
124 try {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 Address curSP = sp.addOffsetTo(offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
126 Frame frame = new AMD64Frame(curSP, null, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
127 RegisterMap map = thread.newRegisterMap(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
128 while (frame != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
129 if (frame.isEntryFrame() && frame.entryFrameIsFirst()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // We were able to traverse all the way to the
a61af66fc99e Initial load
duke
parents:
diff changeset
131 // bottommost Java frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
132 // This sp looks good. Keep it.
a61af66fc99e Initial load
duke
parents:
diff changeset
133 if (DEBUG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
134 System.out.println("CurrentFrameGuess: Choosing sp = " + curSP + ", pc = " + pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
136 setValues(curSP, null, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
137 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
139 frame = frame.sender(map);
a61af66fc99e Initial load
duke
parents:
diff changeset
140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
141 } catch (Exception e) {
a61af66fc99e Initial load
duke
parents:
diff changeset
142 if (DEBUG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
143 System.out.println("CurrentFrameGuess: Exception " + e + " at offset " + offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
144 }
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // Bad SP. Try another.
a61af66fc99e Initial load
duke
parents:
diff changeset
146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
148
a61af66fc99e Initial load
duke
parents:
diff changeset
149 // Were not able to find a plausible SP to go with this PC.
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // Bail out.
a61af66fc99e Initial load
duke
parents:
diff changeset
151 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
152
a61af66fc99e Initial load
duke
parents:
diff changeset
153 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
154 // Original algorithm which does not work because SP was
a61af66fc99e Initial load
duke
parents:
diff changeset
155 // pointing beyond where it should have:
a61af66fc99e Initial load
duke
parents:
diff changeset
156
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // For the server compiler, EBP is not guaranteed to be valid
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // for compiled code. We see whether the PC is in the
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // interpreter and take care of that, otherwise we run code
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // (unfortunately) duplicated from AMD64Frame.senderForCompiledFrame.
a61af66fc99e Initial load
duke
parents:
diff changeset
161
a61af66fc99e Initial load
duke
parents:
diff changeset
162 CodeCache cc = vm.getCodeCache();
a61af66fc99e Initial load
duke
parents:
diff changeset
163 if (cc.contains(pc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
164 CodeBlob cb = cc.findBlob(pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
165
a61af66fc99e Initial load
duke
parents:
diff changeset
166 // See if we can derive a frame pointer from SP and PC
a61af66fc99e Initial load
duke
parents:
diff changeset
167 // NOTE: This is the code duplicated from AMD64Frame
a61af66fc99e Initial load
duke
parents:
diff changeset
168 Address saved_fp = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
169 int llink_offset = cb.getLinkOffset();
a61af66fc99e Initial load
duke
parents:
diff changeset
170 if (llink_offset >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
171 // Restore base-pointer, since next frame might be an interpreter frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
172 Address fp_addr = sp.addOffsetTo(VM.getVM().getAddressSize() * llink_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
173 saved_fp = fp_addr.getAddressAt(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
174 }
a61af66fc99e Initial load
duke
parents:
diff changeset
175
a61af66fc99e Initial load
duke
parents:
diff changeset
176 setValues(sp, saved_fp, pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
177 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
179 */
a61af66fc99e Initial load
duke
parents:
diff changeset
180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
181 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
182 // If the current program counter was not known to us as a Java
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // PC, we currently assume that we are in the run-time system
a61af66fc99e Initial load
duke
parents:
diff changeset
184 // and attempt to look to thread-local storage for saved ESP and
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // EBP. Note that if these are null (because we were, in fact,
a61af66fc99e Initial load
duke
parents:
diff changeset
186 // in Java code, i.e., vtable stubs or similar, and the SA
a61af66fc99e Initial load
duke
parents:
diff changeset
187 // didn't have enough insight into the target VM to understand
a61af66fc99e Initial load
duke
parents:
diff changeset
188 // that) then we are going to lose the entire stack trace for
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // the thread, which is sub-optimal. FIXME.
a61af66fc99e Initial load
duke
parents:
diff changeset
190
a61af66fc99e Initial load
duke
parents:
diff changeset
191 if (DEBUG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
192 System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " +
a61af66fc99e Initial load
duke
parents:
diff changeset
193 thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP());
a61af66fc99e Initial load
duke
parents:
diff changeset
194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
195 if (thread.getLastJavaSP() == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
196 return false; // No known Java frames on stack
a61af66fc99e Initial load
duke
parents:
diff changeset
197 }
a61af66fc99e Initial load
duke
parents:
diff changeset
198 setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null);
a61af66fc99e Initial load
duke
parents:
diff changeset
199 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
202
a61af66fc99e Initial load
duke
parents:
diff changeset
203 public Address getSP() { return spFound; }
a61af66fc99e Initial load
duke
parents:
diff changeset
204 public Address getFP() { return fpFound; }
a61af66fc99e Initial load
duke
parents:
diff changeset
205 /** May be null if getting values from thread-local storage; take
a61af66fc99e Initial load
duke
parents:
diff changeset
206 care to call the correct AMD64Frame constructor to recover this if
a61af66fc99e Initial load
duke
parents:
diff changeset
207 necessary */
a61af66fc99e Initial load
duke
parents:
diff changeset
208 public Address getPC() { return pcFound; }
a61af66fc99e Initial load
duke
parents:
diff changeset
209
a61af66fc99e Initial load
duke
parents:
diff changeset
210 private void setValues(Address sp, Address fp, Address pc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
211 spFound = sp;
a61af66fc99e Initial load
duke
parents:
diff changeset
212 fpFound = fp;
a61af66fc99e Initial load
duke
parents:
diff changeset
213 pcFound = pc;
a61af66fc99e Initial load
duke
parents:
diff changeset
214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
215 }