1 /* |
1 /* |
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
286 virtual bool is_compiled() const { return false; } |
286 virtual bool is_compiled() const { return false; } |
287 virtual bool is_stub() const { return false; } |
287 virtual bool is_stub() const { return false; } |
288 virtual bool is_runtime_stub() const{ return false; } |
288 virtual bool is_runtime_stub() const{ return false; } |
289 virtual void oops_do(OopClosure* f) = 0; |
289 virtual void oops_do(OopClosure* f) = 0; |
290 |
290 |
291 virtual bool interpreted_match(methodOop m) const { return false; } |
291 virtual bool interpreted_match(Method* m) const { return false; } |
292 virtual bool compiled_match(methodOop m ) const { return false; } |
292 virtual bool compiled_match(Method* m ) const { return false; } |
293 virtual bool stub_match(methodOop m, const char* name) const { return false; } |
293 virtual bool stub_match(Method* m, const char* name) const { return false; } |
294 virtual bool adapter_match() const { return false; } |
294 virtual bool adapter_match() const { return false; } |
295 virtual bool runtimeStub_match(const CodeBlob* stub, const char* name) const { return false; } |
295 virtual bool runtimeStub_match(const CodeBlob* stub, const char* name) const { return false; } |
296 virtual bool unknown_compiled_match(const CodeBlob* cb) const { return false; } |
296 virtual bool unknown_compiled_match(const CodeBlob* cb) const { return false; } |
297 |
297 |
298 static void print_title(outputStream* st) { |
298 static void print_title(outputStream* st) { |
310 st->fill_to(col3); |
310 st->fill_to(col3); |
311 st->print(msg); |
311 st->print(msg); |
312 st->cr(); |
312 st->cr(); |
313 } |
313 } |
314 |
314 |
315 virtual methodOop method() = 0; |
315 virtual Method* method() = 0; |
316 |
316 |
317 virtual void print_method_on(outputStream* st) { |
317 virtual void print_method_on(outputStream* st) { |
318 int limit; |
318 int limit; |
319 int i; |
319 int i; |
320 methodOop m = method(); |
320 Method* m = method(); |
321 Symbol* k = m->klass_name(); |
321 Symbol* k = m->klass_name(); |
322 // Print the class name with dots instead of slashes |
322 // Print the class name with dots instead of slashes |
323 limit = k->utf8_length(); |
323 limit = k->utf8_length(); |
324 for (i = 0 ; i < limit ; i += 1) { |
324 for (i = 0 ; i < limit ; i += 1) { |
325 char c = (char) k->byte_at(i); |
325 char c = (char) k->byte_at(i); |
340 if (Verbose || WizardMode) { |
340 if (Verbose || WizardMode) { |
341 // Disambiguate overloaded methods |
341 // Disambiguate overloaded methods |
342 Symbol* sig = m->signature(); |
342 Symbol* sig = m->signature(); |
343 sig->print_symbol_on(st); |
343 sig->print_symbol_on(st); |
344 } else if (MethodHandles::is_signature_polymorphic(m->intrinsic_id())) |
344 } else if (MethodHandles::is_signature_polymorphic(m->intrinsic_id())) |
345 // compare with methodOopDesc::print_short_name |
345 // compare with Method::print_short_name |
346 MethodHandles::print_as_basic_type_signature_on(st, m->signature(), true); |
346 MethodHandles::print_as_basic_type_signature_on(st, m->signature(), true); |
347 } |
347 } |
348 |
348 |
349 virtual void print(outputStream* st, int total_ticks) { |
349 virtual void print(outputStream* st, int total_ticks) { |
350 ticks.print_code(st, total_ticks); |
350 ticks.print_code(st, total_ticks); |
354 print_method_on(st); |
354 print_method_on(st); |
355 st->cr(); |
355 st->cr(); |
356 } |
356 } |
357 |
357 |
358 // for hashing into the table |
358 // for hashing into the table |
359 static int hash(methodOop method) { |
359 static int hash(Method* method) { |
360 // The point here is to try to make something fairly unique |
360 // The point here is to try to make something fairly unique |
361 // out of the fields we can read without grabbing any locks |
361 // out of the fields we can read without grabbing any locks |
362 // since the method may be locked when we need the hash. |
362 // since the method may be locked when we need the hash. |
363 return ( |
363 return ( |
364 method->code_size() ^ |
364 method->code_size() ^ |
386 void ProfilerNode::operator delete(void* p){ |
386 void ProfilerNode::operator delete(void* p){ |
387 } |
387 } |
388 |
388 |
389 class interpretedNode : public ProfilerNode { |
389 class interpretedNode : public ProfilerNode { |
390 private: |
390 private: |
391 methodOop _method; |
391 Method* _method; |
|
392 oop _class_loader; // needed to keep metadata for the method alive |
392 public: |
393 public: |
393 interpretedNode(methodOop method, TickPosition where) : ProfilerNode() { |
394 interpretedNode(Method* method, TickPosition where) : ProfilerNode() { |
394 _method = method; |
395 _method = method; |
|
396 _class_loader = method->method_holder()->class_loader(); |
395 update(where); |
397 update(where); |
396 } |
398 } |
397 |
399 |
398 bool is_interpreted() const { return true; } |
400 bool is_interpreted() const { return true; } |
399 |
401 |
400 bool interpreted_match(methodOop m) const { |
402 bool interpreted_match(Method* m) const { |
401 return _method == m; |
403 return _method == m; |
402 } |
404 } |
403 |
405 |
404 void oops_do(OopClosure* f) { |
406 void oops_do(OopClosure* f) { |
405 f->do_oop((oop*)&_method); |
407 f->do_oop(&_class_loader); |
406 } |
408 } |
407 |
409 |
408 methodOop method() { return _method; } |
410 Method* method() { return _method; } |
409 |
411 |
410 static void print_title(outputStream* st) { |
412 static void print_title(outputStream* st) { |
411 st->fill_to(col1); |
413 st->fill_to(col1); |
412 st->print("%11s", "Interpreted"); |
414 st->print("%11s", "Interpreted"); |
413 ProfilerNode::print_title(st); |
415 ProfilerNode::print_title(st); |
423 } |
425 } |
424 }; |
426 }; |
425 |
427 |
426 class compiledNode : public ProfilerNode { |
428 class compiledNode : public ProfilerNode { |
427 private: |
429 private: |
428 methodOop _method; |
430 Method* _method; |
|
431 oop _class_loader; // needed to keep metadata for the method alive |
429 public: |
432 public: |
430 compiledNode(methodOop method, TickPosition where) : ProfilerNode() { |
433 compiledNode(Method* method, TickPosition where) : ProfilerNode() { |
431 _method = method; |
434 _method = method; |
|
435 _class_loader = method->method_holder()->class_loader(); |
432 update(where); |
436 update(where); |
433 } |
437 } |
434 bool is_compiled() const { return true; } |
438 bool is_compiled() const { return true; } |
435 |
439 |
436 bool compiled_match(methodOop m) const { |
440 bool compiled_match(Method* m) const { |
437 return _method == m; |
441 return _method == m; |
438 } |
442 } |
439 |
443 |
440 methodOop method() { return _method; } |
444 Method* method() { return _method; } |
441 |
445 |
442 void oops_do(OopClosure* f) { |
446 void oops_do(OopClosure* f) { |
443 f->do_oop((oop*)&_method); |
447 f->do_oop(&_class_loader); |
444 } |
448 } |
445 |
449 |
446 static void print_title(outputStream* st) { |
450 static void print_title(outputStream* st) { |
447 st->fill_to(col1); |
451 st->fill_to(col1); |
448 st->print("%11s", "Compiled"); |
452 st->print("%11s", "Compiled"); |
458 } |
462 } |
459 }; |
463 }; |
460 |
464 |
461 class stubNode : public ProfilerNode { |
465 class stubNode : public ProfilerNode { |
462 private: |
466 private: |
463 methodOop _method; |
467 Method* _method; |
|
468 oop _class_loader; // needed to keep metadata for the method alive |
464 const char* _symbol; // The name of the nearest VM symbol (for +ProfileVM). Points to a unique string |
469 const char* _symbol; // The name of the nearest VM symbol (for +ProfileVM). Points to a unique string |
465 public: |
470 public: |
466 stubNode(methodOop method, const char* name, TickPosition where) : ProfilerNode() { |
471 stubNode(Method* method, const char* name, TickPosition where) : ProfilerNode() { |
467 _method = method; |
472 _method = method; |
|
473 _class_loader = method->method_holder()->class_loader(); |
468 _symbol = name; |
474 _symbol = name; |
469 update(where); |
475 update(where); |
470 } |
476 } |
471 |
477 |
472 bool is_stub() const { return true; } |
478 bool is_stub() const { return true; } |
473 |
479 |
474 bool stub_match(methodOop m, const char* name) const { |
480 void oops_do(OopClosure* f) { |
|
481 f->do_oop(&_class_loader); |
|
482 } |
|
483 |
|
484 bool stub_match(Method* m, const char* name) const { |
475 return (_method == m) && (_symbol == name); |
485 return (_method == m) && (_symbol == name); |
476 } |
486 } |
477 |
487 |
478 void oops_do(OopClosure* f) { |
488 Method* method() { return _method; } |
479 f->do_oop((oop*)&_method); |
|
480 } |
|
481 |
|
482 methodOop method() { return _method; } |
|
483 |
489 |
484 static void print_title(outputStream* st) { |
490 static void print_title(outputStream* st) { |
485 st->fill_to(col1); |
491 st->fill_to(col1); |
486 st->print("%11s", "Stub"); |
492 st->print("%11s", "Stub"); |
487 ProfilerNode::print_title(st); |
493 ProfilerNode::print_title(st); |
543 assert(stub->is_runtime_stub(), "wrong code blob"); |
549 assert(stub->is_runtime_stub(), "wrong code blob"); |
544 return ((RuntimeStub*)_stub)->entry_point() == ((RuntimeStub*)stub)->entry_point() && |
550 return ((RuntimeStub*)_stub)->entry_point() == ((RuntimeStub*)stub)->entry_point() && |
545 (_symbol == name); |
551 (_symbol == name); |
546 } |
552 } |
547 |
553 |
548 methodOop method() { return NULL; } |
554 Method* method() { return NULL; } |
549 |
555 |
550 static void print_title(outputStream* st) { |
556 static void print_title(outputStream* st) { |
551 st->fill_to(col1); |
557 st->fill_to(col1); |
552 st->print("%11s", "Runtime stub"); |
558 st->print("%11s", "Runtime stub"); |
553 ProfilerNode::print_title(st); |
559 ProfilerNode::print_title(st); |
591 return !strcmp(((BufferBlob*)cb)->name(), _name); |
597 return !strcmp(((BufferBlob*)cb)->name(), _name); |
592 else |
598 else |
593 return !strcmp(((SingletonBlob*)cb)->name(), _name); |
599 return !strcmp(((SingletonBlob*)cb)->name(), _name); |
594 } |
600 } |
595 |
601 |
596 methodOop method() { return NULL; } |
602 Method* method() { return NULL; } |
597 |
603 |
598 void oops_do(OopClosure* f) { |
604 void oops_do(OopClosure* f) { |
599 ; |
605 ; |
600 } |
606 } |
601 |
607 |
625 const char *name() const { return _name; } |
631 const char *name() const { return _name; } |
626 bool is_compiled() const { return true; } |
632 bool is_compiled() const { return true; } |
627 |
633 |
628 bool vm_match(const char* name) const { return strcmp(name, _name) == 0; } |
634 bool vm_match(const char* name) const { return strcmp(name, _name) == 0; } |
629 |
635 |
630 methodOop method() { return NULL; } |
636 Method* method() { return NULL; } |
631 |
637 |
632 static int hash(const char* name){ |
638 static int hash(const char* name){ |
633 // Compute a simple hash |
639 // Compute a simple hash |
634 const char* cp = name; |
640 const char* cp = name; |
635 int h = 0; |
641 int h = 0; |
659 st->print("%s", _name); |
665 st->print("%s", _name); |
660 } |
666 } |
661 } |
667 } |
662 }; |
668 }; |
663 |
669 |
664 void ThreadProfiler::interpreted_update(methodOop method, TickPosition where) { |
670 void ThreadProfiler::interpreted_update(Method* method, TickPosition where) { |
665 int index = entry(ProfilerNode::hash(method)); |
671 int index = entry(ProfilerNode::hash(method)); |
666 if (!table[index]) { |
672 if (!table[index]) { |
667 table[index] = new (this) interpretedNode(method, where); |
673 table[index] = new (this) interpretedNode(method, where); |
668 } else { |
674 } else { |
669 ProfilerNode* prev = table[index]; |
675 ProfilerNode* prev = table[index]; |
676 } |
682 } |
677 prev->set_next(new (this) interpretedNode(method, where)); |
683 prev->set_next(new (this) interpretedNode(method, where)); |
678 } |
684 } |
679 } |
685 } |
680 |
686 |
681 void ThreadProfiler::compiled_update(methodOop method, TickPosition where) { |
687 void ThreadProfiler::compiled_update(Method* method, TickPosition where) { |
682 int index = entry(ProfilerNode::hash(method)); |
688 int index = entry(ProfilerNode::hash(method)); |
683 if (!table[index]) { |
689 if (!table[index]) { |
684 table[index] = new (this) compiledNode(method, where); |
690 table[index] = new (this) compiledNode(method, where); |
685 } else { |
691 } else { |
686 ProfilerNode* prev = table[index]; |
692 ProfilerNode* prev = table[index]; |
693 } |
699 } |
694 prev->set_next(new (this) compiledNode(method, where)); |
700 prev->set_next(new (this) compiledNode(method, where)); |
695 } |
701 } |
696 } |
702 } |
697 |
703 |
698 void ThreadProfiler::stub_update(methodOop method, const char* name, TickPosition where) { |
704 void ThreadProfiler::stub_update(Method* method, const char* name, TickPosition where) { |
699 int index = entry(ProfilerNode::hash(method)); |
705 int index = entry(ProfilerNode::hash(method)); |
700 if (!table[index]) { |
706 if (!table[index]) { |
701 table[index] = new (this) stubNode(method, name, where); |
707 table[index] = new (this) stubNode(method, name, where); |
702 } else { |
708 } else { |
703 ProfilerNode* prev = table[index]; |
709 ProfilerNode* prev = table[index]; |
955 return; |
961 return; |
956 } |
962 } |
957 |
963 |
958 // The frame has been fully validated so we can trust the method and bci |
964 // The frame has been fully validated so we can trust the method and bci |
959 |
965 |
960 methodOop method = *fr.interpreter_frame_method_addr(); |
966 Method* method = *fr.interpreter_frame_method_addr(); |
961 |
967 |
962 interpreted_update(method, where); |
968 interpreted_update(method, where); |
963 |
969 |
964 // update byte code table |
970 // update byte code table |
965 InterpreterCodelet* desc = Interpreter::codelet_containing(fr.pc()); |
971 InterpreterCodelet* desc = Interpreter::codelet_containing(fr.pc()); |
982 RegisterMap map(thread, false); |
988 RegisterMap map(thread, false); |
983 fr = fr.sender(&map); |
989 fr = fr.sender(&map); |
984 cb = fr.cb(); |
990 cb = fr.cb(); |
985 localwhere = tp_native; |
991 localwhere = tp_native; |
986 } |
992 } |
987 methodOop method = (cb->is_nmethod()) ? ((nmethod *)cb)->method() : |
993 Method* method = (cb->is_nmethod()) ? ((nmethod *)cb)->method() : |
988 (methodOop)NULL; |
994 (Method*)NULL; |
989 |
995 |
990 if (method == NULL) { |
996 if (method == NULL) { |
991 if (cb->is_runtime_stub()) |
997 if (cb->is_runtime_stub()) |
992 runtime_stub_update(cb, name, localwhere); |
998 runtime_stub_update(cb, name, localwhere); |
993 else |
999 else |