0
|
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 # include "incls/_precompiled.incl"
|
|
26 # include "incls/_vframe.cpp.incl"
|
|
27
|
|
28 vframe::vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
|
|
29 : _reg_map(reg_map), _thread(thread) {
|
|
30 assert(fr != NULL, "must have frame");
|
|
31 _fr = *fr;
|
|
32 }
|
|
33
|
|
34 vframe::vframe(const frame* fr, JavaThread* thread)
|
|
35 : _reg_map(thread), _thread(thread) {
|
|
36 assert(fr != NULL, "must have frame");
|
|
37 _fr = *fr;
|
|
38 }
|
|
39
|
|
40 vframe* vframe::new_vframe(const frame* f, const RegisterMap* reg_map, JavaThread* thread) {
|
|
41 // Interpreter frame
|
|
42 if (f->is_interpreted_frame()) {
|
|
43 return new interpretedVFrame(f, reg_map, thread);
|
|
44 }
|
|
45
|
|
46 // Compiled frame
|
|
47 CodeBlob* cb = f->cb();
|
|
48 if (cb != NULL) {
|
|
49 if (cb->is_nmethod()) {
|
|
50 nmethod* nm = (nmethod*)cb;
|
|
51 return new compiledVFrame(f, reg_map, thread, nm);
|
|
52 }
|
|
53
|
|
54 if (f->is_runtime_frame()) {
|
|
55 // Skip this frame and try again.
|
|
56 RegisterMap temp_map = *reg_map;
|
|
57 frame s = f->sender(&temp_map);
|
|
58 return new_vframe(&s, &temp_map, thread);
|
|
59 }
|
|
60 }
|
|
61
|
|
62 // External frame
|
|
63 return new externalVFrame(f, reg_map, thread);
|
|
64 }
|
|
65
|
|
66 vframe* vframe::sender() const {
|
|
67 RegisterMap temp_map = *register_map();
|
|
68 assert(is_top(), "just checking");
|
|
69 if (_fr.is_entry_frame() && _fr.is_first_frame()) return NULL;
|
|
70 frame s = _fr.real_sender(&temp_map);
|
|
71 if (s.is_first_frame()) return NULL;
|
|
72 return vframe::new_vframe(&s, &temp_map, thread());
|
|
73 }
|
|
74
|
|
75 vframe* vframe::top() const {
|
|
76 vframe* vf = (vframe*) this;
|
|
77 while (!vf->is_top()) vf = vf->sender();
|
|
78 return vf;
|
|
79 }
|
|
80
|
|
81
|
|
82 javaVFrame* vframe::java_sender() const {
|
|
83 vframe* f = sender();
|
|
84 while (f != NULL) {
|
|
85 if (f->is_java_frame()) return javaVFrame::cast(f);
|
|
86 f = f->sender();
|
|
87 }
|
|
88 return NULL;
|
|
89 }
|
|
90
|
|
91 // ------------- javaVFrame --------------
|
|
92
|
|
93 GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() {
|
|
94 assert(SafepointSynchronize::is_at_safepoint() || JavaThread::current() == thread(),
|
|
95 "must be at safepoint or it's a java frame of the current thread");
|
|
96
|
|
97 GrowableArray<MonitorInfo*>* mons = monitors();
|
|
98 GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(mons->length());
|
|
99 if (mons->is_empty()) return result;
|
|
100
|
|
101 bool found_first_monitor = false;
|
|
102 ObjectMonitor *pending_monitor = thread()->current_pending_monitor();
|
|
103 ObjectMonitor *waiting_monitor = thread()->current_waiting_monitor();
|
|
104 oop pending_obj = (pending_monitor != NULL ? (oop) pending_monitor->object() : NULL);
|
|
105 oop waiting_obj = (waiting_monitor != NULL ? (oop) waiting_monitor->object() : NULL);
|
|
106
|
|
107 for (int index = (mons->length()-1); index >= 0; index--) {
|
|
108 MonitorInfo* monitor = mons->at(index);
|
|
109 oop obj = monitor->owner();
|
|
110 if (obj == NULL) continue; // skip unowned monitor
|
|
111 //
|
|
112 // Skip the monitor that the thread is blocked to enter or waiting on
|
|
113 //
|
|
114 if (!found_first_monitor && (obj == pending_obj || obj == waiting_obj)) {
|
|
115 continue;
|
|
116 }
|
|
117 found_first_monitor = true;
|
|
118 result->append(monitor);
|
|
119 }
|
|
120 return result;
|
|
121 }
|
|
122
|
|
123 static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) {
|
|
124 if (obj.not_null()) {
|
|
125 st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj());
|
|
126 if (obj->klass() == SystemDictionary::class_klass()) {
|
|
127 klassOop target_klass = java_lang_Class::as_klassOop(obj());
|
|
128 st->print_cr("(a java.lang.Class for %s)", instanceKlass::cast(target_klass)->external_name());
|
|
129 } else {
|
|
130 Klass* k = Klass::cast(obj->klass());
|
|
131 st->print_cr("(a %s)", k->external_name());
|
|
132 }
|
|
133 }
|
|
134 }
|
|
135
|
|
136 void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
|
|
137 ResourceMark rm;
|
|
138
|
|
139 // If this is the first frame, and java.lang.Object.wait(...) then print out the receiver.
|
|
140 if (frame_count == 0) {
|
|
141 if (method()->name() == vmSymbols::wait_name() &&
|
|
142 instanceKlass::cast(method()->method_holder())->name() == vmSymbols::java_lang_Object()) {
|
|
143 StackValueCollection* locs = locals();
|
|
144 if (!locs->is_empty()) {
|
|
145 StackValue* sv = locs->at(0);
|
|
146 if (sv->type() == T_OBJECT) {
|
|
147 Handle o = locs->at(0)->get_obj();
|
|
148 print_locked_object_class_name(st, o, "waiting on");
|
|
149 }
|
|
150 }
|
|
151 } else if (thread()->current_park_blocker() != NULL) {
|
|
152 oop obj = thread()->current_park_blocker();
|
|
153 Klass* k = Klass::cast(obj->klass());
|
|
154 st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name());
|
|
155 }
|
|
156 }
|
|
157
|
|
158
|
|
159 // Print out all monitors that we have locked or are trying to lock
|
|
160 GrowableArray<MonitorInfo*>* mons = monitors();
|
|
161 if (!mons->is_empty()) {
|
|
162 bool found_first_monitor = false;
|
|
163 for (int index = (mons->length()-1); index >= 0; index--) {
|
|
164 MonitorInfo* monitor = mons->at(index);
|
|
165 if (monitor->owner() != NULL) {
|
|
166
|
|
167 // First, assume we have the monitor locked. If we haven't found an
|
|
168 // owned monitor before and this is the first frame, then we need to
|
|
169 // see if we have completed the lock or we are blocked trying to
|
|
170 // acquire it - we can only be blocked if the monitor is inflated
|
|
171
|
|
172 const char *lock_state = "locked"; // assume we have the monitor locked
|
|
173 if (!found_first_monitor && frame_count == 0) {
|
|
174 markOop mark = monitor->owner()->mark();
|
|
175 if (mark->has_monitor() &&
|
|
176 mark->monitor() == thread()->current_pending_monitor()) {
|
|
177 lock_state = "waiting to lock";
|
|
178 }
|
|
179 }
|
|
180
|
|
181 found_first_monitor = true;
|
|
182 print_locked_object_class_name(st, monitor->owner(), lock_state);
|
|
183 }
|
|
184 }
|
|
185 }
|
|
186 }
|
|
187
|
|
188 // ------------- interpretedVFrame --------------
|
|
189
|
|
190 u_char* interpretedVFrame::bcp() const {
|
|
191 return fr().interpreter_frame_bcp();
|
|
192 }
|
|
193
|
|
194 void interpretedVFrame::set_bcp(u_char* bcp) {
|
|
195 fr().interpreter_frame_set_bcp(bcp);
|
|
196 }
|
|
197
|
|
198 intptr_t* interpretedVFrame::locals_addr_at(int offset) const {
|
|
199 assert(fr().is_interpreted_frame(), "frame should be an interpreted frame");
|
|
200 return fr().interpreter_frame_local_at(offset);
|
|
201 }
|
|
202
|
|
203
|
|
204 GrowableArray<MonitorInfo*>* interpretedVFrame::monitors() const {
|
|
205 GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(5);
|
|
206 for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin()));
|
|
207 current >= fr().interpreter_frame_monitor_end();
|
|
208 current = fr().previous_monitor_in_interpreter_frame(current)) {
|
|
209 result->push(new MonitorInfo(current->obj(), current->lock()));
|
|
210 }
|
|
211 return result;
|
|
212 }
|
|
213
|
|
214 int interpretedVFrame::bci() const {
|
|
215 return method()->bci_from(bcp());
|
|
216 }
|
|
217
|
|
218 methodOop interpretedVFrame::method() const {
|
|
219 return fr().interpreter_frame_method();
|
|
220 }
|
|
221
|
|
222 StackValueCollection* interpretedVFrame::locals() const {
|
|
223 int length = method()->max_locals();
|
|
224
|
|
225 if (method()->is_native()) {
|
|
226 // If the method is native, max_locals is not telling the truth.
|
|
227 // maxlocals then equals the size of parameters
|
|
228 length = method()->size_of_parameters();
|
|
229 }
|
|
230
|
|
231 StackValueCollection* result = new StackValueCollection(length);
|
|
232
|
|
233 // Get oopmap describing oops and int for current bci
|
|
234 if (TaggedStackInterpreter) {
|
|
235 for(int i=0; i < length; i++) {
|
|
236 // Find stack location
|
|
237 intptr_t *addr = locals_addr_at(i);
|
|
238
|
|
239 // Depending on oop/int put it in the right package
|
|
240 StackValue *sv;
|
|
241 frame::Tag tag = fr().interpreter_frame_local_tag(i);
|
|
242 if (tag == frame::TagReference) {
|
|
243 // oop value
|
|
244 Handle h(*(oop *)addr);
|
|
245 sv = new StackValue(h);
|
|
246 } else {
|
|
247 // integer
|
|
248 sv = new StackValue(*addr);
|
|
249 }
|
|
250 assert(sv != NULL, "sanity check");
|
|
251 result->add(sv);
|
|
252 }
|
|
253 } else {
|
|
254 InterpreterOopMap oop_mask;
|
|
255 if (TraceDeoptimization && Verbose) {
|
|
256 methodHandle m_h(thread(), method());
|
|
257 OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
|
|
258 } else {
|
|
259 method()->mask_for(bci(), &oop_mask);
|
|
260 }
|
|
261 // handle locals
|
|
262 for(int i=0; i < length; i++) {
|
|
263 // Find stack location
|
|
264 intptr_t *addr = locals_addr_at(i);
|
|
265
|
|
266 // Depending on oop/int put it in the right package
|
|
267 StackValue *sv;
|
|
268 if (oop_mask.is_oop(i)) {
|
|
269 // oop value
|
|
270 Handle h(*(oop *)addr);
|
|
271 sv = new StackValue(h);
|
|
272 } else {
|
|
273 // integer
|
|
274 sv = new StackValue(*addr);
|
|
275 }
|
|
276 assert(sv != NULL, "sanity check");
|
|
277 result->add(sv);
|
|
278 }
|
|
279 }
|
|
280 return result;
|
|
281 }
|
|
282
|
|
283 void interpretedVFrame::set_locals(StackValueCollection* values) const {
|
|
284 if (values == NULL || values->size() == 0) return;
|
|
285
|
|
286 int length = method()->max_locals();
|
|
287 if (method()->is_native()) {
|
|
288 // If the method is native, max_locals is not telling the truth.
|
|
289 // maxlocals then equals the size of parameters
|
|
290 length = method()->size_of_parameters();
|
|
291 }
|
|
292
|
|
293 assert(length == values->size(), "Mismatch between actual stack format and supplied data");
|
|
294
|
|
295 // handle locals
|
|
296 for (int i = 0; i < length; i++) {
|
|
297 // Find stack location
|
|
298 intptr_t *addr = locals_addr_at(i);
|
|
299
|
|
300 // Depending on oop/int put it in the right package
|
|
301 StackValue *sv = values->at(i);
|
|
302 assert(sv != NULL, "sanity check");
|
|
303 if (sv->type() == T_OBJECT) {
|
|
304 *(oop *) addr = (sv->get_obj())();
|
|
305 } else { // integer
|
|
306 *addr = sv->get_int();
|
|
307 }
|
|
308 }
|
|
309 }
|
|
310
|
|
311 StackValueCollection* interpretedVFrame::expressions() const {
|
|
312 int length = fr().interpreter_frame_expression_stack_size();
|
|
313 if (method()->is_native()) {
|
|
314 // If the method is native, there is no expression stack
|
|
315 length = 0;
|
|
316 }
|
|
317
|
|
318 int nof_locals = method()->max_locals();
|
|
319 StackValueCollection* result = new StackValueCollection(length);
|
|
320
|
|
321 if (TaggedStackInterpreter) {
|
|
322 // handle expressions
|
|
323 for(int i=0; i < length; i++) {
|
|
324 // Find stack location
|
|
325 intptr_t *addr = fr().interpreter_frame_expression_stack_at(i);
|
|
326 frame::Tag tag = fr().interpreter_frame_expression_stack_tag(i);
|
|
327
|
|
328 // Depending on oop/int put it in the right package
|
|
329 StackValue *sv;
|
|
330 if (tag == frame::TagReference) {
|
|
331 // oop value
|
|
332 Handle h(*(oop *)addr);
|
|
333 sv = new StackValue(h);
|
|
334 } else {
|
|
335 // otherwise
|
|
336 sv = new StackValue(*addr);
|
|
337 }
|
|
338 assert(sv != NULL, "sanity check");
|
|
339 result->add(sv);
|
|
340 }
|
|
341 } else {
|
|
342 InterpreterOopMap oop_mask;
|
|
343 // Get oopmap describing oops and int for current bci
|
|
344 if (TraceDeoptimization && Verbose) {
|
|
345 methodHandle m_h(method());
|
|
346 OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask);
|
|
347 } else {
|
|
348 method()->mask_for(bci(), &oop_mask);
|
|
349 }
|
|
350 // handle expressions
|
|
351 for(int i=0; i < length; i++) {
|
|
352 // Find stack location
|
|
353 intptr_t *addr = fr().interpreter_frame_expression_stack_at(i);
|
|
354
|
|
355 // Depending on oop/int put it in the right package
|
|
356 StackValue *sv;
|
|
357 if (oop_mask.is_oop(i + nof_locals)) {
|
|
358 // oop value
|
|
359 Handle h(*(oop *)addr);
|
|
360 sv = new StackValue(h);
|
|
361 } else {
|
|
362 // integer
|
|
363 sv = new StackValue(*addr);
|
|
364 }
|
|
365 assert(sv != NULL, "sanity check");
|
|
366 result->add(sv);
|
|
367 }
|
|
368 }
|
|
369 return result;
|
|
370 }
|
|
371
|
|
372
|
|
373 // ------------- cChunk --------------
|
|
374
|
|
375 entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread)
|
|
376 : externalVFrame(fr, reg_map, thread) {}
|
|
377
|
|
378
|
|
379 void vframeStreamCommon::found_bad_method_frame() {
|
|
380 // 6379830 Cut point for an assertion that occasionally fires when
|
|
381 // we are using the performance analyzer.
|
|
382 // Disable this assert when testing the analyzer with fastdebug.
|
|
383 // -XX:SuppressErrorAt=vframe.cpp:XXX (XXX=following line number)
|
|
384 assert(false, "invalid bci or invalid scope desc");
|
|
385 }
|
|
386
|
|
387 // top-frame will be skipped
|
|
388 vframeStream::vframeStream(JavaThread* thread, frame top_frame,
|
|
389 bool stop_at_java_call_stub) : vframeStreamCommon(thread) {
|
|
390 _stop_at_java_call_stub = stop_at_java_call_stub;
|
|
391
|
|
392 // skip top frame, as it may not be at safepoint
|
|
393 _frame = top_frame.sender(&_reg_map);
|
|
394 while (!fill_from_frame()) {
|
|
395 _frame = _frame.sender(&_reg_map);
|
|
396 }
|
|
397 }
|
|
398
|
|
399
|
|
400 // Step back n frames, skip any pseudo frames in between.
|
|
401 // This function is used in Class.forName, Class.newInstance, Method.Invoke,
|
|
402 // AccessController.doPrivileged.
|
|
403 //
|
|
404 // NOTE that in JDK 1.4 this has been exposed to Java as
|
|
405 // sun.reflect.Reflection.getCallerClass(), which can be inlined.
|
|
406 // Inlined versions must match this routine's logic.
|
|
407 // Native method prefixing logic does not need to match since
|
|
408 // the method names don't match and inlining will not occur.
|
|
409 // See, for example,
|
|
410 // Parse::inline_native_Reflection_getCallerClass in
|
|
411 // opto/library_call.cpp.
|
|
412 void vframeStreamCommon::security_get_caller_frame(int depth) {
|
|
413 bool use_new_reflection = JDK_Version::is_gte_jdk14x_version() && UseNewReflection;
|
|
414
|
|
415 while (!at_end()) {
|
|
416 if (Universe::reflect_invoke_cache()->is_same_method(method())) {
|
|
417 // This is Method.invoke() -- skip it
|
|
418 } else if (use_new_reflection &&
|
|
419 Klass::cast(method()->method_holder())
|
|
420 ->is_subclass_of(SystemDictionary::reflect_method_accessor_klass())) {
|
|
421 // This is an auxilary frame -- skip it
|
|
422 } else {
|
|
423 // This is non-excluded frame, we need to count it against the depth
|
|
424 if (depth-- <= 0) {
|
|
425 // we have reached the desired depth, we are done
|
|
426 break;
|
|
427 }
|
|
428 }
|
|
429 if (method()->is_prefixed_native()) {
|
|
430 skip_prefixed_method_and_wrappers();
|
|
431 } else {
|
|
432 next();
|
|
433 }
|
|
434 }
|
|
435 }
|
|
436
|
|
437
|
|
438 void vframeStreamCommon::skip_prefixed_method_and_wrappers() {
|
|
439 ResourceMark rm;
|
|
440 HandleMark hm;
|
|
441
|
|
442 int method_prefix_count = 0;
|
|
443 char** method_prefixes = JvmtiExport::get_all_native_method_prefixes(&method_prefix_count);
|
|
444 KlassHandle prefixed_klass(method()->method_holder());
|
|
445 const char* prefixed_name = method()->name()->as_C_string();
|
|
446 size_t prefixed_name_len = strlen(prefixed_name);
|
|
447 int prefix_index = method_prefix_count-1;
|
|
448
|
|
449 while (!at_end()) {
|
|
450 next();
|
|
451 if (method()->method_holder() != prefixed_klass()) {
|
|
452 break; // classes don't match, can't be a wrapper
|
|
453 }
|
|
454 const char* name = method()->name()->as_C_string();
|
|
455 size_t name_len = strlen(name);
|
|
456 size_t prefix_len = prefixed_name_len - name_len;
|
|
457 if (prefix_len <= 0 || strcmp(name, prefixed_name + prefix_len) != 0) {
|
|
458 break; // prefixed name isn't prefixed version of method name, can't be a wrapper
|
|
459 }
|
|
460 for (; prefix_index >= 0; --prefix_index) {
|
|
461 const char* possible_prefix = method_prefixes[prefix_index];
|
|
462 size_t possible_prefix_len = strlen(possible_prefix);
|
|
463 if (possible_prefix_len == prefix_len &&
|
|
464 strncmp(possible_prefix, prefixed_name, prefix_len) == 0) {
|
|
465 break; // matching prefix found
|
|
466 }
|
|
467 }
|
|
468 if (prefix_index < 0) {
|
|
469 break; // didn't find the prefix, can't be a wrapper
|
|
470 }
|
|
471 prefixed_name = name;
|
|
472 prefixed_name_len = name_len;
|
|
473 }
|
|
474 }
|
|
475
|
|
476
|
|
477 void vframeStreamCommon::skip_reflection_related_frames() {
|
|
478 while (!at_end() &&
|
|
479 (JDK_Version::is_gte_jdk14x_version() && UseNewReflection &&
|
|
480 (Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_method_accessor_klass()) ||
|
|
481 Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_constructor_accessor_klass())))) {
|
|
482 next();
|
|
483 }
|
|
484 }
|
|
485
|
|
486
|
|
487 #ifndef PRODUCT
|
|
488 void vframe::print() {
|
|
489 if (WizardMode) _fr.print_value_on(tty,NULL);
|
|
490 }
|
|
491
|
|
492
|
|
493 void vframe::print_value() const {
|
|
494 ((vframe*)this)->print();
|
|
495 }
|
|
496
|
|
497
|
|
498 void entryVFrame::print_value() const {
|
|
499 ((entryVFrame*)this)->print();
|
|
500 }
|
|
501
|
|
502 void entryVFrame::print() {
|
|
503 vframe::print();
|
|
504 tty->print_cr("C Chunk inbetween Java");
|
|
505 tty->print_cr("C link " INTPTR_FORMAT, _fr.link());
|
|
506 }
|
|
507
|
|
508
|
|
509 // ------------- javaVFrame --------------
|
|
510
|
|
511 static void print_stack_values(const char* title, StackValueCollection* values) {
|
|
512 if (values->is_empty()) return;
|
|
513 tty->print_cr("\t%s:", title);
|
|
514 values->print();
|
|
515 }
|
|
516
|
|
517
|
|
518 void javaVFrame::print() {
|
|
519 ResourceMark rm;
|
|
520 vframe::print();
|
|
521 tty->print("\t");
|
|
522 method()->print_value();
|
|
523 tty->cr();
|
|
524 tty->print_cr("\tbci: %d", bci());
|
|
525
|
|
526 print_stack_values("locals", locals());
|
|
527 print_stack_values("expressions", expressions());
|
|
528
|
|
529 GrowableArray<MonitorInfo*>* list = monitors();
|
|
530 if (list->is_empty()) return;
|
|
531 tty->print_cr("\tmonitor list:");
|
|
532 for (int index = (list->length()-1); index >= 0; index--) {
|
|
533 MonitorInfo* monitor = list->at(index);
|
|
534 tty->print("\t obj\t"); monitor->owner()->print_value();
|
|
535 tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner());
|
|
536 tty->cr();
|
|
537 tty->print("\t ");
|
|
538 monitor->lock()->print_on(tty);
|
|
539 tty->cr();
|
|
540 }
|
|
541 }
|
|
542
|
|
543
|
|
544 void javaVFrame::print_value() const {
|
|
545 methodOop m = method();
|
|
546 klassOop k = m->method_holder();
|
|
547 tty->print_cr("frame( sp=" INTPTR_FORMAT ", unextended_sp=" INTPTR_FORMAT ", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT ")",
|
|
548 _fr.sp(), _fr.unextended_sp(), _fr.fp(), _fr.pc());
|
|
549 tty->print("%s.%s", Klass::cast(k)->internal_name(), m->name()->as_C_string());
|
|
550
|
|
551 if (!m->is_native()) {
|
|
552 symbolOop source_name = instanceKlass::cast(k)->source_file_name();
|
|
553 int line_number = m->line_number_from_bci(bci());
|
|
554 if (source_name != NULL && (line_number != -1)) {
|
|
555 tty->print("(%s:%d)", source_name->as_C_string(), line_number);
|
|
556 }
|
|
557 } else {
|
|
558 tty->print("(Native Method)");
|
|
559 }
|
|
560 // Check frame size and print warning if it looks suspiciously large
|
|
561 if (fr().sp() != NULL) {
|
|
562 uint size = fr().frame_size();
|
|
563 #ifdef _LP64
|
|
564 if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
|
|
565 #else
|
|
566 if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size);
|
|
567 #endif
|
|
568 }
|
|
569 }
|
|
570
|
|
571
|
|
572 bool javaVFrame::structural_compare(javaVFrame* other) {
|
|
573 // Check static part
|
|
574 if (method() != other->method()) return false;
|
|
575 if (bci() != other->bci()) return false;
|
|
576
|
|
577 // Check locals
|
|
578 StackValueCollection *locs = locals();
|
|
579 StackValueCollection *other_locs = other->locals();
|
|
580 assert(locs->size() == other_locs->size(), "sanity check");
|
|
581 int i;
|
|
582 for(i = 0; i < locs->size(); i++) {
|
|
583 // it might happen the compiler reports a conflict and
|
|
584 // the interpreter reports a bogus int.
|
|
585 if ( is_compiled_frame() && locs->at(i)->type() == T_CONFLICT) continue;
|
|
586 if (other->is_compiled_frame() && other_locs->at(i)->type() == T_CONFLICT) continue;
|
|
587
|
|
588 if (!locs->at(i)->equal(other_locs->at(i)))
|
|
589 return false;
|
|
590 }
|
|
591
|
|
592 // Check expressions
|
|
593 StackValueCollection* exprs = expressions();
|
|
594 StackValueCollection* other_exprs = other->expressions();
|
|
595 assert(exprs->size() == other_exprs->size(), "sanity check");
|
|
596 for(i = 0; i < exprs->size(); i++) {
|
|
597 if (!exprs->at(i)->equal(other_exprs->at(i)))
|
|
598 return false;
|
|
599 }
|
|
600
|
|
601 return true;
|
|
602 }
|
|
603
|
|
604
|
|
605 void javaVFrame::print_activation(int index) const {
|
|
606 // frame number and method
|
|
607 tty->print("%2d - ", index);
|
|
608 ((vframe*)this)->print_value();
|
|
609 tty->cr();
|
|
610
|
|
611 if (WizardMode) {
|
|
612 ((vframe*)this)->print();
|
|
613 tty->cr();
|
|
614 }
|
|
615 }
|
|
616
|
|
617
|
|
618 void javaVFrame::verify() const {
|
|
619 }
|
|
620
|
|
621
|
|
622 void interpretedVFrame::verify() const {
|
|
623 }
|
|
624
|
|
625
|
|
626 // ------------- externalVFrame --------------
|
|
627
|
|
628 void externalVFrame::print() {
|
|
629 _fr.print_value_on(tty,NULL);
|
|
630 }
|
|
631
|
|
632
|
|
633 void externalVFrame::print_value() const {
|
|
634 ((vframe*)this)->print();
|
|
635 }
|
|
636 #endif // PRODUCT
|