1 /* 2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/javaClasses.hpp" 27 #include "classfile/systemDictionary.hpp" 28 #include "classfile/vmSymbols.hpp" 29 #include "code/codeCache.hpp" 30 #include "code/debugInfoRec.hpp" 31 #include "code/nmethod.hpp" 32 #include "code/pcDesc.hpp" 33 #include "code/scopeDesc.hpp" 34 #include "interpreter/interpreter.hpp" 35 #include "interpreter/oopMapCache.hpp" 36 #include "memory/resourceArea.hpp" 37 #include "oops/instanceKlass.hpp" 38 #include "oops/oop.inline.hpp" 39 #include "runtime/frame.inline.hpp" 40 #include "runtime/handles.inline.hpp" 41 #include "runtime/objectMonitor.hpp" 42 #include "runtime/objectMonitor.inline.hpp" 43 #include "runtime/signature.hpp" 44 #include "runtime/stubRoutines.hpp" 45 #include "runtime/synchronizer.hpp" 46 #include "runtime/vframe.inline.hpp" 47 #include "runtime/vframeArray.hpp" 48 #include "runtime/vframe_hp.hpp" 49 50 vframe::vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) 51 : _reg_map(reg_map), _thread(thread) { 52 assert(fr != NULL, "must have frame"); 53 _fr = *fr; 54 } 55 56 vframe::vframe(const frame* fr, JavaThread* thread) 57 : _reg_map(thread), _thread(thread) { 58 assert(fr != NULL, "must have frame"); 59 _fr = *fr; 60 } 61 62 vframe* vframe::new_vframe(const frame* f, const RegisterMap* reg_map, JavaThread* thread) { 63 // Interpreter frame 64 if (f->is_interpreted_frame()) { 65 return new interpretedVFrame(f, reg_map, thread); 66 } 67 68 // Compiled frame 69 CodeBlob* cb = f->cb(); 70 if (cb != NULL) { 71 if (cb->is_compiled()) { 72 CompiledMethod* nm = (CompiledMethod*)cb; 73 return new compiledVFrame(f, reg_map, thread, nm); 74 } 75 76 if (f->is_runtime_frame()) { 77 // Skip this frame and try again. 78 RegisterMap temp_map = *reg_map; 79 frame s = f->sender(&temp_map); 80 return new_vframe(&s, &temp_map, thread); 81 } 82 } 83 84 // External frame 85 return new externalVFrame(f, reg_map, thread); 86 } 87 88 vframe* vframe::sender() const { 89 RegisterMap temp_map = *register_map(); 90 assert(is_top(), "just checking"); 91 if (_fr.is_entry_frame() && _fr.is_first_frame()) return NULL; 92 frame s = _fr.real_sender(&temp_map); 93 if (s.is_first_frame()) return NULL; 94 return vframe::new_vframe(&s, &temp_map, thread()); 95 } 96 97 vframe* vframe::top() const { 98 vframe* vf = (vframe*) this; 99 while (!vf->is_top()) vf = vf->sender(); 100 return vf; 101 } 102 103 104 javaVFrame* vframe::java_sender() const { 105 vframe* f = sender(); 106 while (f != NULL) { 107 if (f->is_java_frame()) return javaVFrame::cast(f); 108 f = f->sender(); 109 } 110 return NULL; 111 } 112 113 // ------------- javaVFrame -------------- 114 115 GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() { 116 assert(SafepointSynchronize::is_at_safepoint() || JavaThread::current() == thread(), 117 "must be at safepoint or it's a java frame of the current thread"); 118 119 GrowableArray<MonitorInfo*>* mons = monitors(); 120 GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(mons->length()); 121 if (mons->is_empty()) return result; 122 123 bool found_first_monitor = false; 124 ObjectMonitor *pending_monitor = thread()->current_pending_monitor(); 125 ObjectMonitor *waiting_monitor = thread()->current_waiting_monitor(); 126 oop pending_obj = (pending_monitor != NULL ? (oop) pending_monitor->object() : (oop) NULL); 127 oop waiting_obj = (waiting_monitor != NULL ? (oop) waiting_monitor->object() : (oop) NULL); 128 129 for (int index = (mons->length()-1); index >= 0; index--) { 130 MonitorInfo* monitor = mons->at(index); 131 if (monitor->eliminated() && is_compiled_frame()) continue; // skip eliminated monitor 132 oop obj = monitor->owner(); 133 if (obj == NULL) continue; // skip unowned monitor 134 // 135 // Skip the monitor that the thread is blocked to enter or waiting on 136 // 137 if (!found_first_monitor && (obj == pending_obj || obj == waiting_obj)) { 138 continue; 139 } 140 found_first_monitor = true; 141 result->append(monitor); 142 } 143 return result; 144 } 145 146 void javaVFrame::print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) { 147 if (obj.not_null()) { 148 st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, p2i(obj())); 149 if (obj->klass() == SystemDictionary::Class_klass()) { 150 st->print_cr("(a java.lang.Class for %s)", java_lang_Class::as_external_name(obj())); 151 } else { 152 Klass* k = obj->klass(); 153 st->print_cr("(a %s)", k->external_name()); 154 } 155 } 156 } 157 158 void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { 159 Thread* THREAD = Thread::current(); 160 ResourceMark rm(THREAD); 161 162 // If this is the first frame and it is java.lang.Object.wait(...) 163 // then print out the receiver. Locals are not always available, 164 // e.g., compiled native frames have no scope so there are no locals. 165 if (frame_count == 0) { 166 if (method()->name() == vmSymbols::wait_name() && 167 method()->method_holder()->name() == vmSymbols::java_lang_Object()) { 168 const char *wait_state = "waiting on"; // assume we are waiting 169 // If earlier in the output we reported java.lang.Thread.State == 170 // "WAITING (on object monitor)" and now we report "waiting on", then 171 // we are still waiting for notification or timeout. Otherwise if 172 // we earlier reported java.lang.Thread.State == "BLOCKED (on object 173 // monitor)", then we are actually waiting to re-lock the monitor. 174 // At this level we can't distinguish the two cases to report 175 // "waited on" rather than "waiting on" for the second case. 176 StackValueCollection* locs = locals(); 177 if (!locs->is_empty()) { 178 StackValue* sv = locs->at(0); 179 if (sv->type() == T_OBJECT) { 180 Handle o = locs->at(0)->get_obj(); 181 print_locked_object_class_name(st, o, wait_state); 182 } 183 } else { 184 st->print_cr("\t- %s <no object reference available>", wait_state); 185 } 186 } else if (thread()->current_park_blocker() != NULL) { 187 oop obj = thread()->current_park_blocker(); 188 Klass* k = obj->klass(); 189 st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", p2i(obj), k->external_name()); 190 } 191 } 192 193 // Print out all monitors that we have locked, or are trying to lock, 194 // including re-locking after being notified or timing out in a wait(). 195 GrowableArray<MonitorInfo*>* mons = monitors(); 196 if (!mons->is_empty()) { 197 bool found_first_monitor = false; 198 for (int index = (mons->length()-1); index >= 0; index--) { 199 MonitorInfo* monitor = mons->at(index); 200 if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code 201 if (monitor->owner_is_scalar_replaced()) { 202 Klass* k = java_lang_Class::as_Klass(monitor->owner_klass()); 203 // format below for lockbits matches this one. 204 st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name()); 205 } else { 206 Handle obj(THREAD, monitor->owner()); 207 if (obj() != NULL) { 208 print_locked_object_class_name(st, obj, "eliminated"); 209 } 210 } 211 continue; 212 } 213 if (monitor->owner() != NULL) { 214 // the monitor is associated with an object, i.e., it is locked 215 216 markOop mark = NULL; 217 const char *lock_state = "locked"; // assume we have the monitor locked 218 if (!found_first_monitor && frame_count == 0) { 219 // If this is the first frame and we haven't found an owned 220 // monitor before, then we need to see if we have completed 221 // the lock or if we are blocked trying to acquire it. Only 222 // an inflated monitor that is first on the monitor list in 223 // the first frame can block us on a monitor enter. 224 mark = monitor->owner()->mark(); 225 if (mark->has_monitor() && 226 ( // we have marked ourself as pending on this monitor 227 mark->monitor() == thread()->current_pending_monitor() || 228 // we are not the owner of this monitor 229 !mark->monitor()->is_entered(thread()) 230 )) { 231 lock_state = "waiting to lock"; 232 } else { 233 // We own the monitor which is not as interesting so 234 // disable the extra printing below. 235 mark = NULL; 236 } 237 } else if (frame_count != 0) { 238 // This is not the first frame so we either own this monitor 239 // or we owned the monitor before and called wait(). Because 240 // wait() could have been called on any monitor in a lower 241 // numbered frame on the stack, we have to check all the 242 // monitors on the list for this frame. 243 mark = monitor->owner()->mark(); 244 if (mark->has_monitor() && 245 ( // we have marked ourself as pending on this monitor 246 mark->monitor() == thread()->current_pending_monitor() || 247 // we are not the owner of this monitor 248 !mark->monitor()->is_entered(thread()) 249 )) { 250 lock_state = "waiting to re-lock in wait()"; 251 } else { 252 // We own the monitor which is not as interesting so 253 // disable the extra printing below. 254 mark = NULL; 255 } 256 } 257 print_locked_object_class_name(st, Handle(THREAD, monitor->owner()), lock_state); 258 259 found_first_monitor = true; 260 } 261 } 262 } 263 } 264 265 // ------------- interpretedVFrame -------------- 266 267 u_char* interpretedVFrame::bcp() const { 268 return fr().interpreter_frame_bcp(); 269 } 270 271 void interpretedVFrame::set_bcp(u_char* bcp) { 272 fr().interpreter_frame_set_bcp(bcp); 273 } 274 275 intptr_t* interpretedVFrame::locals_addr_at(int offset) const { 276 assert(fr().is_interpreted_frame(), "frame should be an interpreted frame"); 277 return fr().interpreter_frame_local_at(offset); 278 } 279 280 281 GrowableArray<MonitorInfo*>* interpretedVFrame::monitors() const { 282 GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(5); 283 for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin())); 284 current >= fr().interpreter_frame_monitor_end(); 285 current = fr().previous_monitor_in_interpreter_frame(current)) { 286 result->push(new MonitorInfo(current->obj(), current->lock(), false, false)); 287 } 288 return result; 289 } 290 291 int interpretedVFrame::bci() const { 292 return method()->bci_from(bcp()); 293 } 294 295 Method* interpretedVFrame::method() const { 296 return fr().interpreter_frame_method(); 297 } 298 299 static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask, 300 int index, 301 const intptr_t* const addr) { 302 303 assert(index >= 0 && 304 index < oop_mask.number_of_entries(), "invariant"); 305 306 // categorize using oop_mask 307 if (oop_mask.is_oop(index)) { 308 // reference (oop) "r" 309 Handle h(Thread::current(), addr != NULL ? (*(oop*)addr) : (oop)NULL); 310 return new StackValue(h); 311 } 312 // value (integer) "v" 313 return new StackValue(addr != NULL ? *addr : 0); 314 } 315 316 static bool is_in_expression_stack(const frame& fr, const intptr_t* const addr) { 317 assert(addr != NULL, "invariant"); 318 319 // Ensure to be 'inside' the expresion stack (i.e., addr >= sp for Intel). 320 // In case of exceptions, the expression stack is invalid and the sp 321 // will be reset to express this condition. 322 if (frame::interpreter_frame_expression_stack_direction() > 0) { 323 return addr <= fr.interpreter_frame_tos_address(); 324 } 325 326 return addr >= fr.interpreter_frame_tos_address(); 327 } 328 329 static void stack_locals(StackValueCollection* result, 330 int length, 331 const InterpreterOopMap& oop_mask, 332 const frame& fr) { 333 334 assert(result != NULL, "invariant"); 335 336 for (int i = 0; i < length; ++i) { 337 const intptr_t* const addr = fr.interpreter_frame_local_at(i); 338 assert(addr != NULL, "invariant"); 339 assert(addr >= fr.sp(), "must be inside the frame"); 340 341 StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr); 342 assert(sv != NULL, "sanity check"); 343 344 result->add(sv); 345 } 346 } 347 348 static void stack_expressions(StackValueCollection* result, 349 int length, 350 int max_locals, 351 const InterpreterOopMap& oop_mask, 352 const frame& fr) { 353 354 assert(result != NULL, "invariant"); 355 356 for (int i = 0; i < length; ++i) { 357 const intptr_t* addr = fr.interpreter_frame_expression_stack_at(i); 358 assert(addr != NULL, "invariant"); 359 if (!is_in_expression_stack(fr, addr)) { 360 // Need to ensure no bogus escapes. 361 addr = NULL; 362 } 363 364 StackValue* const sv = create_stack_value_from_oop_map(oop_mask, 365 i + max_locals, 366 addr); 367 assert(sv != NULL, "sanity check"); 368 369 result->add(sv); 370 } 371 } 372 373 StackValueCollection* interpretedVFrame::locals() const { 374 return stack_data(false); 375 } 376 377 StackValueCollection* interpretedVFrame::expressions() const { 378 return stack_data(true); 379 } 380 381 /* 382 * Worker routine for fetching references and/or values 383 * for a particular bci in the interpretedVFrame. 384 * 385 * Returns data for either "locals" or "expressions", 386 * using bci relative oop_map (oop_mask) information. 387 * 388 * @param expressions bool switch controlling what data to return 389 (false == locals / true == expression) 390 * 391 */ 392 StackValueCollection* interpretedVFrame::stack_data(bool expressions) const { 393 394 InterpreterOopMap oop_mask; 395 method()->mask_for(bci(), &oop_mask); 396 const int mask_len = oop_mask.number_of_entries(); 397 398 // If the method is native, method()->max_locals() is not telling the truth. 399 // For our purposes, max locals instead equals the size of parameters. 400 const int max_locals = method()->is_native() ? 401 method()->size_of_parameters() : method()->max_locals(); 402 403 assert(mask_len >= max_locals, "invariant"); 404 405 const int length = expressions ? mask_len - max_locals : max_locals; 406 assert(length >= 0, "invariant"); 407 408 StackValueCollection* const result = new StackValueCollection(length); 409 410 if (0 == length) { 411 return result; 412 } 413 414 if (expressions) { 415 stack_expressions(result, length, max_locals, oop_mask, fr()); 416 } else { 417 stack_locals(result, length, oop_mask, fr()); 418 } 419 420 assert(length == result->size(), "invariant"); 421 422 return result; 423 } 424 425 void interpretedVFrame::set_locals(StackValueCollection* values) const { 426 if (values == NULL || values->size() == 0) return; 427 428 // If the method is native, max_locals is not telling the truth. 429 // maxlocals then equals the size of parameters 430 const int max_locals = method()->is_native() ? 431 method()->size_of_parameters() : method()->max_locals(); 432 433 assert(max_locals == values->size(), "Mismatch between actual stack format and supplied data"); 434 435 // handle locals 436 for (int i = 0; i < max_locals; i++) { 437 // Find stack location 438 intptr_t *addr = locals_addr_at(i); 439 440 // Depending on oop/int put it in the right package 441 const StackValue* const sv = values->at(i); 442 assert(sv != NULL, "sanity check"); 443 if (sv->type() == T_OBJECT) { 444 *(oop *) addr = (sv->get_obj())(); 445 } else { // integer 446 *addr = sv->get_int(); 447 } 448 } 449 } 450 451 // ------------- cChunk -------------- 452 453 entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) 454 : externalVFrame(fr, reg_map, thread) {} 455 456 #ifdef ASSERT 457 void vframeStreamCommon::found_bad_method_frame() const { 458 // 6379830 Cut point for an assertion that occasionally fires when 459 // we are using the performance analyzer. 460 // Disable this assert when testing the analyzer with fastdebug. 461 // -XX:SuppressErrorAt=vframe.cpp:XXX (XXX=following line number) 462 fatal("invalid bci or invalid scope desc"); 463 } 464 #endif 465 466 // top-frame will be skipped 467 vframeStream::vframeStream(JavaThread* thread, frame top_frame, 468 bool stop_at_java_call_stub) : vframeStreamCommon(thread) { 469 _stop_at_java_call_stub = stop_at_java_call_stub; 470 471 // skip top frame, as it may not be at safepoint 472 _frame = top_frame.sender(&_reg_map); 473 while (!fill_from_frame()) { 474 _frame = _frame.sender(&_reg_map); 475 } 476 } 477 478 479 // Step back n frames, skip any pseudo frames in between. 480 // This function is used in Class.forName, Class.newInstance, Method.Invoke, 481 // AccessController.doPrivileged. 482 void vframeStreamCommon::security_get_caller_frame(int depth) { 483 assert(depth >= 0, "invalid depth: %d", depth); 484 for (int n = 0; !at_end(); security_next()) { 485 if (!method()->is_ignored_by_security_stack_walk()) { 486 if (n == depth) { 487 // We have reached the desired depth; return. 488 return; 489 } 490 n++; // this is a non-skipped frame; count it against the depth 491 } 492 } 493 // NOTE: At this point there were not enough frames on the stack 494 // to walk to depth. Callers of this method have to check for at_end. 495 } 496 497 498 void vframeStreamCommon::security_next() { 499 if (method()->is_prefixed_native()) { 500 skip_prefixed_method_and_wrappers(); // calls next() 501 } else { 502 next(); 503 } 504 } 505 506 507 void vframeStreamCommon::skip_prefixed_method_and_wrappers() { 508 ResourceMark rm; 509 HandleMark hm; 510 511 int method_prefix_count = 0; 512 char** method_prefixes = JvmtiExport::get_all_native_method_prefixes(&method_prefix_count); 513 Klass* prefixed_klass = method()->method_holder(); 514 const char* prefixed_name = method()->name()->as_C_string(); 515 size_t prefixed_name_len = strlen(prefixed_name); 516 int prefix_index = method_prefix_count-1; 517 518 while (!at_end()) { 519 next(); 520 if (method()->method_holder() != prefixed_klass) { 521 break; // classes don't match, can't be a wrapper 522 } 523 const char* name = method()->name()->as_C_string(); 524 size_t name_len = strlen(name); 525 size_t prefix_len = prefixed_name_len - name_len; 526 if (prefix_len <= 0 || strcmp(name, prefixed_name + prefix_len) != 0) { 527 break; // prefixed name isn't prefixed version of method name, can't be a wrapper 528 } 529 for (; prefix_index >= 0; --prefix_index) { 530 const char* possible_prefix = method_prefixes[prefix_index]; 531 size_t possible_prefix_len = strlen(possible_prefix); 532 if (possible_prefix_len == prefix_len && 533 strncmp(possible_prefix, prefixed_name, prefix_len) == 0) { 534 break; // matching prefix found 535 } 536 } 537 if (prefix_index < 0) { 538 break; // didn't find the prefix, can't be a wrapper 539 } 540 prefixed_name = name; 541 prefixed_name_len = name_len; 542 } 543 } 544 545 546 void vframeStreamCommon::skip_reflection_related_frames() { 547 while (!at_end() && 548 (method()->method_holder()->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) || 549 method()->method_holder()->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass()))) { 550 next(); 551 } 552 } 553 554 555 #ifndef PRODUCT 556 void vframe::print() { 557 if (WizardMode) _fr.print_value_on(tty,NULL); 558 } 559 560 561 void vframe::print_value() const { 562 ((vframe*)this)->print(); 563 } 564 565 566 void entryVFrame::print_value() const { 567 ((entryVFrame*)this)->print(); 568 } 569 570 void entryVFrame::print() { 571 vframe::print(); 572 tty->print_cr("C Chunk inbetween Java"); 573 tty->print_cr("C link " INTPTR_FORMAT, p2i(_fr.link())); 574 } 575 576 577 // ------------- javaVFrame -------------- 578 579 static void print_stack_values(const char* title, StackValueCollection* values) { 580 if (values->is_empty()) return; 581 tty->print_cr("\t%s:", title); 582 values->print(); 583 } 584 585 586 void javaVFrame::print() { 587 ResourceMark rm; 588 vframe::print(); 589 tty->print("\t"); 590 method()->print_value(); 591 tty->cr(); 592 tty->print_cr("\tbci: %d", bci()); 593 594 print_stack_values("locals", locals()); 595 print_stack_values("expressions", expressions()); 596 597 GrowableArray<MonitorInfo*>* list = monitors(); 598 if (list->is_empty()) return; 599 tty->print_cr("\tmonitor list:"); 600 for (int index = (list->length()-1); index >= 0; index--) { 601 MonitorInfo* monitor = list->at(index); 602 tty->print("\t obj\t"); 603 if (monitor->owner_is_scalar_replaced()) { 604 Klass* k = java_lang_Class::as_Klass(monitor->owner_klass()); 605 tty->print("( is scalar replaced %s)", k->external_name()); 606 } else if (monitor->owner() == NULL) { 607 tty->print("( null )"); 608 } else { 609 monitor->owner()->print_value(); 610 tty->print("(owner=" INTPTR_FORMAT ")", p2i(monitor->owner())); 611 } 612 if (monitor->eliminated()) { 613 if(is_compiled_frame()) { 614 tty->print(" ( lock is eliminated in compiled frame )"); 615 } else { 616 tty->print(" ( lock is eliminated, frame not compiled )"); 617 } 618 } 619 tty->cr(); 620 tty->print("\t "); 621 monitor->lock()->print_on(tty); 622 tty->cr(); 623 } 624 } 625 626 627 void javaVFrame::print_value() const { 628 Method* m = method(); 629 InstanceKlass* k = m->method_holder(); 630 tty->print_cr("frame( sp=" INTPTR_FORMAT ", unextended_sp=" INTPTR_FORMAT ", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT ")", 631 p2i(_fr.sp()), p2i(_fr.unextended_sp()), p2i(_fr.fp()), p2i(_fr.pc())); 632 tty->print("%s.%s", k->internal_name(), m->name()->as_C_string()); 633 634 if (!m->is_native()) { 635 Symbol* source_name = k->source_file_name(); 636 int line_number = m->line_number_from_bci(bci()); 637 if (source_name != NULL && (line_number != -1)) { 638 tty->print("(%s:%d)", source_name->as_C_string(), line_number); 639 } 640 } else { 641 tty->print("(Native Method)"); 642 } 643 // Check frame size and print warning if it looks suspiciously large 644 if (fr().sp() != NULL) { 645 RegisterMap map = *register_map(); 646 uint size = fr().frame_size(&map); 647 #ifdef _LP64 648 if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size); 649 #else 650 if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size); 651 #endif 652 } 653 } 654 655 656 bool javaVFrame::structural_compare(javaVFrame* other) { 657 // Check static part 658 if (method() != other->method()) return false; 659 if (bci() != other->bci()) return false; 660 661 // Check locals 662 StackValueCollection *locs = locals(); 663 StackValueCollection *other_locs = other->locals(); 664 assert(locs->size() == other_locs->size(), "sanity check"); 665 int i; 666 for(i = 0; i < locs->size(); i++) { 667 // it might happen the compiler reports a conflict and 668 // the interpreter reports a bogus int. 669 if ( is_compiled_frame() && locs->at(i)->type() == T_CONFLICT) continue; 670 if (other->is_compiled_frame() && other_locs->at(i)->type() == T_CONFLICT) continue; 671 672 if (!locs->at(i)->equal(other_locs->at(i))) 673 return false; 674 } 675 676 // Check expressions 677 StackValueCollection* exprs = expressions(); 678 StackValueCollection* other_exprs = other->expressions(); 679 assert(exprs->size() == other_exprs->size(), "sanity check"); 680 for(i = 0; i < exprs->size(); i++) { 681 if (!exprs->at(i)->equal(other_exprs->at(i))) 682 return false; 683 } 684 685 return true; 686 } 687 688 689 void javaVFrame::print_activation(int index) const { 690 // frame number and method 691 tty->print("%2d - ", index); 692 ((vframe*)this)->print_value(); 693 tty->cr(); 694 695 if (WizardMode) { 696 ((vframe*)this)->print(); 697 tty->cr(); 698 } 699 } 700 701 702 void javaVFrame::verify() const { 703 } 704 705 706 void interpretedVFrame::verify() const { 707 } 708 709 710 // ------------- externalVFrame -------------- 711 712 void externalVFrame::print() { 713 _fr.print_value_on(tty,NULL); 714 } 715 716 717 void externalVFrame::print_value() const { 718 ((vframe*)this)->print(); 719 } 720 #endif // PRODUCT