annotate src/share/vm/prims/forte.cpp @ 17:ff5961f4c095

6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long) Reviewed-by: kvn, rasbold
author never
date Wed, 05 Dec 2007 09:01:00 -0800
parents a61af66fc99e
children 93b6525e3b82
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
2 * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
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 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
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 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_forte.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28
a61af66fc99e Initial load
duke
parents:
diff changeset
29 //-------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
30
a61af66fc99e Initial load
duke
parents:
diff changeset
31 // Native interfaces for use by Forte tools.
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33
a61af66fc99e Initial load
duke
parents:
diff changeset
34 #ifndef IA64
a61af66fc99e Initial load
duke
parents:
diff changeset
35
a61af66fc99e Initial load
duke
parents:
diff changeset
36 class vframeStreamForte : public vframeStreamCommon {
a61af66fc99e Initial load
duke
parents:
diff changeset
37 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // constructor that starts with sender of frame fr (top_frame)
a61af66fc99e Initial load
duke
parents:
diff changeset
39 vframeStreamForte(JavaThread *jt, frame fr, bool stop_at_java_call_stub);
a61af66fc99e Initial load
duke
parents:
diff changeset
40 void forte_next();
a61af66fc99e Initial load
duke
parents:
diff changeset
41 };
a61af66fc99e Initial load
duke
parents:
diff changeset
42
a61af66fc99e Initial load
duke
parents:
diff changeset
43
a61af66fc99e Initial load
duke
parents:
diff changeset
44 static void forte_is_walkable_compiled_frame(frame* fr, RegisterMap* map,
a61af66fc99e Initial load
duke
parents:
diff changeset
45 bool* is_compiled_p, bool* is_walkable_p);
a61af66fc99e Initial load
duke
parents:
diff changeset
46 static bool forte_is_walkable_interpreted_frame(frame* fr,
a61af66fc99e Initial load
duke
parents:
diff changeset
47 methodOop* method_p, int* bci_p);
a61af66fc99e Initial load
duke
parents:
diff changeset
48
a61af66fc99e Initial load
duke
parents:
diff changeset
49
a61af66fc99e Initial load
duke
parents:
diff changeset
50 // A Forte specific version of frame:safe_for_sender().
a61af66fc99e Initial load
duke
parents:
diff changeset
51 static bool forte_safe_for_sender(frame* fr, JavaThread *thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
52 bool ret_value = false; // be pessimistic
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 #ifdef COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
55 #if defined(IA32) || defined(AMD64)
a61af66fc99e Initial load
duke
parents:
diff changeset
56 {
a61af66fc99e Initial load
duke
parents:
diff changeset
57 // This check is the same as the standard safe_for_sender()
a61af66fc99e Initial load
duke
parents:
diff changeset
58 // on IA32 or AMD64 except that NULL FP values are tolerated
a61af66fc99e Initial load
duke
parents:
diff changeset
59 // for C2.
a61af66fc99e Initial load
duke
parents:
diff changeset
60 address sp = (address)fr->sp();
a61af66fc99e Initial load
duke
parents:
diff changeset
61 address fp = (address)fr->fp();
a61af66fc99e Initial load
duke
parents:
diff changeset
62 ret_value = sp != NULL && sp <= thread->stack_base() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
63 sp >= thread->stack_base() - thread->stack_size() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
64 (fp == NULL || (fp <= thread->stack_base() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
65 fp >= thread->stack_base() - thread->stack_size()));
a61af66fc99e Initial load
duke
parents:
diff changeset
66
a61af66fc99e Initial load
duke
parents:
diff changeset
67 // We used to use standard safe_for_sender() when we are supposed
a61af66fc99e Initial load
duke
parents:
diff changeset
68 // to be executing Java code. However, that prevents us from
a61af66fc99e Initial load
duke
parents:
diff changeset
69 // walking some intrinsic stacks so now we have to be more refined.
a61af66fc99e Initial load
duke
parents:
diff changeset
70 // If we passed the above check and we have a NULL frame pointer
a61af66fc99e Initial load
duke
parents:
diff changeset
71 // and we are supposed to be executing Java code, then we have a
a61af66fc99e Initial load
duke
parents:
diff changeset
72 // couple of more checks to make.
a61af66fc99e Initial load
duke
parents:
diff changeset
73 if (ret_value && fp == NULL && (thread->thread_state() == _thread_in_Java
a61af66fc99e Initial load
duke
parents:
diff changeset
74 || thread->thread_state() == _thread_in_Java_trans)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 if (fr->is_interpreted_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
77 // interpreted frames don't really have a NULL frame pointer
a61af66fc99e Initial load
duke
parents:
diff changeset
78 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
79 } else if (CodeCache::find_blob(fr->pc()) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
80 // the NULL frame pointer should be associated with generated code
a61af66fc99e Initial load
duke
parents:
diff changeset
81 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
82 }
a61af66fc99e Initial load
duke
parents:
diff changeset
83 }
a61af66fc99e Initial load
duke
parents:
diff changeset
84 }
a61af66fc99e Initial load
duke
parents:
diff changeset
85
a61af66fc99e Initial load
duke
parents:
diff changeset
86 #else // !(IA32 || AMD64)
a61af66fc99e Initial load
duke
parents:
diff changeset
87 ret_value = fr->safe_for_sender(thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
88 #endif // IA32 || AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
89
a61af66fc99e Initial load
duke
parents:
diff changeset
90 #else // !COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
91 ret_value = fr->safe_for_sender(thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
92 #endif // COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
93
a61af66fc99e Initial load
duke
parents:
diff changeset
94 if (!ret_value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
95 return ret_value; // not safe, nothing more to do
a61af66fc99e Initial load
duke
parents:
diff changeset
96 }
a61af66fc99e Initial load
duke
parents:
diff changeset
97
a61af66fc99e Initial load
duke
parents:
diff changeset
98 address sp1;
a61af66fc99e Initial load
duke
parents:
diff changeset
99
a61af66fc99e Initial load
duke
parents:
diff changeset
100 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
101 // On Solaris SPARC, when a compiler frame has an interpreted callee
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // the _interpreter_sp_adjustment field contains the adjustment to
a61af66fc99e Initial load
duke
parents:
diff changeset
103 // this frame's SP made by that interpreted callee.
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // For AsyncGetCallTrace(), we need to verify that the resulting SP
a61af66fc99e Initial load
duke
parents:
diff changeset
105 // is valid for the specified thread's stack.
a61af66fc99e Initial load
duke
parents:
diff changeset
106 sp1 = (address)fr->sp();
a61af66fc99e Initial load
duke
parents:
diff changeset
107 address sp2 = (address)fr->unextended_sp();
a61af66fc99e Initial load
duke
parents:
diff changeset
108
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // If the second SP is NULL, then the _interpreter_sp_adjustment
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // field simply adjusts this frame's SP to NULL and the frame is
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // not safe. This strange value can be set in the frame constructor
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // when our peek into the interpreted callee's adjusted value for
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // this frame's SP finds a NULL. This can happen when SIGPROF
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // catches us while we are creating the interpreter frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
115 //
a61af66fc99e Initial load
duke
parents:
diff changeset
116 if (sp2 == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
117
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // If the two SPs are different, then _interpreter_sp_adjustment
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // is non-zero and we need to validate the second SP. We invert
a61af66fc99e Initial load
duke
parents:
diff changeset
120 // the range check from frame::safe_for_sender() and bail out
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // if the second SP is not safe.
a61af66fc99e Initial load
duke
parents:
diff changeset
122 (sp1 != sp2 && !(sp2 <= thread->stack_base()
a61af66fc99e Initial load
duke
parents:
diff changeset
123 && sp2 >= (thread->stack_base() - thread->stack_size())))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
124 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
126 #endif // SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
127
a61af66fc99e Initial load
duke
parents:
diff changeset
128 if (fr->is_entry_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
129 // This frame thinks it is an entry frame; we need to validate
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // the JavaCallWrapper pointer.
a61af66fc99e Initial load
duke
parents:
diff changeset
131 // Note: frame::entry_frame_is_first() assumes that the
a61af66fc99e Initial load
duke
parents:
diff changeset
132 // JavaCallWrapper has a non-NULL _anchor field. We don't
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // check that here (yet) since we've never seen a failure
a61af66fc99e Initial load
duke
parents:
diff changeset
134 // due to a NULL _anchor field.
a61af66fc99e Initial load
duke
parents:
diff changeset
135 // Update: Originally this check was done only for SPARC. However,
a61af66fc99e Initial load
duke
parents:
diff changeset
136 // this failure has now been seen on C2 C86. I have no reason to
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // believe that this is not a general issue so I'm enabling the
a61af66fc99e Initial load
duke
parents:
diff changeset
138 // check for all compilers on all supported platforms.
a61af66fc99e Initial load
duke
parents:
diff changeset
139 #ifdef COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
140 #if defined(IA32) || defined(AMD64)
a61af66fc99e Initial load
duke
parents:
diff changeset
141 if (fr->fp() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
142 // C2 X86 allows NULL frame pointers, but if we have one then
a61af66fc99e Initial load
duke
parents:
diff changeset
143 // we cannot call entry_frame_call_wrapper().
a61af66fc99e Initial load
duke
parents:
diff changeset
144 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
146 #endif // IA32 || AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
147 #endif // COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
148
a61af66fc99e Initial load
duke
parents:
diff changeset
149 sp1 = (address)fr->entry_frame_call_wrapper();
a61af66fc99e Initial load
duke
parents:
diff changeset
150 // We invert the range check from frame::safe_for_sender() and
a61af66fc99e Initial load
duke
parents:
diff changeset
151 // bail out if the JavaCallWrapper * is not safe.
a61af66fc99e Initial load
duke
parents:
diff changeset
152 if (!(sp1 <= thread->stack_base()
a61af66fc99e Initial load
duke
parents:
diff changeset
153 && sp1 >= (thread->stack_base() - thread->stack_size()))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
154 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 return ret_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
160
a61af66fc99e Initial load
duke
parents:
diff changeset
161
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // Unknown compiled frames have caused assertion failures on Solaris
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // X86. This code also detects unknown compiled frames on Solaris
a61af66fc99e Initial load
duke
parents:
diff changeset
164 // SPARC, but no assertion failures have been observed. However, I'm
a61af66fc99e Initial load
duke
parents:
diff changeset
165 // paranoid so I'm enabling this code whenever we have a compiler.
a61af66fc99e Initial load
duke
parents:
diff changeset
166 //
a61af66fc99e Initial load
duke
parents:
diff changeset
167 // Returns true if the specified frame is an unknown compiled frame
a61af66fc99e Initial load
duke
parents:
diff changeset
168 // and false otherwise.
a61af66fc99e Initial load
duke
parents:
diff changeset
169 static bool is_unknown_compiled_frame(frame* fr, JavaThread *thread) {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 bool ret_value = false; // be optimistic
a61af66fc99e Initial load
duke
parents:
diff changeset
171
a61af66fc99e Initial load
duke
parents:
diff changeset
172 // This failure mode only occurs when the thread is in state
a61af66fc99e Initial load
duke
parents:
diff changeset
173 // _thread_in_Java so we are okay for this check for any other
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // thread state.
a61af66fc99e Initial load
duke
parents:
diff changeset
175 //
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // Note: _thread_in_Java does not always mean that the thread
a61af66fc99e Initial load
duke
parents:
diff changeset
177 // is executing Java code. AsyncGetCallTrace() has caught
a61af66fc99e Initial load
duke
parents:
diff changeset
178 // threads executing in JRT_LEAF() routines when the state
a61af66fc99e Initial load
duke
parents:
diff changeset
179 // will also be _thread_in_Java.
a61af66fc99e Initial load
duke
parents:
diff changeset
180 if (thread->thread_state() != _thread_in_Java) {
a61af66fc99e Initial load
duke
parents:
diff changeset
181 return ret_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
182 }
a61af66fc99e Initial load
duke
parents:
diff changeset
183
a61af66fc99e Initial load
duke
parents:
diff changeset
184 // This failure mode only occurs with compiled frames so we are
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // okay for this check for both entry and interpreted frames.
a61af66fc99e Initial load
duke
parents:
diff changeset
186 if (fr->is_entry_frame() || fr->is_interpreted_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
187 return ret_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
189
a61af66fc99e Initial load
duke
parents:
diff changeset
190 // This failure mode only occurs when the compiled frame's PC
a61af66fc99e Initial load
duke
parents:
diff changeset
191 // is in the code cache so we are okay for this check if the
a61af66fc99e Initial load
duke
parents:
diff changeset
192 // PC is not in the code cache.
a61af66fc99e Initial load
duke
parents:
diff changeset
193 CodeBlob* cb = CodeCache::find_blob(fr->pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
194 if (cb == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
195 return ret_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
197
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // We have compiled code in the code cache so it is time for
a61af66fc99e Initial load
duke
parents:
diff changeset
199 // the final check: let's see if any frame type is set
a61af66fc99e Initial load
duke
parents:
diff changeset
200 ret_value = !(
a61af66fc99e Initial load
duke
parents:
diff changeset
201 // is_entry_frame() is checked above
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // testers that are a subset of is_entry_frame():
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // is_first_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
204 fr->is_java_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
205 // testers that are a subset of is_java_frame():
a61af66fc99e Initial load
duke
parents:
diff changeset
206 // is_interpreted_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
207 // is_compiled_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
208 || fr->is_native_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
209 || fr->is_runtime_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
210 || fr->is_safepoint_blob_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
211 );
a61af66fc99e Initial load
duke
parents:
diff changeset
212
a61af66fc99e Initial load
duke
parents:
diff changeset
213 // If there is no frame type set, then we have an unknown compiled
a61af66fc99e Initial load
duke
parents:
diff changeset
214 // frame and sender() should not be called on it.
a61af66fc99e Initial load
duke
parents:
diff changeset
215
a61af66fc99e Initial load
duke
parents:
diff changeset
216 return ret_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
218
a61af66fc99e Initial load
duke
parents:
diff changeset
219 #define DebugNonSafepoints_IS_CLEARED \
a61af66fc99e Initial load
duke
parents:
diff changeset
220 (!FLAG_IS_DEFAULT(DebugNonSafepoints) && !DebugNonSafepoints)
a61af66fc99e Initial load
duke
parents:
diff changeset
221
a61af66fc99e Initial load
duke
parents:
diff changeset
222 // if -XX:-DebugNonSafepoints, then top-frame will be skipped
a61af66fc99e Initial load
duke
parents:
diff changeset
223 vframeStreamForte::vframeStreamForte(JavaThread *jt, frame fr,
a61af66fc99e Initial load
duke
parents:
diff changeset
224 bool stop_at_java_call_stub) : vframeStreamCommon(jt) {
a61af66fc99e Initial load
duke
parents:
diff changeset
225 _stop_at_java_call_stub = stop_at_java_call_stub;
a61af66fc99e Initial load
duke
parents:
diff changeset
226
a61af66fc99e Initial load
duke
parents:
diff changeset
227 if (!DebugNonSafepoints_IS_CLEARED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // decode the top frame fully
a61af66fc99e Initial load
duke
parents:
diff changeset
229 // (usual case, if JVMTI is enabled)
a61af66fc99e Initial load
duke
parents:
diff changeset
230 _frame = fr;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // skip top frame, as it may not be at safepoint
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // For AsyncGetCallTrace(), we extracted as much info from the top
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // frame as we could in forte_is_walkable_frame(). We also verified
a61af66fc99e Initial load
duke
parents:
diff changeset
235 // forte_safe_for_sender() so this sender() call is safe.
a61af66fc99e Initial load
duke
parents:
diff changeset
236 _frame = fr.sender(&_reg_map);
a61af66fc99e Initial load
duke
parents:
diff changeset
237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
238
a61af66fc99e Initial load
duke
parents:
diff changeset
239 if (jt->thread_state() == _thread_in_Java && !fr.is_first_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
240 bool sender_check = false; // assume sender is not safe
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 if (forte_safe_for_sender(&_frame, jt)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // If the initial sender frame is safe, then continue on with other
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // checks. The unsafe sender frame has been seen on Solaris X86
a61af66fc99e Initial load
duke
parents:
diff changeset
245 // with both Compiler1 and Compiler2. It has not been seen on
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // Solaris SPARC, but seems like a good sanity check to have
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // anyway.
a61af66fc99e Initial load
duke
parents:
diff changeset
248
a61af66fc99e Initial load
duke
parents:
diff changeset
249 // SIGPROF caught us in Java code and the current frame is not the
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // first frame so we should sanity check the sender frame. It is
a61af66fc99e Initial load
duke
parents:
diff changeset
251 // possible for SIGPROF to catch us in the middle of making a call.
a61af66fc99e Initial load
duke
parents:
diff changeset
252 // When that happens the current frame is actually a combination of
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // the real sender and some of the new call's info. We can't find
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // the real sender with such a current frame and things can get
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // confused.
a61af66fc99e Initial load
duke
parents:
diff changeset
256 //
a61af66fc99e Initial load
duke
parents:
diff changeset
257 // This sanity check has caught problems with the sender frame on
a61af66fc99e Initial load
duke
parents:
diff changeset
258 // Solaris SPARC. So far Solaris X86 has not had a failure here.
a61af66fc99e Initial load
duke
parents:
diff changeset
259 sender_check = _frame.is_entry_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // testers that are a subset of is_entry_frame():
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // is_first_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
262 || _frame.is_java_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // testers that are a subset of is_java_frame():
a61af66fc99e Initial load
duke
parents:
diff changeset
264 // is_interpreted_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
265 // is_compiled_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
266 || _frame.is_native_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
267 || _frame.is_runtime_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
268 || _frame.is_safepoint_blob_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
269 ;
a61af66fc99e Initial load
duke
parents:
diff changeset
270
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // We need an additional sanity check on an initial interpreted
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // sender frame. This interpreted frame needs to be both walkable
a61af66fc99e Initial load
duke
parents:
diff changeset
273 // and have a valid BCI. This is yet another variant of SIGPROF
a61af66fc99e Initial load
duke
parents:
diff changeset
274 // catching us in the middle of making a call.
a61af66fc99e Initial load
duke
parents:
diff changeset
275 if (sender_check && _frame.is_interpreted_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
276 methodOop method = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
277 int bci = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
278
a61af66fc99e Initial load
duke
parents:
diff changeset
279 if (!forte_is_walkable_interpreted_frame(&_frame, &method, &bci)
a61af66fc99e Initial load
duke
parents:
diff changeset
280 || bci == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
281 sender_check = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
283 }
a61af66fc99e Initial load
duke
parents:
diff changeset
284
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // We need an additional sanity check on an initial compiled
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // sender frame. This compiled frame also needs to be walkable.
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // This is yet another variant of SIGPROF catching us in the
a61af66fc99e Initial load
duke
parents:
diff changeset
288 // middle of making a call.
a61af66fc99e Initial load
duke
parents:
diff changeset
289 if (sender_check && !_frame.is_interpreted_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
290 bool is_compiled, is_walkable;
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 forte_is_walkable_compiled_frame(&_frame, &_reg_map,
a61af66fc99e Initial load
duke
parents:
diff changeset
293 &is_compiled, &is_walkable);
a61af66fc99e Initial load
duke
parents:
diff changeset
294 if (is_compiled && !is_walkable) {
a61af66fc99e Initial load
duke
parents:
diff changeset
295 sender_check = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
296 }
a61af66fc99e Initial load
duke
parents:
diff changeset
297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
299
a61af66fc99e Initial load
duke
parents:
diff changeset
300 if (!sender_check) {
a61af66fc99e Initial load
duke
parents:
diff changeset
301 // nothing else to try if we can't recognize the sender
a61af66fc99e Initial load
duke
parents:
diff changeset
302 _mode = at_end_mode;
a61af66fc99e Initial load
duke
parents:
diff changeset
303 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
306
a61af66fc99e Initial load
duke
parents:
diff changeset
307 int loop_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
308 int loop_max = MaxJavaStackTraceDepth * 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
309
a61af66fc99e Initial load
duke
parents:
diff changeset
310 while (!fill_from_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
311 _frame = _frame.sender(&_reg_map);
a61af66fc99e Initial load
duke
parents:
diff changeset
312
a61af66fc99e Initial load
duke
parents:
diff changeset
313 #ifdef COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
314 #if defined(IA32) || defined(AMD64)
a61af66fc99e Initial load
duke
parents:
diff changeset
315 // Stress testing on C2 X86 has shown a periodic problem with
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // the sender() call below. The initial _frame that we have on
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // entry to the loop has already passed forte_safe_for_sender()
a61af66fc99e Initial load
duke
parents:
diff changeset
318 // so we only check frames after it.
a61af66fc99e Initial load
duke
parents:
diff changeset
319 if (!forte_safe_for_sender(&_frame, _thread)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
320 _mode = at_end_mode;
a61af66fc99e Initial load
duke
parents:
diff changeset
321 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
323 #endif // IA32 || AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
324 #endif // COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
325
a61af66fc99e Initial load
duke
parents:
diff changeset
326 if (++loop_count >= loop_max) {
a61af66fc99e Initial load
duke
parents:
diff changeset
327 // We have looped more than twice the number of possible
a61af66fc99e Initial load
duke
parents:
diff changeset
328 // Java frames. This indicates that we are trying to walk
a61af66fc99e Initial load
duke
parents:
diff changeset
329 // a stack that is in the middle of being constructed and
a61af66fc99e Initial load
duke
parents:
diff changeset
330 // it is self referential.
a61af66fc99e Initial load
duke
parents:
diff changeset
331 _mode = at_end_mode;
a61af66fc99e Initial load
duke
parents:
diff changeset
332 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
333 }
a61af66fc99e Initial load
duke
parents:
diff changeset
334 }
a61af66fc99e Initial load
duke
parents:
diff changeset
335 }
a61af66fc99e Initial load
duke
parents:
diff changeset
336
a61af66fc99e Initial load
duke
parents:
diff changeset
337
a61af66fc99e Initial load
duke
parents:
diff changeset
338 // Solaris SPARC Compiler1 needs an additional check on the grandparent
a61af66fc99e Initial load
duke
parents:
diff changeset
339 // of the top_frame when the parent of the top_frame is interpreted and
a61af66fc99e Initial load
duke
parents:
diff changeset
340 // the grandparent is compiled. However, in this method we do not know
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // the relationship of the current _frame relative to the top_frame so
a61af66fc99e Initial load
duke
parents:
diff changeset
342 // we implement a more broad sanity check. When the previous callee is
a61af66fc99e Initial load
duke
parents:
diff changeset
343 // interpreted and the current sender is compiled, we verify that the
a61af66fc99e Initial load
duke
parents:
diff changeset
344 // current sender is also walkable. If it is not walkable, then we mark
a61af66fc99e Initial load
duke
parents:
diff changeset
345 // the current vframeStream as at the end.
a61af66fc99e Initial load
duke
parents:
diff changeset
346 void vframeStreamForte::forte_next() {
a61af66fc99e Initial load
duke
parents:
diff changeset
347 // handle frames with inlining
a61af66fc99e Initial load
duke
parents:
diff changeset
348 if (_mode == compiled_mode &&
a61af66fc99e Initial load
duke
parents:
diff changeset
349 vframeStreamCommon::fill_in_compiled_inlined_sender()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
352
a61af66fc99e Initial load
duke
parents:
diff changeset
353 // handle general case
a61af66fc99e Initial load
duke
parents:
diff changeset
354
a61af66fc99e Initial load
duke
parents:
diff changeset
355 int loop_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
356 int loop_max = MaxJavaStackTraceDepth * 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
357
a61af66fc99e Initial load
duke
parents:
diff changeset
358
a61af66fc99e Initial load
duke
parents:
diff changeset
359 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
360
a61af66fc99e Initial load
duke
parents:
diff changeset
361 #if defined(COMPILER1) && defined(SPARC)
a61af66fc99e Initial load
duke
parents:
diff changeset
362 bool prevIsInterpreted = _frame.is_interpreted_frame();
a61af66fc99e Initial load
duke
parents:
diff changeset
363 #endif // COMPILER1 && SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
364
a61af66fc99e Initial load
duke
parents:
diff changeset
365 _frame = _frame.sender(&_reg_map);
a61af66fc99e Initial load
duke
parents:
diff changeset
366
a61af66fc99e Initial load
duke
parents:
diff changeset
367 if (!forte_safe_for_sender(&_frame, _thread)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 _mode = at_end_mode;
a61af66fc99e Initial load
duke
parents:
diff changeset
369 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
371
a61af66fc99e Initial load
duke
parents:
diff changeset
372 #if defined(COMPILER1) && defined(SPARC)
a61af66fc99e Initial load
duke
parents:
diff changeset
373 if (prevIsInterpreted) {
a61af66fc99e Initial load
duke
parents:
diff changeset
374 // previous callee was interpreted and may require a special check
a61af66fc99e Initial load
duke
parents:
diff changeset
375 if (_frame.is_compiled_frame() && _frame.cb()->is_compiled_by_c1()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // compiled sender called interpreted callee so need one more check
a61af66fc99e Initial load
duke
parents:
diff changeset
377 bool is_compiled, is_walkable;
a61af66fc99e Initial load
duke
parents:
diff changeset
378
a61af66fc99e Initial load
duke
parents:
diff changeset
379 // sanity check the compiled sender frame
a61af66fc99e Initial load
duke
parents:
diff changeset
380 forte_is_walkable_compiled_frame(&_frame, &_reg_map,
a61af66fc99e Initial load
duke
parents:
diff changeset
381 &is_compiled, &is_walkable);
a61af66fc99e Initial load
duke
parents:
diff changeset
382 assert(is_compiled, "sanity check");
a61af66fc99e Initial load
duke
parents:
diff changeset
383 if (!is_walkable) {
a61af66fc99e Initial load
duke
parents:
diff changeset
384 // compiled sender frame is not walkable so bail out
a61af66fc99e Initial load
duke
parents:
diff changeset
385 _mode = at_end_mode;
a61af66fc99e Initial load
duke
parents:
diff changeset
386 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
387 }
a61af66fc99e Initial load
duke
parents:
diff changeset
388 }
a61af66fc99e Initial load
duke
parents:
diff changeset
389 }
a61af66fc99e Initial load
duke
parents:
diff changeset
390 #endif // COMPILER1 && SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
391
a61af66fc99e Initial load
duke
parents:
diff changeset
392 if (++loop_count >= loop_max) {
a61af66fc99e Initial load
duke
parents:
diff changeset
393 // We have looped more than twice the number of possible
a61af66fc99e Initial load
duke
parents:
diff changeset
394 // Java frames. This indicates that we are trying to walk
a61af66fc99e Initial load
duke
parents:
diff changeset
395 // a stack that is in the middle of being constructed and
a61af66fc99e Initial load
duke
parents:
diff changeset
396 // it is self referential.
a61af66fc99e Initial load
duke
parents:
diff changeset
397 _mode = at_end_mode;
a61af66fc99e Initial load
duke
parents:
diff changeset
398 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
399 }
a61af66fc99e Initial load
duke
parents:
diff changeset
400 } while (!fill_from_frame());
a61af66fc99e Initial load
duke
parents:
diff changeset
401 }
a61af66fc99e Initial load
duke
parents:
diff changeset
402
a61af66fc99e Initial load
duke
parents:
diff changeset
403 // Determine if 'fr' is a walkable, compiled frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
404 // *is_compiled_p is set to true if the frame is compiled and if it
a61af66fc99e Initial load
duke
parents:
diff changeset
405 // is, then *is_walkable_p is set to true if it is also walkable.
a61af66fc99e Initial load
duke
parents:
diff changeset
406 static void forte_is_walkable_compiled_frame(frame* fr, RegisterMap* map,
a61af66fc99e Initial load
duke
parents:
diff changeset
407 bool* is_compiled_p, bool* is_walkable_p) {
a61af66fc99e Initial load
duke
parents:
diff changeset
408
a61af66fc99e Initial load
duke
parents:
diff changeset
409 *is_compiled_p = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
410 *is_walkable_p = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
411
a61af66fc99e Initial load
duke
parents:
diff changeset
412 CodeBlob* cb = CodeCache::find_blob(fr->pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
413 if (cb != NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
414 cb->is_nmethod() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
415 ((nmethod*)cb)->is_java_method()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
416 // frame is compiled and executing a Java method
a61af66fc99e Initial load
duke
parents:
diff changeset
417 *is_compiled_p = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
418
a61af66fc99e Initial load
duke
parents:
diff changeset
419 // Increment PC because the PcDesc we want is associated with
a61af66fc99e Initial load
duke
parents:
diff changeset
420 // the *end* of the instruction, and pc_desc_near searches
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // forward to the first matching PC after the probe PC.
a61af66fc99e Initial load
duke
parents:
diff changeset
422 PcDesc* pc_desc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
423 if (!DebugNonSafepoints_IS_CLEARED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
424 // usual case: look for any safepoint near the sampled PC
a61af66fc99e Initial load
duke
parents:
diff changeset
425 address probe_pc = fr->pc() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
426 pc_desc = ((nmethod*) cb)->pc_desc_near(probe_pc);
a61af66fc99e Initial load
duke
parents:
diff changeset
427 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
428 // reduced functionality: only recognize PCs immediately after calls
a61af66fc99e Initial load
duke
parents:
diff changeset
429 pc_desc = ((nmethod*) cb)->pc_desc_at(fr->pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
431 if (pc_desc != NULL && (pc_desc->scope_decode_offset()
a61af66fc99e Initial load
duke
parents:
diff changeset
432 == DebugInformationRecorder::serialized_null)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
433 pc_desc = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
435 if (pc_desc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
436 // it has a PcDesc so the frame is also walkable
a61af66fc99e Initial load
duke
parents:
diff changeset
437 *is_walkable_p = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
438 if (!DebugNonSafepoints_IS_CLEARED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // Normalize the PC to the one associated exactly with
a61af66fc99e Initial load
duke
parents:
diff changeset
440 // this PcDesc, so that subsequent stack-walking queries
a61af66fc99e Initial load
duke
parents:
diff changeset
441 // need not be approximate:
a61af66fc99e Initial load
duke
parents:
diff changeset
442 fr->set_pc(pc_desc->real_pc((nmethod*) cb));
a61af66fc99e Initial load
duke
parents:
diff changeset
443 }
a61af66fc99e Initial load
duke
parents:
diff changeset
444 }
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // Implied else: this compiled frame has no PcDesc, i.e., contains
a61af66fc99e Initial load
duke
parents:
diff changeset
446 // a frameless stub such as C1 method exit, so it is not walkable.
a61af66fc99e Initial load
duke
parents:
diff changeset
447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
448 // Implied else: this isn't a compiled frame so it isn't a
a61af66fc99e Initial load
duke
parents:
diff changeset
449 // walkable, compiled frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
451
a61af66fc99e Initial load
duke
parents:
diff changeset
452 // Determine if 'fr' is a walkable interpreted frame. Returns false
a61af66fc99e Initial load
duke
parents:
diff changeset
453 // if it is not. *method_p, and *bci_p are not set when false is
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // returned. *method_p is non-NULL if frame was executing a Java
a61af66fc99e Initial load
duke
parents:
diff changeset
455 // method. *bci_p is != -1 if a valid BCI in the Java method could
a61af66fc99e Initial load
duke
parents:
diff changeset
456 // be found.
a61af66fc99e Initial load
duke
parents:
diff changeset
457 // Note: this method returns true when a valid Java method is found
a61af66fc99e Initial load
duke
parents:
diff changeset
458 // even if a valid BCI cannot be found.
a61af66fc99e Initial load
duke
parents:
diff changeset
459
a61af66fc99e Initial load
duke
parents:
diff changeset
460 static bool forte_is_walkable_interpreted_frame(frame* fr,
a61af66fc99e Initial load
duke
parents:
diff changeset
461 methodOop* method_p, int* bci_p) {
a61af66fc99e Initial load
duke
parents:
diff changeset
462 assert(fr->is_interpreted_frame(), "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
463
a61af66fc99e Initial load
duke
parents:
diff changeset
464 // top frame is an interpreted frame
a61af66fc99e Initial load
duke
parents:
diff changeset
465 // check if it is walkable (i.e. valid methodOop and valid bci)
a61af66fc99e Initial load
duke
parents:
diff changeset
466 if (fr->is_interpreted_frame_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
467 if (fr->fp() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
468 // access address in order not to trigger asserts that
a61af66fc99e Initial load
duke
parents:
diff changeset
469 // are built in interpreter_frame_method function
a61af66fc99e Initial load
duke
parents:
diff changeset
470 methodOop method = *fr->interpreter_frame_method_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
471 if (Universe::heap()->is_valid_method(method)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
472 intptr_t bcx = fr->interpreter_frame_bcx();
a61af66fc99e Initial load
duke
parents:
diff changeset
473 int bci = method->validate_bci_from_bcx(bcx);
a61af66fc99e Initial load
duke
parents:
diff changeset
474 // note: bci is set to -1 if not a valid bci
a61af66fc99e Initial load
duke
parents:
diff changeset
475 *method_p = method;
a61af66fc99e Initial load
duke
parents:
diff changeset
476 *bci_p = bci;
a61af66fc99e Initial load
duke
parents:
diff changeset
477 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
478 }
a61af66fc99e Initial load
duke
parents:
diff changeset
479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
481 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
483
a61af66fc99e Initial load
duke
parents:
diff changeset
484
a61af66fc99e Initial load
duke
parents:
diff changeset
485 // Determine if 'fr' can be used to find a walkable frame. Returns
a61af66fc99e Initial load
duke
parents:
diff changeset
486 // false if a walkable frame cannot be found. *walkframe_p, *method_p,
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // and *bci_p are not set when false is returned. Returns true if a
a61af66fc99e Initial load
duke
parents:
diff changeset
488 // walkable frame is returned via *walkframe_p. *method_p is non-NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
489 // if the returned frame was executing a Java method. *bci_p is != -1
a61af66fc99e Initial load
duke
parents:
diff changeset
490 // if a valid BCI in the Java method could be found.
a61af66fc99e Initial load
duke
parents:
diff changeset
491 //
a61af66fc99e Initial load
duke
parents:
diff changeset
492 // *walkframe_p will be used by vframeStreamForte as the initial
a61af66fc99e Initial load
duke
parents:
diff changeset
493 // frame for walking the stack. Currently the initial frame is
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // skipped by vframeStreamForte because we inherited the logic from
a61af66fc99e Initial load
duke
parents:
diff changeset
495 // the vframeStream class. This needs to be revisited in the future.
a61af66fc99e Initial load
duke
parents:
diff changeset
496 static bool forte_is_walkable_frame(JavaThread* thread, frame* fr,
a61af66fc99e Initial load
duke
parents:
diff changeset
497 frame* walkframe_p, methodOop* method_p, int* bci_p) {
a61af66fc99e Initial load
duke
parents:
diff changeset
498
a61af66fc99e Initial load
duke
parents:
diff changeset
499 if (!forte_safe_for_sender(fr, thread)
a61af66fc99e Initial load
duke
parents:
diff changeset
500 || is_unknown_compiled_frame(fr, thread)
a61af66fc99e Initial load
duke
parents:
diff changeset
501 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
502 // If the initial frame is not safe, then bail out. So far this
a61af66fc99e Initial load
duke
parents:
diff changeset
503 // has only been seen on Solaris X86 with Compiler2, but it seems
a61af66fc99e Initial load
duke
parents:
diff changeset
504 // like a great initial sanity check.
a61af66fc99e Initial load
duke
parents:
diff changeset
505 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
507
a61af66fc99e Initial load
duke
parents:
diff changeset
508 if (fr->is_first_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
509 // If initial frame is frame from StubGenerator and there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
510 // previous anchor, there are no java frames yet
a61af66fc99e Initial load
duke
parents:
diff changeset
511 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
512 }
a61af66fc99e Initial load
duke
parents:
diff changeset
513
a61af66fc99e Initial load
duke
parents:
diff changeset
514 if (fr->is_interpreted_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
515 if (forte_is_walkable_interpreted_frame(fr, method_p, bci_p)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
516 *walkframe_p = *fr;
a61af66fc99e Initial load
duke
parents:
diff changeset
517 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
518 }
a61af66fc99e Initial load
duke
parents:
diff changeset
519 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
520 }
a61af66fc99e Initial load
duke
parents:
diff changeset
521
a61af66fc99e Initial load
duke
parents:
diff changeset
522 // At this point we have something other than a first frame or an
a61af66fc99e Initial load
duke
parents:
diff changeset
523 // interpreted frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
524
a61af66fc99e Initial load
duke
parents:
diff changeset
525 methodOop method = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
526 frame candidate = *fr;
a61af66fc99e Initial load
duke
parents:
diff changeset
527
a61af66fc99e Initial load
duke
parents:
diff changeset
528 // If we loop more than twice the number of possible Java
a61af66fc99e Initial load
duke
parents:
diff changeset
529 // frames, then this indicates that we are trying to walk
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // a stack that is in the middle of being constructed and
a61af66fc99e Initial load
duke
parents:
diff changeset
531 // it is self referential. So far this problem has only
a61af66fc99e Initial load
duke
parents:
diff changeset
532 // been seen on Solaris X86 Compiler2, but it seems like
a61af66fc99e Initial load
duke
parents:
diff changeset
533 // a good robustness fix for all platforms.
a61af66fc99e Initial load
duke
parents:
diff changeset
534
a61af66fc99e Initial load
duke
parents:
diff changeset
535 int loop_count;
a61af66fc99e Initial load
duke
parents:
diff changeset
536 int loop_max = MaxJavaStackTraceDepth * 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
537
a61af66fc99e Initial load
duke
parents:
diff changeset
538 for (loop_count = 0; loop_count < loop_max; loop_count++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
539 // determine if the candidate frame is executing a Java method
a61af66fc99e Initial load
duke
parents:
diff changeset
540 if (CodeCache::contains(candidate.pc())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
541 // candidate is a compiled frame or stub routine
a61af66fc99e Initial load
duke
parents:
diff changeset
542 CodeBlob* cb = CodeCache::find_blob(candidate.pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
543
a61af66fc99e Initial load
duke
parents:
diff changeset
544 if (cb->is_nmethod()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
545 method = ((nmethod *)cb)->method();
a61af66fc99e Initial load
duke
parents:
diff changeset
546 }
a61af66fc99e Initial load
duke
parents:
diff changeset
547 } // end if CodeCache has our PC
a61af66fc99e Initial load
duke
parents:
diff changeset
548
a61af66fc99e Initial load
duke
parents:
diff changeset
549 RegisterMap map(thread, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
550
a61af66fc99e Initial load
duke
parents:
diff changeset
551 // we have a Java frame that seems reasonable
a61af66fc99e Initial load
duke
parents:
diff changeset
552 if (method != NULL && candidate.is_java_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
553 && candidate.sp() != NULL && candidate.pc() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
554 // we need to sanity check the candidate further
a61af66fc99e Initial load
duke
parents:
diff changeset
555 bool is_compiled, is_walkable;
a61af66fc99e Initial load
duke
parents:
diff changeset
556
a61af66fc99e Initial load
duke
parents:
diff changeset
557 forte_is_walkable_compiled_frame(&candidate, &map, &is_compiled,
a61af66fc99e Initial load
duke
parents:
diff changeset
558 &is_walkable);
a61af66fc99e Initial load
duke
parents:
diff changeset
559 if (is_compiled) {
a61af66fc99e Initial load
duke
parents:
diff changeset
560 // At this point, we know we have a compiled Java frame with
a61af66fc99e Initial load
duke
parents:
diff changeset
561 // method information that we want to return. We don't check
a61af66fc99e Initial load
duke
parents:
diff changeset
562 // the is_walkable flag here because that flag pertains to
a61af66fc99e Initial load
duke
parents:
diff changeset
563 // vframeStreamForte work that is done after we are done here.
a61af66fc99e Initial load
duke
parents:
diff changeset
564 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
566 }
a61af66fc99e Initial load
duke
parents:
diff changeset
567
a61af66fc99e Initial load
duke
parents:
diff changeset
568 // At this point, the candidate doesn't work so try the sender.
a61af66fc99e Initial load
duke
parents:
diff changeset
569
a61af66fc99e Initial load
duke
parents:
diff changeset
570 // For AsyncGetCallTrace() we cannot assume there is a sender
a61af66fc99e Initial load
duke
parents:
diff changeset
571 // for the initial frame. The initial forte_safe_for_sender() call
a61af66fc99e Initial load
duke
parents:
diff changeset
572 // and check for is_first_frame() is done on entry to this method.
a61af66fc99e Initial load
duke
parents:
diff changeset
573 candidate = candidate.sender(&map);
a61af66fc99e Initial load
duke
parents:
diff changeset
574 if (!forte_safe_for_sender(&candidate, thread)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
575
a61af66fc99e Initial load
duke
parents:
diff changeset
576 #ifdef COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
577 #if defined(IA32) || defined(AMD64)
a61af66fc99e Initial load
duke
parents:
diff changeset
578 // C2 on X86 can use the ebp register as a general purpose register
a61af66fc99e Initial load
duke
parents:
diff changeset
579 // which can cause the candidate to fail theforte_safe_for_sender()
a61af66fc99e Initial load
duke
parents:
diff changeset
580 // above. We try one more time using a NULL frame pointer (fp).
a61af66fc99e Initial load
duke
parents:
diff changeset
581
a61af66fc99e Initial load
duke
parents:
diff changeset
582 candidate = frame(candidate.sp(), NULL, candidate.pc());
a61af66fc99e Initial load
duke
parents:
diff changeset
583 if (!forte_safe_for_sender(&candidate, thread)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
584 #endif // IA32 || AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
585 #endif // COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
586
a61af66fc99e Initial load
duke
parents:
diff changeset
587 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
588
a61af66fc99e Initial load
duke
parents:
diff changeset
589 #ifdef COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
590 #if defined(IA32) || defined(AMD64)
a61af66fc99e Initial load
duke
parents:
diff changeset
591 } // end forte_safe_for_sender retry with NULL fp
a61af66fc99e Initial load
duke
parents:
diff changeset
592 #endif // IA32 || AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
593 #endif // COMPILER2
a61af66fc99e Initial load
duke
parents:
diff changeset
594
a61af66fc99e Initial load
duke
parents:
diff changeset
595 } // end first forte_safe_for_sender check
a61af66fc99e Initial load
duke
parents:
diff changeset
596
a61af66fc99e Initial load
duke
parents:
diff changeset
597 if (candidate.is_first_frame()
a61af66fc99e Initial load
duke
parents:
diff changeset
598 || is_unknown_compiled_frame(&candidate, thread)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
599 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
601 } // end for loop_count
a61af66fc99e Initial load
duke
parents:
diff changeset
602
a61af66fc99e Initial load
duke
parents:
diff changeset
603 if (method == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
604 // If we didn't get any method info from the candidate, then
a61af66fc99e Initial load
duke
parents:
diff changeset
605 // we have nothing to return so bail out.
a61af66fc99e Initial load
duke
parents:
diff changeset
606 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
607 }
a61af66fc99e Initial load
duke
parents:
diff changeset
608
a61af66fc99e Initial load
duke
parents:
diff changeset
609 *walkframe_p = candidate;
a61af66fc99e Initial load
duke
parents:
diff changeset
610 *method_p = method;
a61af66fc99e Initial load
duke
parents:
diff changeset
611 *bci_p = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
612 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
613 }
a61af66fc99e Initial load
duke
parents:
diff changeset
614
a61af66fc99e Initial load
duke
parents:
diff changeset
615
a61af66fc99e Initial load
duke
parents:
diff changeset
616 // call frame copied from old .h file and renamed
a61af66fc99e Initial load
duke
parents:
diff changeset
617 typedef struct {
a61af66fc99e Initial load
duke
parents:
diff changeset
618 jint lineno; // line number in the source file
a61af66fc99e Initial load
duke
parents:
diff changeset
619 jmethodID method_id; // method executed in this frame
a61af66fc99e Initial load
duke
parents:
diff changeset
620 } ASGCT_CallFrame;
a61af66fc99e Initial load
duke
parents:
diff changeset
621
a61af66fc99e Initial load
duke
parents:
diff changeset
622 // call trace copied from old .h file and renamed
a61af66fc99e Initial load
duke
parents:
diff changeset
623 typedef struct {
a61af66fc99e Initial load
duke
parents:
diff changeset
624 JNIEnv *env_id; // Env where trace was recorded
a61af66fc99e Initial load
duke
parents:
diff changeset
625 jint num_frames; // number of frames in this trace
a61af66fc99e Initial load
duke
parents:
diff changeset
626 ASGCT_CallFrame *frames; // frames
a61af66fc99e Initial load
duke
parents:
diff changeset
627 } ASGCT_CallTrace;
a61af66fc99e Initial load
duke
parents:
diff changeset
628
a61af66fc99e Initial load
duke
parents:
diff changeset
629 static void forte_fill_call_trace_given_top(JavaThread* thd,
a61af66fc99e Initial load
duke
parents:
diff changeset
630 ASGCT_CallTrace* trace, int depth, frame top_frame) {
a61af66fc99e Initial load
duke
parents:
diff changeset
631 NoHandleMark nhm;
a61af66fc99e Initial load
duke
parents:
diff changeset
632
a61af66fc99e Initial load
duke
parents:
diff changeset
633 frame walkframe;
a61af66fc99e Initial load
duke
parents:
diff changeset
634 methodOop method;
a61af66fc99e Initial load
duke
parents:
diff changeset
635 int bci;
a61af66fc99e Initial load
duke
parents:
diff changeset
636 int count;
a61af66fc99e Initial load
duke
parents:
diff changeset
637
a61af66fc99e Initial load
duke
parents:
diff changeset
638 count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
639 assert(trace->frames != NULL, "trace->frames must be non-NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
640
a61af66fc99e Initial load
duke
parents:
diff changeset
641 if (!forte_is_walkable_frame(thd, &top_frame, &walkframe, &method, &bci)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
642 // return if no walkable frame is found
a61af66fc99e Initial load
duke
parents:
diff changeset
643 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
645
a61af66fc99e Initial load
duke
parents:
diff changeset
646 CollectedHeap* ch = Universe::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
647
a61af66fc99e Initial load
duke
parents:
diff changeset
648 if (method != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
649 // The method is not stored GC safe so see if GC became active
a61af66fc99e Initial load
duke
parents:
diff changeset
650 // after we entered AsyncGetCallTrace() and before we try to
a61af66fc99e Initial load
duke
parents:
diff changeset
651 // use the methodOop.
a61af66fc99e Initial load
duke
parents:
diff changeset
652 // Yes, there is still a window after this check and before
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // we use methodOop below, but we can't lock out GC so that
a61af66fc99e Initial load
duke
parents:
diff changeset
654 // has to be an acceptable risk.
a61af66fc99e Initial load
duke
parents:
diff changeset
655 if (!ch->is_valid_method(method)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
656 trace->num_frames = -2;
a61af66fc99e Initial load
duke
parents:
diff changeset
657 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
658 }
a61af66fc99e Initial load
duke
parents:
diff changeset
659
a61af66fc99e Initial load
duke
parents:
diff changeset
660 if (DebugNonSafepoints_IS_CLEARED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
661 // Take whatever method the top-frame decoder managed to scrape up.
a61af66fc99e Initial load
duke
parents:
diff changeset
662 // We look further at the top frame only if non-safepoint
a61af66fc99e Initial load
duke
parents:
diff changeset
663 // debugging information is available.
a61af66fc99e Initial load
duke
parents:
diff changeset
664 count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
665 trace->num_frames = count;
a61af66fc99e Initial load
duke
parents:
diff changeset
666 trace->frames[0].method_id = method->find_jmethod_id_or_null();
a61af66fc99e Initial load
duke
parents:
diff changeset
667 if (!method->is_native()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
668 trace->frames[0].lineno = bci;
a61af66fc99e Initial load
duke
parents:
diff changeset
669 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
670 trace->frames[0].lineno = -3;
a61af66fc99e Initial load
duke
parents:
diff changeset
671 }
a61af66fc99e Initial load
duke
parents:
diff changeset
672 }
a61af66fc99e Initial load
duke
parents:
diff changeset
673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
674
a61af66fc99e Initial load
duke
parents:
diff changeset
675 // check has_last_Java_frame() after looking at the top frame
a61af66fc99e Initial load
duke
parents:
diff changeset
676 // which may be an interpreted Java frame.
a61af66fc99e Initial load
duke
parents:
diff changeset
677 if (!thd->has_last_Java_frame() && method == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
678 trace->num_frames = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
679 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
680 }
a61af66fc99e Initial load
duke
parents:
diff changeset
681
a61af66fc99e Initial load
duke
parents:
diff changeset
682 vframeStreamForte st(thd, walkframe, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
683 for (; !st.at_end() && count < depth; st.forte_next(), count++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
684 bci = st.bci();
a61af66fc99e Initial load
duke
parents:
diff changeset
685 method = st.method();
a61af66fc99e Initial load
duke
parents:
diff changeset
686
a61af66fc99e Initial load
duke
parents:
diff changeset
687 // The method is not stored GC safe so see if GC became active
a61af66fc99e Initial load
duke
parents:
diff changeset
688 // after we entered AsyncGetCallTrace() and before we try to
a61af66fc99e Initial load
duke
parents:
diff changeset
689 // use the methodOop.
a61af66fc99e Initial load
duke
parents:
diff changeset
690 // Yes, there is still a window after this check and before
a61af66fc99e Initial load
duke
parents:
diff changeset
691 // we use methodOop below, but we can't lock out GC so that
a61af66fc99e Initial load
duke
parents:
diff changeset
692 // has to be an acceptable risk.
a61af66fc99e Initial load
duke
parents:
diff changeset
693 if (!ch->is_valid_method(method)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
694 // we throw away everything we've gathered in this sample since
a61af66fc99e Initial load
duke
parents:
diff changeset
695 // none of it is safe
a61af66fc99e Initial load
duke
parents:
diff changeset
696 trace->num_frames = -2;
a61af66fc99e Initial load
duke
parents:
diff changeset
697 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
698 }
a61af66fc99e Initial load
duke
parents:
diff changeset
699
a61af66fc99e Initial load
duke
parents:
diff changeset
700 trace->frames[count].method_id = method->find_jmethod_id_or_null();
a61af66fc99e Initial load
duke
parents:
diff changeset
701 if (!method->is_native()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
702 trace->frames[count].lineno = bci;
a61af66fc99e Initial load
duke
parents:
diff changeset
703 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
704 trace->frames[count].lineno = -3;
a61af66fc99e Initial load
duke
parents:
diff changeset
705 }
a61af66fc99e Initial load
duke
parents:
diff changeset
706 }
a61af66fc99e Initial load
duke
parents:
diff changeset
707 trace->num_frames = count;
a61af66fc99e Initial load
duke
parents:
diff changeset
708 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
709 }
a61af66fc99e Initial load
duke
parents:
diff changeset
710
a61af66fc99e Initial load
duke
parents:
diff changeset
711
a61af66fc99e Initial load
duke
parents:
diff changeset
712 // Forte Analyzer AsyncGetCallTrace() entry point. Currently supported
a61af66fc99e Initial load
duke
parents:
diff changeset
713 // on Linux X86, Solaris SPARC and Solaris X86.
a61af66fc99e Initial load
duke
parents:
diff changeset
714 //
a61af66fc99e Initial load
duke
parents:
diff changeset
715 // Async-safe version of GetCallTrace being called from a signal handler
a61af66fc99e Initial load
duke
parents:
diff changeset
716 // when a LWP gets interrupted by SIGPROF but the stack traces are filled
a61af66fc99e Initial load
duke
parents:
diff changeset
717 // with different content (see below).
a61af66fc99e Initial load
duke
parents:
diff changeset
718 //
a61af66fc99e Initial load
duke
parents:
diff changeset
719 // This function must only be called when JVM/TI
a61af66fc99e Initial load
duke
parents:
diff changeset
720 // CLASS_LOAD events have been enabled since agent startup. The enabled
a61af66fc99e Initial load
duke
parents:
diff changeset
721 // event will cause the jmethodIDs to be allocated at class load time.
a61af66fc99e Initial load
duke
parents:
diff changeset
722 // The jmethodIDs cannot be allocated in a signal handler because locks
a61af66fc99e Initial load
duke
parents:
diff changeset
723 // cannot be grabbed in a signal handler safely.
a61af66fc99e Initial load
duke
parents:
diff changeset
724 //
a61af66fc99e Initial load
duke
parents:
diff changeset
725 // void (*AsyncGetCallTrace)(ASGCT_CallTrace *trace, jint depth, void* ucontext)
a61af66fc99e Initial load
duke
parents:
diff changeset
726 //
a61af66fc99e Initial load
duke
parents:
diff changeset
727 // Called by the profiler to obtain the current method call stack trace for
a61af66fc99e Initial load
duke
parents:
diff changeset
728 // a given thread. The thread is identified by the env_id field in the
a61af66fc99e Initial load
duke
parents:
diff changeset
729 // ASGCT_CallTrace structure. The profiler agent should allocate a ASGCT_CallTrace
a61af66fc99e Initial load
duke
parents:
diff changeset
730 // structure with enough memory for the requested stack depth. The VM fills in
a61af66fc99e Initial load
duke
parents:
diff changeset
731 // the frames buffer and the num_frames field.
a61af66fc99e Initial load
duke
parents:
diff changeset
732 //
a61af66fc99e Initial load
duke
parents:
diff changeset
733 // Arguments:
a61af66fc99e Initial load
duke
parents:
diff changeset
734 //
a61af66fc99e Initial load
duke
parents:
diff changeset
735 // trace - trace data structure to be filled by the VM.
a61af66fc99e Initial load
duke
parents:
diff changeset
736 // depth - depth of the call stack trace.
a61af66fc99e Initial load
duke
parents:
diff changeset
737 // ucontext - ucontext_t of the LWP
a61af66fc99e Initial load
duke
parents:
diff changeset
738 //
a61af66fc99e Initial load
duke
parents:
diff changeset
739 // ASGCT_CallTrace:
a61af66fc99e Initial load
duke
parents:
diff changeset
740 // typedef struct {
a61af66fc99e Initial load
duke
parents:
diff changeset
741 // JNIEnv *env_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
742 // jint num_frames;
a61af66fc99e Initial load
duke
parents:
diff changeset
743 // ASGCT_CallFrame *frames;
a61af66fc99e Initial load
duke
parents:
diff changeset
744 // } ASGCT_CallTrace;
a61af66fc99e Initial load
duke
parents:
diff changeset
745 //
a61af66fc99e Initial load
duke
parents:
diff changeset
746 // Fields:
a61af66fc99e Initial load
duke
parents:
diff changeset
747 // env_id - ID of thread which executed this trace.
a61af66fc99e Initial load
duke
parents:
diff changeset
748 // num_frames - number of frames in the trace.
a61af66fc99e Initial load
duke
parents:
diff changeset
749 // (< 0 indicates the frame is not walkable).
a61af66fc99e Initial load
duke
parents:
diff changeset
750 // frames - the ASGCT_CallFrames that make up this trace. Callee followed by callers.
a61af66fc99e Initial load
duke
parents:
diff changeset
751 //
a61af66fc99e Initial load
duke
parents:
diff changeset
752 // ASGCT_CallFrame:
a61af66fc99e Initial load
duke
parents:
diff changeset
753 // typedef struct {
a61af66fc99e Initial load
duke
parents:
diff changeset
754 // jint lineno;
a61af66fc99e Initial load
duke
parents:
diff changeset
755 // jmethodID method_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
756 // } ASGCT_CallFrame;
a61af66fc99e Initial load
duke
parents:
diff changeset
757 //
a61af66fc99e Initial load
duke
parents:
diff changeset
758 // Fields:
a61af66fc99e Initial load
duke
parents:
diff changeset
759 // 1) For Java frame (interpreted and compiled),
a61af66fc99e Initial load
duke
parents:
diff changeset
760 // lineno - bci of the method being executed or -1 if bci is not available
a61af66fc99e Initial load
duke
parents:
diff changeset
761 // method_id - jmethodID of the method being executed
a61af66fc99e Initial load
duke
parents:
diff changeset
762 // 2) For native method
a61af66fc99e Initial load
duke
parents:
diff changeset
763 // lineno - (-3)
a61af66fc99e Initial load
duke
parents:
diff changeset
764 // method_id - jmethodID of the method being executed
a61af66fc99e Initial load
duke
parents:
diff changeset
765
a61af66fc99e Initial load
duke
parents:
diff changeset
766 extern "C" {
a61af66fc99e Initial load
duke
parents:
diff changeset
767 void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) {
a61af66fc99e Initial load
duke
parents:
diff changeset
768 if (SafepointSynchronize::is_synchronizing()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
769 // The safepoint mechanism is trying to synchronize all the threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
770 // Since this can involve thread suspension, it is not safe for us
a61af66fc99e Initial load
duke
parents:
diff changeset
771 // to be here. We can reduce the deadlock risk window by quickly
a61af66fc99e Initial load
duke
parents:
diff changeset
772 // returning to the SIGPROF handler. However, it is still possible
a61af66fc99e Initial load
duke
parents:
diff changeset
773 // for VMThread to catch us here or in the SIGPROF handler. If we
a61af66fc99e Initial load
duke
parents:
diff changeset
774 // are suspended while holding a resource and another thread blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
775 // on that resource in the SIGPROF handler, then we will have a
a61af66fc99e Initial load
duke
parents:
diff changeset
776 // three-thread deadlock (VMThread, this thread, the other thread).
a61af66fc99e Initial load
duke
parents:
diff changeset
777 trace->num_frames = -10;
a61af66fc99e Initial load
duke
parents:
diff changeset
778 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
779 }
a61af66fc99e Initial load
duke
parents:
diff changeset
780
a61af66fc99e Initial load
duke
parents:
diff changeset
781 JavaThread* thread;
a61af66fc99e Initial load
duke
parents:
diff changeset
782
a61af66fc99e Initial load
duke
parents:
diff changeset
783 if (trace->env_id == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
784 (thread = JavaThread::thread_from_jni_environment(trace->env_id)) == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
785 thread->is_exiting()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
786
a61af66fc99e Initial load
duke
parents:
diff changeset
787 // bad env_id, thread has exited or thread is exiting
a61af66fc99e Initial load
duke
parents:
diff changeset
788 trace->num_frames = -8;
a61af66fc99e Initial load
duke
parents:
diff changeset
789 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
790 }
a61af66fc99e Initial load
duke
parents:
diff changeset
791
a61af66fc99e Initial load
duke
parents:
diff changeset
792 if (thread->in_deopt_handler()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
793 // thread is in the deoptimization handler so return no frames
a61af66fc99e Initial load
duke
parents:
diff changeset
794 trace->num_frames = -9;
a61af66fc99e Initial load
duke
parents:
diff changeset
795 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
797
a61af66fc99e Initial load
duke
parents:
diff changeset
798 assert(JavaThread::current() == thread,
a61af66fc99e Initial load
duke
parents:
diff changeset
799 "AsyncGetCallTrace must be called by the current interrupted thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
800
a61af66fc99e Initial load
duke
parents:
diff changeset
801 if (!JvmtiExport::should_post_class_load()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
802 trace->num_frames = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
803 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
804 }
a61af66fc99e Initial load
duke
parents:
diff changeset
805
a61af66fc99e Initial load
duke
parents:
diff changeset
806 if (Universe::heap()->is_gc_active()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
807 trace->num_frames = -2;
a61af66fc99e Initial load
duke
parents:
diff changeset
808 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
809 }
a61af66fc99e Initial load
duke
parents:
diff changeset
810
a61af66fc99e Initial load
duke
parents:
diff changeset
811 switch (thread->thread_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
812 case _thread_new:
a61af66fc99e Initial load
duke
parents:
diff changeset
813 case _thread_uninitialized:
a61af66fc99e Initial load
duke
parents:
diff changeset
814 case _thread_new_trans:
a61af66fc99e Initial load
duke
parents:
diff changeset
815 // We found the thread on the threads list above, but it is too
a61af66fc99e Initial load
duke
parents:
diff changeset
816 // young to be useful so return that there are no Java frames.
a61af66fc99e Initial load
duke
parents:
diff changeset
817 trace->num_frames = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
818 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
819 case _thread_in_native:
a61af66fc99e Initial load
duke
parents:
diff changeset
820 case _thread_in_native_trans:
a61af66fc99e Initial load
duke
parents:
diff changeset
821 case _thread_blocked:
a61af66fc99e Initial load
duke
parents:
diff changeset
822 case _thread_blocked_trans:
a61af66fc99e Initial load
duke
parents:
diff changeset
823 case _thread_in_vm:
a61af66fc99e Initial load
duke
parents:
diff changeset
824 case _thread_in_vm_trans:
a61af66fc99e Initial load
duke
parents:
diff changeset
825 {
a61af66fc99e Initial load
duke
parents:
diff changeset
826 frame fr;
a61af66fc99e Initial load
duke
parents:
diff changeset
827
a61af66fc99e Initial load
duke
parents:
diff changeset
828 // param isInJava == false - indicate we aren't in Java code
a61af66fc99e Initial load
duke
parents:
diff changeset
829 if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, false)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
830 if (!thread->has_last_Java_frame()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
831 trace->num_frames = 0; // no Java frames
a61af66fc99e Initial load
duke
parents:
diff changeset
832 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
833 trace->num_frames = -3; // unknown frame
a61af66fc99e Initial load
duke
parents:
diff changeset
834 }
a61af66fc99e Initial load
duke
parents:
diff changeset
835 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
836 trace->num_frames = -4; // non walkable frame by default
a61af66fc99e Initial load
duke
parents:
diff changeset
837 forte_fill_call_trace_given_top(thread, trace, depth, fr);
a61af66fc99e Initial load
duke
parents:
diff changeset
838 }
a61af66fc99e Initial load
duke
parents:
diff changeset
839 }
a61af66fc99e Initial load
duke
parents:
diff changeset
840 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
841 case _thread_in_Java:
a61af66fc99e Initial load
duke
parents:
diff changeset
842 case _thread_in_Java_trans:
a61af66fc99e Initial load
duke
parents:
diff changeset
843 {
a61af66fc99e Initial load
duke
parents:
diff changeset
844 frame fr;
a61af66fc99e Initial load
duke
parents:
diff changeset
845
a61af66fc99e Initial load
duke
parents:
diff changeset
846 // param isInJava == true - indicate we are in Java code
a61af66fc99e Initial load
duke
parents:
diff changeset
847 if (!thread->pd_get_top_frame_for_signal_handler(&fr, ucontext, true)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
848 trace->num_frames = -5; // unknown frame
a61af66fc99e Initial load
duke
parents:
diff changeset
849 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
850 trace->num_frames = -6; // non walkable frame by default
a61af66fc99e Initial load
duke
parents:
diff changeset
851 forte_fill_call_trace_given_top(thread, trace, depth, fr);
a61af66fc99e Initial load
duke
parents:
diff changeset
852 }
a61af66fc99e Initial load
duke
parents:
diff changeset
853 }
a61af66fc99e Initial load
duke
parents:
diff changeset
854 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
855 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
856 // Unknown thread state
a61af66fc99e Initial load
duke
parents:
diff changeset
857 trace->num_frames = -7;
a61af66fc99e Initial load
duke
parents:
diff changeset
858 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
859 }
a61af66fc99e Initial load
duke
parents:
diff changeset
860 }
a61af66fc99e Initial load
duke
parents:
diff changeset
861
a61af66fc99e Initial load
duke
parents:
diff changeset
862
a61af66fc99e Initial load
duke
parents:
diff changeset
863 #ifndef _WINDOWS
a61af66fc99e Initial load
duke
parents:
diff changeset
864 // Support for the Forte(TM) Peformance Tools collector.
a61af66fc99e Initial load
duke
parents:
diff changeset
865 //
a61af66fc99e Initial load
duke
parents:
diff changeset
866 // The method prototype is derived from libcollector.h. For more
a61af66fc99e Initial load
duke
parents:
diff changeset
867 // information, please see the libcollect man page.
a61af66fc99e Initial load
duke
parents:
diff changeset
868
a61af66fc99e Initial load
duke
parents:
diff changeset
869 // Method to let libcollector know about a dynamically loaded function.
a61af66fc99e Initial load
duke
parents:
diff changeset
870 // Because it is weakly bound, the calls become NOP's when the library
a61af66fc99e Initial load
duke
parents:
diff changeset
871 // isn't present.
a61af66fc99e Initial load
duke
parents:
diff changeset
872 void collector_func_load(char* name,
a61af66fc99e Initial load
duke
parents:
diff changeset
873 void* null_argument_1,
a61af66fc99e Initial load
duke
parents:
diff changeset
874 void* null_argument_2,
a61af66fc99e Initial load
duke
parents:
diff changeset
875 void *vaddr,
a61af66fc99e Initial load
duke
parents:
diff changeset
876 int size,
a61af66fc99e Initial load
duke
parents:
diff changeset
877 int zero_argument,
a61af66fc99e Initial load
duke
parents:
diff changeset
878 void* null_argument_3);
a61af66fc99e Initial load
duke
parents:
diff changeset
879 #pragma weak collector_func_load
a61af66fc99e Initial load
duke
parents:
diff changeset
880 #define collector_func_load(x0,x1,x2,x3,x4,x5,x6) \
a61af66fc99e Initial load
duke
parents:
diff changeset
881 ( collector_func_load ? collector_func_load(x0,x1,x2,x3,x4,x5,x6),0 : 0 )
a61af66fc99e Initial load
duke
parents:
diff changeset
882 #endif // !_WINDOWS
a61af66fc99e Initial load
duke
parents:
diff changeset
883
a61af66fc99e Initial load
duke
parents:
diff changeset
884 } // end extern "C"
a61af66fc99e Initial load
duke
parents:
diff changeset
885 #endif // !IA64
a61af66fc99e Initial load
duke
parents:
diff changeset
886
a61af66fc99e Initial load
duke
parents:
diff changeset
887 void Forte::register_stub(const char* name, address start, address end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
888 #if !defined(_WINDOWS) && !defined(IA64)
a61af66fc99e Initial load
duke
parents:
diff changeset
889 assert(pointer_delta(end, start, sizeof(jbyte)) < INT_MAX,
a61af66fc99e Initial load
duke
parents:
diff changeset
890 "Code size exceeds maximum range")
a61af66fc99e Initial load
duke
parents:
diff changeset
891
a61af66fc99e Initial load
duke
parents:
diff changeset
892 collector_func_load((char*)name, NULL, NULL, start,
a61af66fc99e Initial load
duke
parents:
diff changeset
893 pointer_delta(end, start, sizeof(jbyte)), 0, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
894 #endif // !_WINDOWS && !IA64
a61af66fc99e Initial load
duke
parents:
diff changeset
895 }