Mercurial > hg > graal-jvmci-8
comparison src/share/vm/runtime/vframe.hpp @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | d3cd40645d0d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a61af66fc99e |
---|---|
1 /* | |
2 * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 // vframes are virtual stack frames representing source level activations. | |
26 // A single frame may hold several source level activations in the case of | |
27 // optimized code. The debugging stored with the optimized code enables | |
28 // us to unfold a frame as a stack of vframes. | |
29 // A cVFrame represents an activation of a non-java method. | |
30 | |
31 // The vframe inheritance hierarchy: | |
32 // - vframe | |
33 // - javaVFrame | |
34 // - interpretedVFrame | |
35 // - compiledVFrame ; (used for both compiled Java methods and native stubs) | |
36 // - externalVFrame | |
37 // - entryVFrame ; special frame created when calling Java from C | |
38 | |
39 // - BasicLock | |
40 | |
41 class vframe: public ResourceObj { | |
42 protected: | |
43 frame _fr; // Raw frame behind the virtual frame. | |
44 RegisterMap _reg_map; // Register map for the raw frame (used to handle callee-saved registers). | |
45 JavaThread* _thread; // The thread owning the raw frame. | |
46 | |
47 vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread); | |
48 vframe(const frame* fr, JavaThread* thread); | |
49 public: | |
50 // Factory method for creating vframes | |
51 static vframe* new_vframe(const frame* f, const RegisterMap *reg_map, JavaThread* thread); | |
52 | |
53 // Accessors | |
54 frame fr() const { return _fr; } | |
55 CodeBlob* cb() const { return _fr.cb(); } | |
56 nmethod* nm() const { | |
57 assert( cb() != NULL && cb()->is_nmethod(), "usage"); | |
58 return (nmethod*) cb(); | |
59 } | |
60 | |
61 // ???? Does this need to be a copy? | |
62 frame* frame_pointer() { return &_fr; } | |
63 const RegisterMap* register_map() const { return &_reg_map; } | |
64 JavaThread* thread() const { return _thread; } | |
65 | |
66 // Returns the sender vframe | |
67 virtual vframe* sender() const; | |
68 | |
69 // Returns the next javaVFrame on the stack (skipping all other kinds of frame) | |
70 javaVFrame *java_sender() const; | |
71 | |
72 // Answers if the this is the top vframe in the frame, i.e., if the sender vframe | |
73 // is in the caller frame | |
74 virtual bool is_top() const { return true; } | |
75 | |
76 // Returns top vframe within same frame (see is_top()) | |
77 virtual vframe* top() const; | |
78 | |
79 // Type testing operations | |
80 virtual bool is_entry_frame() const { return false; } | |
81 virtual bool is_java_frame() const { return false; } | |
82 virtual bool is_interpreted_frame() const { return false; } | |
83 virtual bool is_compiled_frame() const { return false; } | |
84 | |
85 #ifndef PRODUCT | |
86 // printing operations | |
87 virtual void print_value() const; | |
88 virtual void print(); | |
89 #endif | |
90 }; | |
91 | |
92 | |
93 class javaVFrame: public vframe { | |
94 public: | |
95 // JVM state | |
96 virtual methodOop method() const = 0; | |
97 virtual int bci() const = 0; | |
98 virtual StackValueCollection* locals() const = 0; | |
99 virtual StackValueCollection* expressions() const = 0; | |
100 // the order returned by monitors() is from oldest -> youngest#4418568 | |
101 virtual GrowableArray<MonitorInfo*>* monitors() const = 0; | |
102 | |
103 // Debugging support via JVMTI. | |
104 // NOTE that this is not guaranteed to give correct results for compiled vframes. | |
105 // Deoptimize first if necessary. | |
106 virtual void set_locals(StackValueCollection* values) const = 0; | |
107 | |
108 // Test operation | |
109 bool is_java_frame() const { return true; } | |
110 | |
111 protected: | |
112 javaVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {} | |
113 javaVFrame(const frame* fr, JavaThread* thread) : vframe(fr, thread) {} | |
114 | |
115 public: | |
116 // casting | |
117 static javaVFrame* cast(vframe* vf) { | |
118 assert(vf == NULL || vf->is_java_frame(), "must be java frame"); | |
119 return (javaVFrame*) vf; | |
120 } | |
121 | |
122 // Return an array of monitors locked by this frame in the youngest to oldest order | |
123 GrowableArray<MonitorInfo*>* locked_monitors(); | |
124 | |
125 // printing used during stack dumps | |
126 void print_lock_info_on(outputStream* st, int frame_count); | |
127 void print_lock_info(int frame_count) { print_lock_info_on(tty, frame_count); } | |
128 | |
129 #ifndef PRODUCT | |
130 public: | |
131 // printing operations | |
132 void print(); | |
133 void print_value() const; | |
134 void print_activation(int index) const; | |
135 | |
136 // verify operations | |
137 virtual void verify() const; | |
138 | |
139 // Structural compare | |
140 bool structural_compare(javaVFrame* other); | |
141 #endif | |
142 friend class vframe; | |
143 }; | |
144 | |
145 class interpretedVFrame: public javaVFrame { | |
146 public: | |
147 // JVM state | |
148 methodOop method() const; | |
149 int bci() const; | |
150 StackValueCollection* locals() const; | |
151 StackValueCollection* expressions() const; | |
152 GrowableArray<MonitorInfo*>* monitors() const; | |
153 | |
154 void set_locals(StackValueCollection* values) const; | |
155 | |
156 // Test operation | |
157 bool is_interpreted_frame() const { return true; } | |
158 | |
159 protected: | |
160 interpretedVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : javaVFrame(fr, reg_map, thread) {}; | |
161 | |
162 public: | |
163 // Accessors for Byte Code Pointer | |
164 u_char* bcp() const; | |
165 void set_bcp(u_char* bcp); | |
166 | |
167 // casting | |
168 static interpretedVFrame* cast(vframe* vf) { | |
169 assert(vf == NULL || vf->is_interpreted_frame(), "must be interpreted frame"); | |
170 return (interpretedVFrame*) vf; | |
171 } | |
172 | |
173 private: | |
174 static const int bcp_offset; | |
175 intptr_t* locals_addr_at(int offset) const; | |
176 | |
177 // returns where the parameters starts relative to the frame pointer | |
178 int start_of_parameters() const; | |
179 | |
180 #ifndef PRODUCT | |
181 public: | |
182 // verify operations | |
183 void verify() const; | |
184 #endif | |
185 friend class vframe; | |
186 }; | |
187 | |
188 | |
189 class externalVFrame: public vframe { | |
190 protected: | |
191 externalVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {} | |
192 | |
193 #ifndef PRODUCT | |
194 public: | |
195 // printing operations | |
196 void print_value() const; | |
197 void print(); | |
198 #endif | |
199 friend class vframe; | |
200 }; | |
201 | |
202 class entryVFrame: public externalVFrame { | |
203 public: | |
204 bool is_entry_frame() const { return true; } | |
205 | |
206 protected: | |
207 entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread); | |
208 | |
209 public: | |
210 // casting | |
211 static entryVFrame* cast(vframe* vf) { | |
212 assert(vf == NULL || vf->is_entry_frame(), "must be entry frame"); | |
213 return (entryVFrame*) vf; | |
214 } | |
215 | |
216 #ifndef PRODUCT | |
217 public: | |
218 // printing | |
219 void print_value() const; | |
220 void print(); | |
221 #endif | |
222 friend class vframe; | |
223 }; | |
224 | |
225 | |
226 // A MonitorInfo is a ResourceObject that describes a the pair: | |
227 // 1) the owner of the monitor | |
228 // 2) the monitor lock | |
229 class MonitorInfo : public ResourceObj { | |
230 private: | |
231 oop _owner; // the object owning the monitor | |
232 BasicLock* _lock; | |
233 public: | |
234 // Constructor | |
235 MonitorInfo(oop owner, BasicLock* lock) { | |
236 _owner = owner; | |
237 _lock = lock; | |
238 } | |
239 // Accessors | |
240 oop owner() const { return _owner; } | |
241 BasicLock* lock() const { return _lock; } | |
242 }; | |
243 | |
244 class vframeStreamCommon : StackObj { | |
245 protected: | |
246 // common | |
247 frame _frame; | |
248 JavaThread* _thread; | |
249 RegisterMap _reg_map; | |
250 enum { interpreted_mode, compiled_mode, at_end_mode } _mode; | |
251 | |
252 int _sender_decode_offset; | |
253 | |
254 // Cached information | |
255 methodOop _method; | |
256 int _bci; | |
257 | |
258 // Should VM activations be ignored or not | |
259 bool _stop_at_java_call_stub; | |
260 | |
261 bool fill_in_compiled_inlined_sender(); | |
262 void fill_from_compiled_frame(int decode_offset); | |
263 void fill_from_compiled_native_frame(); | |
264 | |
265 void found_bad_method_frame(); | |
266 | |
267 void fill_from_interpreter_frame(); | |
268 bool fill_from_frame(); | |
269 | |
270 // Helper routine for security_get_caller_frame | |
271 void skip_prefixed_method_and_wrappers(); | |
272 | |
273 public: | |
274 // Constructor | |
275 vframeStreamCommon(JavaThread* thread) : _reg_map(thread, false) { | |
276 _thread = thread; | |
277 } | |
278 | |
279 // Accessors | |
280 methodOop method() const { return _method; } | |
281 int bci() const { return _bci; } | |
282 intptr_t* frame_id() const { return _frame.id(); } | |
283 address frame_pc() const { return _frame.pc(); } | |
284 | |
285 CodeBlob* cb() const { return _frame.cb(); } | |
286 nmethod* nm() const { | |
287 assert( cb() != NULL && cb()->is_nmethod(), "usage"); | |
288 return (nmethod*) cb(); | |
289 } | |
290 | |
291 // Frame type | |
292 bool is_interpreted_frame() const { return _frame.is_interpreted_frame(); } | |
293 bool is_entry_frame() const { return _frame.is_entry_frame(); } | |
294 | |
295 // Iteration | |
296 void next() { | |
297 // handle frames with inlining | |
298 if (_mode == compiled_mode && fill_in_compiled_inlined_sender()) return; | |
299 | |
300 // handle general case | |
301 do { | |
302 _frame = _frame.sender(&_reg_map); | |
303 } while (!fill_from_frame()); | |
304 } | |
305 | |
306 bool at_end() const { return _mode == at_end_mode; } | |
307 | |
308 // Implements security traversal. Skips depth no. of frame including | |
309 // special security frames and prefixed native methods | |
310 void security_get_caller_frame(int depth); | |
311 | |
312 // Helper routine for JVM_LatestUserDefinedLoader -- needed for 1.4 | |
313 // reflection implementation | |
314 void skip_reflection_related_frames(); | |
315 }; | |
316 | |
317 class vframeStream : public vframeStreamCommon { | |
318 public: | |
319 // Constructors | |
320 vframeStream(JavaThread* thread, bool stop_at_java_call_stub = false) | |
321 : vframeStreamCommon(thread) { | |
322 _stop_at_java_call_stub = stop_at_java_call_stub; | |
323 | |
324 if (!thread->has_last_Java_frame()) { | |
325 _mode = at_end_mode; | |
326 return; | |
327 } | |
328 | |
329 _frame = _thread->last_frame(); | |
330 while (!fill_from_frame()) { | |
331 _frame = _frame.sender(&_reg_map); | |
332 } | |
333 } | |
334 | |
335 // top_frame may not be at safepoint, start with sender | |
336 vframeStream(JavaThread* thread, frame top_frame, bool stop_at_java_call_stub = false); | |
337 }; | |
338 | |
339 | |
340 inline bool vframeStreamCommon::fill_in_compiled_inlined_sender() { | |
341 if (_sender_decode_offset == DebugInformationRecorder::serialized_null) { | |
342 return false; | |
343 } | |
344 fill_from_compiled_frame(_sender_decode_offset); | |
345 return true; | |
346 } | |
347 | |
348 | |
349 inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) { | |
350 _mode = compiled_mode; | |
351 | |
352 // Range check to detect ridiculous offsets. | |
353 if (decode_offset == DebugInformationRecorder::serialized_null || | |
354 decode_offset < 0 || | |
355 decode_offset >= nm()->scopes_data_size()) { | |
356 // 6379830 AsyncGetCallTrace sometimes feeds us wild frames. | |
357 // If we attempt to read nmethod::scopes_data at serialized_null (== 0), | |
358 // or if we read some at other crazy offset, | |
359 // we will decode garbage and make wild references into the heap, | |
360 // leading to crashes in product mode. | |
361 // (This isn't airtight, of course, since there are internal | |
362 // offsets which are also crazy.) | |
363 #ifdef ASSERT | |
364 if (WizardMode) { | |
365 tty->print_cr("Error in fill_from_frame: pc_desc for " | |
366 INTPTR_FORMAT " not found or invalid at %d", | |
367 _frame.pc(), decode_offset); | |
368 nm()->print(); | |
369 nm()->method()->print_codes(); | |
370 nm()->print_code(); | |
371 nm()->print_pcs(); | |
372 } | |
373 #endif | |
374 // Provide a cheap fallback in product mode. (See comment above.) | |
375 found_bad_method_frame(); | |
376 fill_from_compiled_native_frame(); | |
377 return; | |
378 } | |
379 | |
380 // Decode first part of scopeDesc | |
381 DebugInfoReadStream buffer(nm(), decode_offset); | |
382 _sender_decode_offset = buffer.read_int(); | |
383 _method = methodOop(buffer.read_oop()); | |
384 _bci = buffer.read_bci(); | |
385 | |
386 assert(_method->is_method(), "checking type of decoded method"); | |
387 } | |
388 | |
389 // The native frames are handled specially. We do not rely on ScopeDesc info | |
390 // since the pc might not be exact due to the _last_native_pc trick. | |
391 inline void vframeStreamCommon::fill_from_compiled_native_frame() { | |
392 _mode = compiled_mode; | |
393 _sender_decode_offset = DebugInformationRecorder::serialized_null; | |
394 _method = nm()->method(); | |
395 _bci = 0; | |
396 } | |
397 | |
398 inline bool vframeStreamCommon::fill_from_frame() { | |
399 // Interpreted frame | |
400 if (_frame.is_interpreted_frame()) { | |
401 fill_from_interpreter_frame(); | |
402 return true; | |
403 } | |
404 | |
405 // Compiled frame | |
406 | |
407 if (cb() != NULL && cb()->is_nmethod()) { | |
408 if (nm()->is_native_method()) { | |
409 // Do not rely on scopeDesc since the pc might be unprecise due to the _last_native_pc trick. | |
410 fill_from_compiled_native_frame(); | |
411 } else { | |
412 PcDesc* pc_desc = nm()->pc_desc_at(_frame.pc()); | |
413 int decode_offset; | |
414 if (pc_desc == NULL) { | |
415 // Should not happen, but let fill_from_compiled_frame handle it. | |
416 decode_offset = DebugInformationRecorder::serialized_null; | |
417 } else { | |
418 decode_offset = pc_desc->scope_decode_offset(); | |
419 } | |
420 fill_from_compiled_frame(decode_offset); | |
421 } | |
422 return true; | |
423 } | |
424 | |
425 // End of stack? | |
426 if (_frame.is_first_frame() || (_stop_at_java_call_stub && _frame.is_entry_frame())) { | |
427 _mode = at_end_mode; | |
428 return true; | |
429 } | |
430 | |
431 return false; | |
432 } | |
433 | |
434 | |
435 inline void vframeStreamCommon::fill_from_interpreter_frame() { | |
436 methodOop method = _frame.interpreter_frame_method(); | |
437 intptr_t bcx = _frame.interpreter_frame_bcx(); | |
438 int bci = method->validate_bci_from_bcx(bcx); | |
439 // 6379830 AsyncGetCallTrace sometimes feeds us wild frames. | |
440 if (bci < 0) { | |
441 found_bad_method_frame(); | |
442 bci = 0; // pretend it's on the point of entering | |
443 } | |
444 _mode = interpreted_mode; | |
445 _method = method; | |
446 _bci = bci; | |
447 } |