vframe.cpp revision 1472:c18cbe5936b8
11539Srgrimes/* 21539Srgrimes * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 31539Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41539Srgrimes * 51539Srgrimes * This code is free software; you can redistribute it and/or modify it 61539Srgrimes * under the terms of the GNU General Public License version 2 only, as 71539Srgrimes * published by the Free Software Foundation. 81539Srgrimes * 91539Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT 101539Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 111539Srgrimes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 121539Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 13203964Simp * accompanied this code). 141539Srgrimes * 151539Srgrimes * You should have received a copy of the GNU General Public License version 161539Srgrimes * 2 along with this work; if not, write to the Free Software Foundation, 171539Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 181539Srgrimes * 191539Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 201539Srgrimes * or visit www.oracle.com if you need additional information or have any 211539Srgrimes * questions. 221539Srgrimes * 231539Srgrimes */ 241539Srgrimes 251539Srgrimes# include "incls/_precompiled.incl" 261539Srgrimes# include "incls/_vframe.cpp.incl" 271539Srgrimes 281539Srgrimesvframe::vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) 2923657Speter: _reg_map(reg_map), _thread(thread) { 3055031Sbde assert(fr != NULL, "must have frame"); 311539Srgrimes _fr = *fr; 321539Srgrimes} 331539Srgrimes 347865Sbdevframe::vframe(const frame* fr, JavaThread* thread) 351539Srgrimes: _reg_map(thread), _thread(thread) { 3633861Sbde assert(fr != NULL, "must have frame"); 37123257Smarcel _fr = *fr; 38102227Smike} 3933861Sbde 40103728Swollmanvframe* vframe::new_vframe(const frame* f, const RegisterMap* reg_map, JavaThread* thread) { 41102227Smike // Interpreter frame 42102227Smike if (f->is_interpreted_frame()) { 43102227Smike return new interpretedVFrame(f, reg_map, thread); 4415483Sbde } 4515483Sbde 4615483Sbde // Compiled frame 47102227Smike CodeBlob* cb = f->cb(); 48102227Smike if (cb != NULL) { 49102227Smike if (cb->is_nmethod()) { 501539Srgrimes nmethod* nm = (nmethod*)cb; 511539Srgrimes return new compiledVFrame(f, reg_map, thread, nm); 5299640Sobrien } 53102227Smike 54102227Smike if (f->is_runtime_frame()) { 55102227Smike // Skip this frame and try again. 561539Srgrimes RegisterMap temp_map = *reg_map; 5799640Sobrien frame s = f->sender(&temp_map); 581539Srgrimes return new_vframe(&s, &temp_map, thread); 591539Srgrimes } 60103766Sbde } 61103766Sbde 621539Srgrimes // External frame 631539Srgrimes return new externalVFrame(f, reg_map, thread); 641539Srgrimes} 65103766Sbde 66103766Sbdevframe* vframe::sender() const { 671539Srgrimes RegisterMap temp_map = *register_map(); 681539Srgrimes assert(is_top(), "just checking"); 691539Srgrimes if (_fr.is_entry_frame() && _fr.is_first_frame()) return NULL; 701539Srgrimes frame s = _fr.real_sender(&temp_map); 711539Srgrimes if (s.is_first_frame()) return NULL; 721539Srgrimes return vframe::new_vframe(&s, &temp_map, thread()); 731539Srgrimes} 741539Srgrimes 751539Srgrimesvframe* vframe::top() const { 761539Srgrimes vframe* vf = (vframe*) this; 771539Srgrimes while (!vf->is_top()) vf = vf->sender(); 7893032Simp return vf; 7993032Simp} 8093032Simp 8193032Simp 8293032SimpjavaVFrame* vframe::java_sender() const { 8393032Simp vframe* f = sender(); 8493032Simp while (f != NULL) { 8593032Simp if (f->is_java_frame()) return javaVFrame::cast(f); 86187961Sdas f = f->sender(); 8793032Simp } 8893032Simp return NULL; 8993032Simp} 9093032Simp 9193032Simp// ------------- javaVFrame -------------- 9293032Simp 93187961SdasGrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() { 94103728Swollman assert(SafepointSynchronize::is_at_safepoint() || JavaThread::current() == thread(), 95103766Sbde "must be at safepoint or it's a java frame of the current thread"); 96103728Swollman 9793032Simp GrowableArray<MonitorInfo*>* mons = monitors(); 9893032Simp GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(mons->length()); 9993032Simp if (mons->is_empty()) return result; 10093032Simp 10193032Simp bool found_first_monitor = false; 102103766Sbde ObjectMonitor *pending_monitor = thread()->current_pending_monitor(); 103112163Sdas ObjectMonitor *waiting_monitor = thread()->current_waiting_monitor(); 104103766Sbde oop pending_obj = (pending_monitor != NULL ? (oop) pending_monitor->object() : (oop) NULL); 105112163Sdas oop waiting_obj = (waiting_monitor != NULL ? (oop) waiting_monitor->object() : (oop) NULL); 106112163Sdas 1071539Srgrimes for (int index = (mons->length()-1); index >= 0; index--) { 108103012Stjr MonitorInfo* monitor = mons->at(index); 10993032Simp if (monitor->eliminated() && is_compiled_frame()) continue; // skip eliminated monitor 11093032Simp oop obj = monitor->owner(); 111103012Stjr if (obj == NULL) continue; // skip unowned monitor 1121539Srgrimes // 113103728Swollman // Skip the monitor that the thread is blocked to enter or waiting on 114103728Swollman // 115103728Swollman if (!found_first_monitor && (obj == pending_obj || obj == waiting_obj)) { 116103728Swollman continue; 117103728Swollman } 118103728Swollman found_first_monitor = true; 119103728Swollman result->append(monitor); 120103728Swollman } 121103728Swollman return result; 122103728Swollman} 123103728Swollman 124103728Swollmanstatic void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) { 125103728Swollman if (obj.not_null()) { 126103728Swollman st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj()); 127103728Swollman if (obj->klass() == SystemDictionary::Class_klass()) { 128103728Swollman klassOop target_klass = java_lang_Class::as_klassOop(obj()); 129103728Swollman st->print_cr("(a java.lang.Class for %s)", instanceKlass::cast(target_klass)->external_name()); 13069201Sphk } else { 131103728Swollman Klass* k = Klass::cast(obj->klass()); 132103728Swollman st->print_cr("(a %s)", k->external_name()); 133103728Swollman } 134103728Swollman } 135103728Swollman} 136103728Swollman 137103728Swollmanvoid javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { 138103728Swollman ResourceMark rm; 139103728Swollman 140103766Sbde // If this is the first frame, and java.lang.Object.wait(...) then print out the receiver. 141103766Sbde if (frame_count == 0) { 142103728Swollman if (method()->name() == vmSymbols::wait_name() && 143103728Swollman instanceKlass::cast(method()->method_holder())->name() == vmSymbols::java_lang_Object()) { 144103766Sbde StackValueCollection* locs = locals(); 145103728Swollman if (!locs->is_empty()) { 146103728Swollman StackValue* sv = locs->at(0); 147103766Sbde if (sv->type() == T_OBJECT) { 148103728Swollman Handle o = locs->at(0)->get_obj(); 149103728Swollman print_locked_object_class_name(st, o, "waiting on"); 150103728Swollman } 151103728Swollman } 152103728Swollman } else if (thread()->current_park_blocker() != NULL) { 153103728Swollman oop obj = thread()->current_park_blocker(); 154103728Swollman Klass* k = Klass::cast(obj->klass()); 155103728Swollman st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name()); 156154250Sjasone } 157103728Swollman } 15893032Simp 159171195Sscf 160103728Swollman // Print out all monitors that we have locked or are trying to lock 1611539Srgrimes GrowableArray<MonitorInfo*>* mons = monitors(); 162189349Sdas if (!mons->is_empty()) { 163189349Sdas bool found_first_monitor = false; 164189349Sdas for (int index = (mons->length()-1); index >= 0; index--) { 165189349Sdas MonitorInfo* monitor = mons->at(index); 166189349Sdas if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code 167189349Sdas if (monitor->owner_is_scalar_replaced()) { 168189349Sdas Klass* k = Klass::cast(monitor->owner_klass()); 169189349Sdas st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name()); 170189349Sdas } else { 171189349Sdas oop obj = monitor->owner(); 172189349Sdas if (obj != NULL) { 173189349Sdas print_locked_object_class_name(st, obj, "eliminated"); 174103728Swollman } 175103728Swollman } 176103728Swollman continue; 177103728Swollman } 178103728Swollman if (monitor->owner() != NULL) { 179103728Swollman 180103728Swollman // First, assume we have the monitor locked. If we haven't found an 181103728Swollman // owned monitor before and this is the first frame, then we need to 182153707Strhodes // see if we have completed the lock or we are blocked trying to 18393032Simp // acquire it - we can only be blocked if the monitor is inflated 184103766Sbde 18593032Simp const char *lock_state = "locked"; // assume we have the monitor locked 186103766Sbde if (!found_first_monitor && frame_count == 0) { 187103766Sbde markOop mark = monitor->owner()->mark(); 188108574Sjmallett if (mark->has_monitor() && 189103728Swollman mark->monitor() == thread()->current_pending_monitor()) { 19093032Simp lock_state = "waiting to lock"; 191153707Strhodes } 19293032Simp } 19393032Simp 194189782Sdas found_first_monitor = true; 195103728Swollman print_locked_object_class_name(st, monitor->owner(), lock_state); 196103766Sbde } 197103728Swollman } 19893032Simp } 19993032Simp} 200108574Sjmallett 201108574Sjmallett// ------------- interpretedVFrame -------------- 202171195Sscf 203103728Swollmanu_char* interpretedVFrame::bcp() const { 204103728Swollman return fr().interpreter_frame_bcp(); 2057865Sbde} 20693032Simp 207103728Swollmanvoid interpretedVFrame::set_bcp(u_char* bcp) { 208103728Swollman fr().interpreter_frame_set_bcp(bcp); 209103728Swollman} 210103728Swollman 211103728Swollmanintptr_t* interpretedVFrame::locals_addr_at(int offset) const { 21293032Simp assert(fr().is_interpreted_frame(), "frame should be an interpreted frame"); 213103728Swollman return fr().interpreter_frame_local_at(offset); 214108574Sjmallett} 215103728Swollman 2164749Sats 217103728SwollmanGrowableArray<MonitorInfo*>* interpretedVFrame::monitors() const { 218103728Swollman GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(5); 219103766Sbde for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin())); 220103766Sbde current >= fr().interpreter_frame_monitor_end(); 221103728Swollman current = fr().previous_monitor_in_interpreter_frame(current)) { 222116397Sdes result->push(new MonitorInfo(current->obj(), current->lock(), false, false)); 223116397Sdes } 224116397Sdes return result; 225116397Sdes} 226116397Sdes 227116397Sdesint interpretedVFrame::bci() const { 228116397Sdes return method()->bci_from(bcp()); 229116397Sdes} 230116397Sdes 231116831SobrienmethodOop interpretedVFrame::method() const { 232116831Sobrien return fr().interpreter_frame_method(); 233116397Sdes} 234116831Sobrien 235116831SobrienStackValueCollection* interpretedVFrame::locals() const { 236116397Sdes int length = method()->max_locals(); 237116397Sdes 238189820Sdas if (method()->is_native()) { 23941927Sdt // If the method is native, max_locals is not telling the truth. 24093032Simp // maxlocals then equals the size of parameters 241180658Sache length = method()->size_of_parameters(); 242180658Sache } 24393032Simp 244180689Sache StackValueCollection* result = new StackValueCollection(length); 245180689Sache 246108445Sobrien // Get oopmap describing oops and int for current bci 247103728Swollman InterpreterOopMap oop_mask; 24893032Simp if (TraceDeoptimization && Verbose) { 24993032Simp methodHandle m_h(thread(), method()); 25093032Simp OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); 25193032Simp } else { 25293032Simp method()->mask_for(bci(), &oop_mask); 25393032Simp } 25493032Simp // handle locals 25593032Simp for(int i=0; i < length; i++) { 25693032Simp // Find stack location 25793032Simp intptr_t *addr = locals_addr_at(i); 2581539Srgrimes 25993032Simp // Depending on oop/int put it in the right package 260150052Sstefanf StackValue *sv; 261150052Sstefanf if (oop_mask.is_oop(i)) { 262188497Sed // oop value 263188497Sed Handle h(*(oop *)addr); 26493032Simp sv = new StackValue(h); 26588399Smike } else { 26693032Simp // integer 2671539Srgrimes sv = new StackValue(*addr); 26893032Simp } 269153707Strhodes assert(sv != NULL, "sanity check"); 27093032Simp result->add(sv); 271103164Swollman } 272103164Swollman return result; 27393032Simp} 27493032Simp 27593032Simpvoid interpretedVFrame::set_locals(StackValueCollection* values) const { 276139922Stjr if (values == NULL || values->size() == 0) return; 27793032Simp 278103164Swollman int length = method()->max_locals(); 279103164Swollman if (method()->is_native()) { 28093032Simp // If the method is native, max_locals is not telling the truth. 28193032Simp // maxlocals then equals the size of parameters 282156707Sandre length = method()->size_of_parameters(); 283156707Sandre } 284103728Swollman 285103728Swollman assert(length == values->size(), "Mismatch between actual stack format and supplied data"); 286103766Sbde 287103766Sbde // handle locals 28841927Sdt for (int i = 0; i < length; i++) { 28993032Simp // Find stack location 290126136Sache intptr_t *addr = locals_addr_at(i); 291126136Sache 292103728Swollman // Depending on oop/int put it in the right package 2931539Srgrimes StackValue *sv = values->at(i); 2941539Srgrimes assert(sv != NULL, "sanity check"); 2957865Sbde if (sv->type() == T_OBJECT) { 296 *(oop *) addr = (sv->get_obj())(); 297 } else { // integer 298 *addr = sv->get_int(); 299 } 300 } 301} 302 303StackValueCollection* interpretedVFrame::expressions() const { 304 int length = fr().interpreter_frame_expression_stack_size(); 305 if (method()->is_native()) { 306 // If the method is native, there is no expression stack 307 length = 0; 308 } 309 310 int nof_locals = method()->max_locals(); 311 StackValueCollection* result = new StackValueCollection(length); 312 313 InterpreterOopMap oop_mask; 314 // Get oopmap describing oops and int for current bci 315 if (TraceDeoptimization && Verbose) { 316 methodHandle m_h(method()); 317 OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); 318 } else { 319 method()->mask_for(bci(), &oop_mask); 320 } 321 // handle expressions 322 for(int i=0; i < length; i++) { 323 // Find stack location 324 intptr_t *addr = fr().interpreter_frame_expression_stack_at(i); 325 326 // Depending on oop/int put it in the right package 327 StackValue *sv; 328 if (oop_mask.is_oop(i + nof_locals)) { 329 // oop value 330 Handle h(*(oop *)addr); 331 sv = new StackValue(h); 332 } else { 333 // integer 334 sv = new StackValue(*addr); 335 } 336 assert(sv != NULL, "sanity check"); 337 result->add(sv); 338 } 339 return result; 340} 341 342 343// ------------- cChunk -------------- 344 345entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) 346: externalVFrame(fr, reg_map, thread) {} 347 348 349void vframeStreamCommon::found_bad_method_frame() { 350 // 6379830 Cut point for an assertion that occasionally fires when 351 // we are using the performance analyzer. 352 // Disable this assert when testing the analyzer with fastdebug. 353 // -XX:SuppressErrorAt=vframe.cpp:XXX (XXX=following line number) 354 assert(false, "invalid bci or invalid scope desc"); 355} 356 357// top-frame will be skipped 358vframeStream::vframeStream(JavaThread* thread, frame top_frame, 359 bool stop_at_java_call_stub) : vframeStreamCommon(thread) { 360 _stop_at_java_call_stub = stop_at_java_call_stub; 361 362 // skip top frame, as it may not be at safepoint 363 _frame = top_frame.sender(&_reg_map); 364 while (!fill_from_frame()) { 365 _frame = _frame.sender(&_reg_map); 366 } 367} 368 369 370// Step back n frames, skip any pseudo frames in between. 371// This function is used in Class.forName, Class.newInstance, Method.Invoke, 372// AccessController.doPrivileged. 373// 374// NOTE that in JDK 1.4 this has been exposed to Java as 375// sun.reflect.Reflection.getCallerClass(), which can be inlined. 376// Inlined versions must match this routine's logic. 377// Native method prefixing logic does not need to match since 378// the method names don't match and inlining will not occur. 379// See, for example, 380// Parse::inline_native_Reflection_getCallerClass in 381// opto/library_call.cpp. 382void vframeStreamCommon::security_get_caller_frame(int depth) { 383 bool use_new_reflection = JDK_Version::is_gte_jdk14x_version() && UseNewReflection; 384 385 while (!at_end()) { 386 if (Universe::reflect_invoke_cache()->is_same_method(method())) { 387 // This is Method.invoke() -- skip it 388 } else if (use_new_reflection && 389 Klass::cast(method()->method_holder()) 390 ->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass())) { 391 // This is an auxilary frame -- skip it 392 } else if (method()->is_method_handle_adapter()) { 393 // This is an internal adapter frame from the MethodHandleCompiler -- skip it 394 } else { 395 // This is non-excluded frame, we need to count it against the depth 396 if (depth-- <= 0) { 397 // we have reached the desired depth, we are done 398 break; 399 } 400 } 401 if (method()->is_prefixed_native()) { 402 skip_prefixed_method_and_wrappers(); 403 } else { 404 next(); 405 } 406 } 407} 408 409 410void vframeStreamCommon::skip_prefixed_method_and_wrappers() { 411 ResourceMark rm; 412 HandleMark hm; 413 414 int method_prefix_count = 0; 415 char** method_prefixes = JvmtiExport::get_all_native_method_prefixes(&method_prefix_count); 416 KlassHandle prefixed_klass(method()->method_holder()); 417 const char* prefixed_name = method()->name()->as_C_string(); 418 size_t prefixed_name_len = strlen(prefixed_name); 419 int prefix_index = method_prefix_count-1; 420 421 while (!at_end()) { 422 next(); 423 if (method()->method_holder() != prefixed_klass()) { 424 break; // classes don't match, can't be a wrapper 425 } 426 const char* name = method()->name()->as_C_string(); 427 size_t name_len = strlen(name); 428 size_t prefix_len = prefixed_name_len - name_len; 429 if (prefix_len <= 0 || strcmp(name, prefixed_name + prefix_len) != 0) { 430 break; // prefixed name isn't prefixed version of method name, can't be a wrapper 431 } 432 for (; prefix_index >= 0; --prefix_index) { 433 const char* possible_prefix = method_prefixes[prefix_index]; 434 size_t possible_prefix_len = strlen(possible_prefix); 435 if (possible_prefix_len == prefix_len && 436 strncmp(possible_prefix, prefixed_name, prefix_len) == 0) { 437 break; // matching prefix found 438 } 439 } 440 if (prefix_index < 0) { 441 break; // didn't find the prefix, can't be a wrapper 442 } 443 prefixed_name = name; 444 prefixed_name_len = name_len; 445 } 446} 447 448 449void vframeStreamCommon::skip_reflection_related_frames() { 450 while (!at_end() && 451 (JDK_Version::is_gte_jdk14x_version() && UseNewReflection && 452 (Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) || 453 Klass::cast(method()->method_holder())->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass())))) { 454 next(); 455 } 456} 457 458 459#ifndef PRODUCT 460void vframe::print() { 461 if (WizardMode) _fr.print_value_on(tty,NULL); 462} 463 464 465void vframe::print_value() const { 466 ((vframe*)this)->print(); 467} 468 469 470void entryVFrame::print_value() const { 471 ((entryVFrame*)this)->print(); 472} 473 474void entryVFrame::print() { 475 vframe::print(); 476 tty->print_cr("C Chunk inbetween Java"); 477 tty->print_cr("C link " INTPTR_FORMAT, _fr.link()); 478} 479 480 481// ------------- javaVFrame -------------- 482 483static void print_stack_values(const char* title, StackValueCollection* values) { 484 if (values->is_empty()) return; 485 tty->print_cr("\t%s:", title); 486 values->print(); 487} 488 489 490void javaVFrame::print() { 491 ResourceMark rm; 492 vframe::print(); 493 tty->print("\t"); 494 method()->print_value(); 495 tty->cr(); 496 tty->print_cr("\tbci: %d", bci()); 497 498 print_stack_values("locals", locals()); 499 print_stack_values("expressions", expressions()); 500 501 GrowableArray<MonitorInfo*>* list = monitors(); 502 if (list->is_empty()) return; 503 tty->print_cr("\tmonitor list:"); 504 for (int index = (list->length()-1); index >= 0; index--) { 505 MonitorInfo* monitor = list->at(index); 506 tty->print("\t obj\t"); 507 if (monitor->owner_is_scalar_replaced()) { 508 Klass* k = Klass::cast(monitor->owner_klass()); 509 tty->print("( is scalar replaced %s)", k->external_name()); 510 } else if (monitor->owner() == NULL) { 511 tty->print("( null )"); 512 } else { 513 monitor->owner()->print_value(); 514 tty->print("(" INTPTR_FORMAT ")", (address)monitor->owner()); 515 } 516 if (monitor->eliminated() && is_compiled_frame()) 517 tty->print(" ( lock is eliminated )"); 518 tty->cr(); 519 tty->print("\t "); 520 monitor->lock()->print_on(tty); 521 tty->cr(); 522 } 523} 524 525 526void javaVFrame::print_value() const { 527 methodOop m = method(); 528 klassOop k = m->method_holder(); 529 tty->print_cr("frame( sp=" INTPTR_FORMAT ", unextended_sp=" INTPTR_FORMAT ", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT ")", 530 _fr.sp(), _fr.unextended_sp(), _fr.fp(), _fr.pc()); 531 tty->print("%s.%s", Klass::cast(k)->internal_name(), m->name()->as_C_string()); 532 533 if (!m->is_native()) { 534 symbolOop source_name = instanceKlass::cast(k)->source_file_name(); 535 int line_number = m->line_number_from_bci(bci()); 536 if (source_name != NULL && (line_number != -1)) { 537 tty->print("(%s:%d)", source_name->as_C_string(), line_number); 538 } 539 } else { 540 tty->print("(Native Method)"); 541 } 542 // Check frame size and print warning if it looks suspiciously large 543 if (fr().sp() != NULL) { 544 RegisterMap map = *register_map(); 545 uint size = fr().frame_size(&map); 546#ifdef _LP64 547 if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size); 548#else 549 if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size); 550#endif 551 } 552} 553 554 555bool javaVFrame::structural_compare(javaVFrame* other) { 556 // Check static part 557 if (method() != other->method()) return false; 558 if (bci() != other->bci()) return false; 559 560 // Check locals 561 StackValueCollection *locs = locals(); 562 StackValueCollection *other_locs = other->locals(); 563 assert(locs->size() == other_locs->size(), "sanity check"); 564 int i; 565 for(i = 0; i < locs->size(); i++) { 566 // it might happen the compiler reports a conflict and 567 // the interpreter reports a bogus int. 568 if ( is_compiled_frame() && locs->at(i)->type() == T_CONFLICT) continue; 569 if (other->is_compiled_frame() && other_locs->at(i)->type() == T_CONFLICT) continue; 570 571 if (!locs->at(i)->equal(other_locs->at(i))) 572 return false; 573 } 574 575 // Check expressions 576 StackValueCollection* exprs = expressions(); 577 StackValueCollection* other_exprs = other->expressions(); 578 assert(exprs->size() == other_exprs->size(), "sanity check"); 579 for(i = 0; i < exprs->size(); i++) { 580 if (!exprs->at(i)->equal(other_exprs->at(i))) 581 return false; 582 } 583 584 return true; 585} 586 587 588void javaVFrame::print_activation(int index) const { 589 // frame number and method 590 tty->print("%2d - ", index); 591 ((vframe*)this)->print_value(); 592 tty->cr(); 593 594 if (WizardMode) { 595 ((vframe*)this)->print(); 596 tty->cr(); 597 } 598} 599 600 601void javaVFrame::verify() const { 602} 603 604 605void interpretedVFrame::verify() const { 606} 607 608 609// ------------- externalVFrame -------------- 610 611void externalVFrame::print() { 612 _fr.print_value_on(tty,NULL); 613} 614 615 616void externalVFrame::print_value() const { 617 ((vframe*)this)->print(); 618} 619#endif // PRODUCT 620