Mercurial > hg > truffle
comparison src/share/vm/runtime/fprofiler.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | 1d7922586cf6 |
children | aeaca88565e6 |
comparison
equal
deleted
inserted
replaced
6724:36d1d483d5d6 | 6725:da91efe96a93 |
---|---|
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); |
510 } | 516 } |
511 bool is_compiled() const { return true; } | 517 bool is_compiled() const { return true; } |
512 | 518 |
513 bool adapter_match() const { return true; } | 519 bool adapter_match() const { return true; } |
514 | 520 |
515 methodOop method() { return NULL; } | 521 Method* method() { return NULL; } |
516 | 522 |
517 void oops_do(OopClosure* f) { | 523 void oops_do(OopClosure* f) { |
518 ; | 524 ; |
519 } | 525 } |
520 | 526 |
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 |