1 /* 2 * Copyright (c) 1997, 2017, 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 if (ObjectMonitor::Knob_Verbose && mark != NULL) { 259 st->print("\t- lockbits="); 260 mark->print_on(st); 261 st->cr(); 262 } 263 264 found_first_monitor = true; 265 } 266 } 267 } 268 } 269 270 // ------------- interpretedVFrame -------------- 271 272 u_char* interpretedVFrame::bcp() const { 273 return fr().interpreter_frame_bcp(); 274 } 275 276 void interpretedVFrame::set_bcp(u_char* bcp) { 277 fr().interpreter_frame_set_bcp(bcp); 278 } 279 280 intptr_t* interpretedVFrame::locals_addr_at(int offset) const { 281 assert(fr().is_interpreted_frame(), "frame should be an interpreted frame"); 282 return fr().interpreter_frame_local_at(offset); 283 } 284 285 286 GrowableArray<MonitorInfo*>* interpretedVFrame::monitors() const { 287 GrowableArray<MonitorInfo*>* result = new GrowableArray<MonitorInfo*>(5); 288 for (BasicObjectLock* current = (fr().previous_monitor_in_interpreter_frame(fr().interpreter_frame_monitor_begin())); 289 current >= fr().interpreter_frame_monitor_end(); 290 current = fr().previous_monitor_in_interpreter_frame(current)) { 291 result->push(new MonitorInfo(current->obj(), current->lock(), false, false)); 292 } 293 return result; 294 } 295 296 int interpretedVFrame::bci() const { 297 return method()->bci_from(bcp()); 298 } 299 300 Method* interpretedVFrame::method() const { 301 return fr().interpreter_frame_method(); 302 } 303 304 static StackValue* create_stack_value_from_oop_map(const InterpreterOopMap& oop_mask, 305 int index, 306 const intptr_t* const addr) { 307 308 assert(index >= 0 && 309 index < oop_mask.number_of_entries(), "invariant"); 310 311 // categorize using oop_mask 312 if (oop_mask.is_oop(index)) { 313 // reference (oop) "r" 314 Handle h(Thread::current(), addr != NULL ? (*(oop*)addr) : (oop)NULL); 315 return new StackValue(h); 316 } 317 // value (integer) "v" 318 return new StackValue(addr != NULL ? *addr : 0); 319 } 320 321 static bool is_in_expression_stack(const frame& fr, const intptr_t* const addr) { 322 assert(addr != NULL, "invariant"); 323 324 // Ensure to be 'inside' the expresion stack (i.e., addr >= sp for Intel). 325 // In case of exceptions, the expression stack is invalid and the sp 326 // will be reset to express this condition. 327 if (frame::interpreter_frame_expression_stack_direction() > 0) { 328 return addr <= fr.interpreter_frame_tos_address(); 329 } 330 331 return addr >= fr.interpreter_frame_tos_address(); 332 } 333 334 static void stack_locals(StackValueCollection* result, 335 int length, 336 const InterpreterOopMap& oop_mask, 337 const frame& fr) { 338 339 assert(result != NULL, "invariant"); 340 341 for (int i = 0; i < length; ++i) { 342 const intptr_t* const addr = fr.interpreter_frame_local_at(i); 343 assert(addr != NULL, "invariant"); 344 assert(addr >= fr.sp(), "must be inside the frame"); 345 346 StackValue* const sv = create_stack_value_from_oop_map(oop_mask, i, addr); 347 assert(sv != NULL, "sanity check"); 348 349 result->add(sv); 350 } 351 } 352 353 static void stack_expressions(StackValueCollection* result, 354 int length, 355 int max_locals, 356 const InterpreterOopMap& oop_mask, 357 const frame& fr) { 358 359 assert(result != NULL, "invariant"); 360 361 for (int i = 0; i < length; ++i) { 362 const intptr_t* addr = fr.interpreter_frame_expression_stack_at(i); 363 assert(addr != NULL, "invariant"); 364 if (!is_in_expression_stack(fr, addr)) { 365 // Need to ensure no bogus escapes. 366 addr = NULL; 367 } 368 369 StackValue* const sv = create_stack_value_from_oop_map(oop_mask, 370 i + max_locals, 371 addr); 372 assert(sv != NULL, "sanity check"); 373 374 result->add(sv); 375 } 376 } 377 378 StackValueCollection* interpretedVFrame::locals() const { 379 return stack_data(false); 380 } 381 382 StackValueCollection* interpretedVFrame::expressions() const { 383 return stack_data(true); 384 } 385 386 /* 387 * Worker routine for fetching references and/or values 388 * for a particular bci in the interpretedVFrame. 389 * 390 * Returns data for either "locals" or "expressions", 391 * using bci relative oop_map (oop_mask) information. 392 * 393 * @param expressions bool switch controlling what data to return 394 (false == locals / true == expression) 395 * 396 */ 397 StackValueCollection* interpretedVFrame::stack_data(bool expressions) const { 398 399 InterpreterOopMap oop_mask; 400 method()->mask_for(bci(), &oop_mask); 401 const int mask_len = oop_mask.number_of_entries(); 402 403 // If the method is native, method()->max_locals() is not telling the truth. 404 // For our purposes, max locals instead equals the size of parameters. 405 const int max_locals = method()->is_native() ? 406 method()->size_of_parameters() : method()->max_locals(); 407 408 assert(mask_len >= max_locals, "invariant"); 409 410 const int length = expressions ? mask_len - max_locals : max_locals; 411 assert(length >= 0, "invariant"); 412 413 StackValueCollection* const result = new StackValueCollection(length); 414 415 if (0 == length) { 416 return result; 417 } 418 419 if (expressions) { 420 stack_expressions(result, length, max_locals, oop_mask, fr()); 421 } else { 422 stack_locals(result, length, oop_mask, fr()); 423 } 424 425 assert(length == result->size(), "invariant"); 426 427 return result; 428 } 429 430 void interpretedVFrame::set_locals(StackValueCollection* values) const { 431 if (values == NULL || values->size() == 0) return; 432 433 // If the method is native, max_locals is not telling the truth. 434 // maxlocals then equals the size of parameters 435 const int max_locals = method()->is_native() ? 436 method()->size_of_parameters() : method()->max_locals(); 437 438 assert(max_locals == values->size(), "Mismatch between actual stack format and supplied data"); 439 440 // handle locals 441 for (int i = 0; i < max_locals; i++) { 442 // Find stack location 443 intptr_t *addr = locals_addr_at(i); 444 445 // Depending on oop/int put it in the right package 446 const StackValue* const sv = values->at(i); 447 assert(sv != NULL, "sanity check"); 448 if (sv->type() == T_OBJECT) { 449 *(oop *) addr = (sv->get_obj())(); 450 } else { // integer 451 *addr = sv->get_int(); 452 } 453 } 454 } 455 456 // ------------- cChunk -------------- 457 458 entryVFrame::entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) 459 : externalVFrame(fr, reg_map, thread) {} 460 461 #ifdef ASSERT 462 void vframeStreamCommon::found_bad_method_frame() const { 463 // 6379830 Cut point for an assertion that occasionally fires when 464 // we are using the performance analyzer. 465 // Disable this assert when testing the analyzer with fastdebug. 466 // -XX:SuppressErrorAt=vframe.cpp:XXX (XXX=following line number) 467 fatal("invalid bci or invalid scope desc"); 468 } 469 #endif 470 471 // top-frame will be skipped 472 vframeStream::vframeStream(JavaThread* thread, frame top_frame, 473 bool stop_at_java_call_stub) : vframeStreamCommon(thread) { 474 _stop_at_java_call_stub = stop_at_java_call_stub; 475 476 // skip top frame, as it may not be at safepoint 477 _frame = top_frame.sender(&_reg_map); 478 while (!fill_from_frame()) { 479 _frame = _frame.sender(&_reg_map); 480 } 481 } 482 483 484 // Step back n frames, skip any pseudo frames in between. 485 // This function is used in Class.forName, Class.newInstance, Method.Invoke, 486 // AccessController.doPrivileged. 487 void vframeStreamCommon::security_get_caller_frame(int depth) { 488 assert(depth >= 0, "invalid depth: %d", depth); 489 for (int n = 0; !at_end(); security_next()) { 490 if (!method()->is_ignored_by_security_stack_walk()) { 491 if (n == depth) { 492 // We have reached the desired depth; return. 493 return; 494 } 495 n++; // this is a non-skipped frame; count it against the depth 496 } 497 } 498 // NOTE: At this point there were not enough frames on the stack 499 // to walk to depth. Callers of this method have to check for at_end. 500 } 501 502 503 void vframeStreamCommon::security_next() { 504 if (method()->is_prefixed_native()) { 505 skip_prefixed_method_and_wrappers(); // calls next() 506 } else { 507 next(); 508 } 509 } 510 511 512 void vframeStreamCommon::skip_prefixed_method_and_wrappers() { 513 ResourceMark rm; 514 HandleMark hm; 515 516 int method_prefix_count = 0; 517 char** method_prefixes = JvmtiExport::get_all_native_method_prefixes(&method_prefix_count); 518 Klass* prefixed_klass = method()->method_holder(); 519 const char* prefixed_name = method()->name()->as_C_string(); 520 size_t prefixed_name_len = strlen(prefixed_name); 521 int prefix_index = method_prefix_count-1; 522 523 while (!at_end()) { 524 next(); 525 if (method()->method_holder() != prefixed_klass) { 526 break; // classes don't match, can't be a wrapper 527 } 528 const char* name = method()->name()->as_C_string(); 529 size_t name_len = strlen(name); 530 size_t prefix_len = prefixed_name_len - name_len; 531 if (prefix_len <= 0 || strcmp(name, prefixed_name + prefix_len) != 0) { 532 break; // prefixed name isn't prefixed version of method name, can't be a wrapper 533 } 534 for (; prefix_index >= 0; --prefix_index) { 535 const char* possible_prefix = method_prefixes[prefix_index]; 536 size_t possible_prefix_len = strlen(possible_prefix); 537 if (possible_prefix_len == prefix_len && 538 strncmp(possible_prefix, prefixed_name, prefix_len) == 0) { 539 break; // matching prefix found 540 } 541 } 542 if (prefix_index < 0) { 543 break; // didn't find the prefix, can't be a wrapper 544 } 545 prefixed_name = name; 546 prefixed_name_len = name_len; 547 } 548 } 549 550 551 void vframeStreamCommon::skip_reflection_related_frames() { 552 while (!at_end() && 553 (method()->method_holder()->is_subclass_of(SystemDictionary::reflect_MethodAccessorImpl_klass()) || 554 method()->method_holder()->is_subclass_of(SystemDictionary::reflect_ConstructorAccessorImpl_klass()))) { 555 next(); 556 } 557 } 558 559 560 #ifndef PRODUCT 561 void vframe::print() { 562 if (WizardMode) _fr.print_value_on(tty,NULL); 563 } 564 565 566 void vframe::print_value() const { 567 ((vframe*)this)->print(); 568 } 569 570 571 void entryVFrame::print_value() const { 572 ((entryVFrame*)this)->print(); 573 } 574 575 void entryVFrame::print() { 576 vframe::print(); 577 tty->print_cr("C Chunk inbetween Java"); 578 tty->print_cr("C link " INTPTR_FORMAT, p2i(_fr.link())); 579 } 580 581 582 // ------------- javaVFrame -------------- 583 584 static void print_stack_values(const char* title, StackValueCollection* values) { 585 if (values->is_empty()) return; 586 tty->print_cr("\t%s:", title); 587 values->print(); 588 } 589 590 591 void javaVFrame::print() { 592 ResourceMark rm; 593 vframe::print(); 594 tty->print("\t"); 595 method()->print_value(); 596 tty->cr(); 597 tty->print_cr("\tbci: %d", bci()); 598 599 print_stack_values("locals", locals()); 600 print_stack_values("expressions", expressions()); 601 602 GrowableArray<MonitorInfo*>* list = monitors(); 603 if (list->is_empty()) return; 604 tty->print_cr("\tmonitor list:"); 605 for (int index = (list->length()-1); index >= 0; index--) { 606 MonitorInfo* monitor = list->at(index); 607 tty->print("\t obj\t"); 608 if (monitor->owner_is_scalar_replaced()) { 609 Klass* k = java_lang_Class::as_Klass(monitor->owner_klass()); 610 tty->print("( is scalar replaced %s)", k->external_name()); 611 } else if (monitor->owner() == NULL) { 612 tty->print("( null )"); 613 } else { 614 monitor->owner()->print_value(); 615 tty->print("(owner=" INTPTR_FORMAT ")", p2i(monitor->owner())); 616 } 617 if (monitor->eliminated()) { 618 if(is_compiled_frame()) { 619 tty->print(" ( lock is eliminated in compiled frame )"); 620 } else { 621 tty->print(" ( lock is eliminated, frame not compiled )"); 622 } 623 } 624 tty->cr(); 625 tty->print("\t "); 626 monitor->lock()->print_on(tty); 627 tty->cr(); 628 } 629 } 630 631 632 void javaVFrame::print_value() const { 633 Method* m = method(); 634 InstanceKlass* k = m->method_holder(); 635 tty->print_cr("frame( sp=" INTPTR_FORMAT ", unextended_sp=" INTPTR_FORMAT ", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT ")", 636 p2i(_fr.sp()), p2i(_fr.unextended_sp()), p2i(_fr.fp()), p2i(_fr.pc())); 637 tty->print("%s.%s", k->internal_name(), m->name()->as_C_string()); 638 639 if (!m->is_native()) { 640 Symbol* source_name = k->source_file_name(); 641 int line_number = m->line_number_from_bci(bci()); 642 if (source_name != NULL && (line_number != -1)) { 643 tty->print("(%s:%d)", source_name->as_C_string(), line_number); 644 } 645 } else { 646 tty->print("(Native Method)"); 647 } 648 // Check frame size and print warning if it looks suspiciously large 649 if (fr().sp() != NULL) { 650 RegisterMap map = *register_map(); 651 uint size = fr().frame_size(&map); 652 #ifdef _LP64 653 if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size); 654 #else 655 if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size); 656 #endif 657 } 658 } 659 660 661 bool javaVFrame::structural_compare(javaVFrame* other) { 662 // Check static part 663 if (method() != other->method()) return false; 664 if (bci() != other->bci()) return false; 665 666 // Check locals 667 StackValueCollection *locs = locals(); 668 StackValueCollection *other_locs = other->locals(); 669 assert(locs->size() == other_locs->size(), "sanity check"); 670 int i; 671 for(i = 0; i < locs->size(); i++) { 672 // it might happen the compiler reports a conflict and 673 // the interpreter reports a bogus int. 674 if ( is_compiled_frame() && locs->at(i)->type() == T_CONFLICT) continue; 675 if (other->is_compiled_frame() && other_locs->at(i)->type() == T_CONFLICT) continue; 676 677 if (!locs->at(i)->equal(other_locs->at(i))) 678 return false; 679 } 680 681 // Check expressions 682 StackValueCollection* exprs = expressions(); 683 StackValueCollection* other_exprs = other->expressions(); 684 assert(exprs->size() == other_exprs->size(), "sanity check"); 685 for(i = 0; i < exprs->size(); i++) { 686 if (!exprs->at(i)->equal(other_exprs->at(i))) 687 return false; 688 } 689 690 return true; 691 } 692 693 694 void javaVFrame::print_activation(int index) const { 695 // frame number and method 696 tty->print("%2d - ", index); 697 ((vframe*)this)->print_value(); 698 tty->cr(); 699 700 if (WizardMode) { 701 ((vframe*)this)->print(); 702 tty->cr(); 703 } 704 } 705 706 707 void javaVFrame::verify() const { 708 } 709 710 711 void interpretedVFrame::verify() const { 712 } 713 714 715 // ------------- externalVFrame -------------- 716 717 void externalVFrame::print() { 718 _fr.print_value_on(tty,NULL); 719 } 720 721 722 void externalVFrame::print_value() const { 723 ((vframe*)this)->print(); 724 } 725 #endif // PRODUCT