Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/symbolTable.cpp @ 6197:d2a62e0f25eb
6995781: Native Memory Tracking (Phase 1)
7151532: DCmd for hotspot native memory tracking
Summary: Implementation of native memory tracking phase 1, which tracks VM native memory usage, and related DCmd
Reviewed-by: acorn, coleenp, fparain
author | zgu |
---|---|
date | Thu, 28 Jun 2012 17:03:16 -0400 |
parents | 246d977b51f2 |
children | ace99a6ffc83 |
comparison
equal
deleted
inserted
replaced
6174:74533f63b116 | 6197:d2a62e0f25eb |
---|---|
62 } | 62 } |
63 | 63 |
64 void SymbolTable::initialize_symbols(int arena_alloc_size) { | 64 void SymbolTable::initialize_symbols(int arena_alloc_size) { |
65 // Initialize the arena for global symbols, size passed in depends on CDS. | 65 // Initialize the arena for global symbols, size passed in depends on CDS. |
66 if (arena_alloc_size == 0) { | 66 if (arena_alloc_size == 0) { |
67 _arena = new Arena(); | 67 _arena = new (mtSymbol) Arena(); |
68 } else { | 68 } else { |
69 _arena = new Arena(arena_alloc_size); | 69 _arena = new (mtSymbol) Arena(arena_alloc_size); |
70 } | 70 } |
71 } | 71 } |
72 | 72 |
73 // Call function for all symbols in the symbol table. | 73 // Call function for all symbols in the symbol table. |
74 void SymbolTable::symbols_do(SymbolClosure *cl) { | 74 void SymbolTable::symbols_do(SymbolClosure *cl) { |
75 const int n = the_table()->table_size(); | 75 const int n = the_table()->table_size(); |
76 for (int i = 0; i < n; i++) { | 76 for (int i = 0; i < n; i++) { |
77 for (HashtableEntry<Symbol*>* p = the_table()->bucket(i); | 77 for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
78 p != NULL; | 78 p != NULL; |
79 p = p->next()) { | 79 p = p->next()) { |
80 cl->do_symbol(p->literal_addr()); | 80 cl->do_symbol(p->literal_addr()); |
81 } | 81 } |
82 } | 82 } |
90 void SymbolTable::unlink() { | 90 void SymbolTable::unlink() { |
91 int removed = 0; | 91 int removed = 0; |
92 int total = 0; | 92 int total = 0; |
93 size_t memory_total = 0; | 93 size_t memory_total = 0; |
94 for (int i = 0; i < the_table()->table_size(); ++i) { | 94 for (int i = 0; i < the_table()->table_size(); ++i) { |
95 HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i); | 95 HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i); |
96 HashtableEntry<Symbol*>* entry = the_table()->bucket(i); | 96 HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i); |
97 while (entry != NULL) { | 97 while (entry != NULL) { |
98 // Shared entries are normally at the end of the bucket and if we run into | 98 // Shared entries are normally at the end of the bucket and if we run into |
99 // a shared entry, then there is nothing more to remove. However, if we | 99 // a shared entry, then there is nothing more to remove. However, if we |
100 // have rehashed the table, then the shared entries are no longer at the | 100 // have rehashed the table, then the shared entries are no longer at the |
101 // end of the bucket. | 101 // end of the bucket. |
115 the_table()->free_entry(entry); | 115 the_table()->free_entry(entry); |
116 } else { | 116 } else { |
117 p = entry->next_addr(); | 117 p = entry->next_addr(); |
118 } | 118 } |
119 // get next entry | 119 // get next entry |
120 entry = (HashtableEntry<Symbol*>*)HashtableEntry<Symbol*>::make_ptr(*p); | 120 entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p); |
121 } | 121 } |
122 } | 122 } |
123 symbols_removed += removed; | 123 symbols_removed += removed; |
124 symbols_counted += total; | 124 symbols_counted += total; |
125 // Exclude printing for normal PrintGCDetails because people parse | 125 // Exclude printing for normal PrintGCDetails because people parse |
162 // Lookup a symbol in a bucket. | 162 // Lookup a symbol in a bucket. |
163 | 163 |
164 Symbol* SymbolTable::lookup(int index, const char* name, | 164 Symbol* SymbolTable::lookup(int index, const char* name, |
165 int len, unsigned int hash) { | 165 int len, unsigned int hash) { |
166 int count = 0; | 166 int count = 0; |
167 for (HashtableEntry<Symbol*>* e = bucket(index); e != NULL; e = e->next()) { | 167 for (HashtableEntry<Symbol*, mtSymbol>* e = bucket(index); e != NULL; e = e->next()) { |
168 count++; // count all entries in this bucket, not just ones with same hash | 168 count++; // count all entries in this bucket, not just ones with same hash |
169 if (e->hash() == hash) { | 169 if (e->hash() == hash) { |
170 Symbol* sym = e->literal(); | 170 Symbol* sym = e->literal(); |
171 if (sym->equals(name, len)) { | 171 if (sym->equals(name, len)) { |
172 // something is referencing this symbol now. | 172 // something is referencing this symbol now. |
174 return sym; | 174 return sym; |
175 } | 175 } |
176 } | 176 } |
177 } | 177 } |
178 // If the bucket size is too deep check if this hash code is insufficient. | 178 // If the bucket size is too deep check if this hash code is insufficient. |
179 if (count >= BasicHashtable::rehash_count && !needs_rehashing()) { | 179 if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) { |
180 _needs_rehashing = check_rehash_table(count); | 180 _needs_rehashing = check_rehash_table(count); |
181 } | 181 } |
182 return NULL; | 182 return NULL; |
183 } | 183 } |
184 | 184 |
266 // Do not increment the reference count to keep this alive | 266 // Do not increment the reference count to keep this alive |
267 Symbol** SymbolTable::lookup_symbol_addr(Symbol* sym){ | 267 Symbol** SymbolTable::lookup_symbol_addr(Symbol* sym){ |
268 unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length()); | 268 unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length()); |
269 int index = the_table()->hash_to_index(hash); | 269 int index = the_table()->hash_to_index(hash); |
270 | 270 |
271 for (HashtableEntry<Symbol*>* e = the_table()->bucket(index); e != NULL; e = e->next()) { | 271 for (HashtableEntry<Symbol*, mtSymbol>* e = the_table()->bucket(index); e != NULL; e = e->next()) { |
272 if (e->hash() == hash) { | 272 if (e->hash() == hash) { |
273 Symbol* literal_sym = e->literal(); | 273 Symbol* literal_sym = e->literal(); |
274 if (sym == literal_sym) { | 274 if (sym == literal_sym) { |
275 return e->literal_addr(); | 275 return e->literal_addr(); |
276 } | 276 } |
385 | 385 |
386 // Create a new symbol. | 386 // Create a new symbol. |
387 Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL); | 387 Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL); |
388 assert(sym->equals((char*)name, len), "symbol must be properly initialized"); | 388 assert(sym->equals((char*)name, len), "symbol must be properly initialized"); |
389 | 389 |
390 HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym); | 390 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); |
391 add_entry(index, entry); | 391 add_entry(index, entry); |
392 return sym; | 392 return sym; |
393 } | 393 } |
394 | 394 |
395 // This version of basic_add adds symbols in batch from the constant pool | 395 // This version of basic_add adds symbols in batch from the constant pool |
433 // Create a new symbol. The null class loader is never unloaded so these | 433 // Create a new symbol. The null class loader is never unloaded so these |
434 // are allocated specially in a permanent arena. | 434 // are allocated specially in a permanent arena. |
435 bool c_heap = class_loader() != NULL; | 435 bool c_heap = class_loader() != NULL; |
436 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); | 436 Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false)); |
437 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? | 437 assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be??? |
438 HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym); | 438 HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym); |
439 add_entry(index, entry); | 439 add_entry(index, entry); |
440 cp->symbol_at_put(cp_indices[i], sym); | 440 cp->symbol_at_put(cp_indices[i], sym); |
441 } | 441 } |
442 } | 442 } |
443 return true; | 443 return true; |
444 } | 444 } |
445 | 445 |
446 | 446 |
447 void SymbolTable::verify() { | 447 void SymbolTable::verify() { |
448 for (int i = 0; i < the_table()->table_size(); ++i) { | 448 for (int i = 0; i < the_table()->table_size(); ++i) { |
449 HashtableEntry<Symbol*>* p = the_table()->bucket(i); | 449 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
450 for ( ; p != NULL; p = p->next()) { | 450 for ( ; p != NULL; p = p->next()) { |
451 Symbol* s = (Symbol*)(p->literal()); | 451 Symbol* s = (Symbol*)(p->literal()); |
452 guarantee(s != NULL, "symbol is NULL"); | 452 guarantee(s != NULL, "symbol is NULL"); |
453 unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length()); | 453 unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length()); |
454 guarantee(p->hash() == h, "broken hash in symbol table entry"); | 454 guarantee(p->hash() == h, "broken hash in symbol table entry"); |
460 | 460 |
461 void SymbolTable::dump(outputStream* st) { | 461 void SymbolTable::dump(outputStream* st) { |
462 NumberSeq summary; | 462 NumberSeq summary; |
463 for (int i = 0; i < the_table()->table_size(); ++i) { | 463 for (int i = 0; i < the_table()->table_size(); ++i) { |
464 int count = 0; | 464 int count = 0; |
465 for (HashtableEntry<Symbol*>* e = the_table()->bucket(i); | 465 for (HashtableEntry<Symbol*, mtSymbol>* e = the_table()->bucket(i); |
466 e != NULL; e = e->next()) { | 466 e != NULL; e = e->next()) { |
467 count++; | 467 count++; |
468 } | 468 } |
469 summary.add((double)count); | 469 summary.add((double)count); |
470 } | 470 } |
497 int max_symbols = 0; | 497 int max_symbols = 0; |
498 int out_of_range = 0; | 498 int out_of_range = 0; |
499 int memory_total = 0; | 499 int memory_total = 0; |
500 int count = 0; | 500 int count = 0; |
501 for (i = 0; i < the_table()->table_size(); i++) { | 501 for (i = 0; i < the_table()->table_size(); i++) { |
502 HashtableEntry<Symbol*>* p = the_table()->bucket(i); | 502 HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i); |
503 for ( ; p != NULL; p = p->next()) { | 503 for ( ; p != NULL; p = p->next()) { |
504 memory_total += p->literal()->object_size(); | 504 memory_total += p->literal()->object_size(); |
505 count++; | 505 count++; |
506 int counter = p->literal()->utf8_length(); | 506 int counter = p->literal()->utf8_length(); |
507 total += counter; | 507 total += counter; |
558 results_length, out_of_range); | 558 results_length, out_of_range); |
559 } | 559 } |
560 | 560 |
561 void SymbolTable::print() { | 561 void SymbolTable::print() { |
562 for (int i = 0; i < the_table()->table_size(); ++i) { | 562 for (int i = 0; i < the_table()->table_size(); ++i) { |
563 HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i); | 563 HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i); |
564 HashtableEntry<Symbol*>* entry = the_table()->bucket(i); | 564 HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i); |
565 if (entry != NULL) { | 565 if (entry != NULL) { |
566 while (entry != NULL) { | 566 while (entry != NULL) { |
567 tty->print(PTR_FORMAT " ", entry->literal()); | 567 tty->print(PTR_FORMAT " ", entry->literal()); |
568 entry->literal()->print(); | 568 entry->literal()->print(); |
569 tty->print(" %d", entry->literal()->refcount()); | 569 tty->print(" %d", entry->literal()->refcount()); |
570 p = entry->next_addr(); | 570 p = entry->next_addr(); |
571 entry = (HashtableEntry<Symbol*>*)HashtableEntry<Symbol*>::make_ptr(*p); | 571 entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p); |
572 } | 572 } |
573 tty->cr(); | 573 tty->cr(); |
574 } | 574 } |
575 } | 575 } |
576 } | 576 } |
629 } | 629 } |
630 | 630 |
631 oop StringTable::lookup(int index, jchar* name, | 631 oop StringTable::lookup(int index, jchar* name, |
632 int len, unsigned int hash) { | 632 int len, unsigned int hash) { |
633 int count = 0; | 633 int count = 0; |
634 for (HashtableEntry<oop>* l = bucket(index); l != NULL; l = l->next()) { | 634 for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) { |
635 count++; | 635 count++; |
636 if (l->hash() == hash) { | 636 if (l->hash() == hash) { |
637 if (java_lang_String::equals(l->literal(), name, len)) { | 637 if (java_lang_String::equals(l->literal(), name, len)) { |
638 return l->literal(); | 638 return l->literal(); |
639 } | 639 } |
640 } | 640 } |
641 } | 641 } |
642 // If the bucket size is too deep check if this hash code is insufficient. | 642 // If the bucket size is too deep check if this hash code is insufficient. |
643 if (count >= BasicHashtable::rehash_count && !needs_rehashing()) { | 643 if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) { |
644 _needs_rehashing = check_rehash_table(count); | 644 _needs_rehashing = check_rehash_table(count); |
645 } | 645 } |
646 return NULL; | 646 return NULL; |
647 } | 647 } |
648 | 648 |
674 if (test != NULL) { | 674 if (test != NULL) { |
675 // Entry already added | 675 // Entry already added |
676 return test; | 676 return test; |
677 } | 677 } |
678 | 678 |
679 HashtableEntry<oop>* entry = new_entry(hashValue, string()); | 679 HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string()); |
680 add_entry(index, entry); | 680 add_entry(index, entry); |
681 return string(); | 681 return string(); |
682 } | 682 } |
683 | 683 |
684 | 684 |
759 void StringTable::unlink(BoolObjectClosure* is_alive) { | 759 void StringTable::unlink(BoolObjectClosure* is_alive) { |
760 // Readers of the table are unlocked, so we should only be removing | 760 // Readers of the table are unlocked, so we should only be removing |
761 // entries at a safepoint. | 761 // entries at a safepoint. |
762 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); | 762 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); |
763 for (int i = 0; i < the_table()->table_size(); ++i) { | 763 for (int i = 0; i < the_table()->table_size(); ++i) { |
764 HashtableEntry<oop>** p = the_table()->bucket_addr(i); | 764 HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i); |
765 HashtableEntry<oop>* entry = the_table()->bucket(i); | 765 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i); |
766 while (entry != NULL) { | 766 while (entry != NULL) { |
767 // Shared entries are normally at the end of the bucket and if we run into | 767 // Shared entries are normally at the end of the bucket and if we run into |
768 // a shared entry, then there is nothing more to remove. However, if we | 768 // a shared entry, then there is nothing more to remove. However, if we |
769 // have rehashed the table, then the shared entries are no longer at the | 769 // have rehashed the table, then the shared entries are no longer at the |
770 // end of the bucket. | 770 // end of the bucket. |
776 p = entry->next_addr(); | 776 p = entry->next_addr(); |
777 } else { | 777 } else { |
778 *p = entry->next(); | 778 *p = entry->next(); |
779 the_table()->free_entry(entry); | 779 the_table()->free_entry(entry); |
780 } | 780 } |
781 entry = (HashtableEntry<oop>*)HashtableEntry<oop>::make_ptr(*p); | 781 entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p); |
782 } | 782 } |
783 } | 783 } |
784 } | 784 } |
785 | 785 |
786 void StringTable::oops_do(OopClosure* f) { | 786 void StringTable::oops_do(OopClosure* f) { |
787 for (int i = 0; i < the_table()->table_size(); ++i) { | 787 for (int i = 0; i < the_table()->table_size(); ++i) { |
788 HashtableEntry<oop>** p = the_table()->bucket_addr(i); | 788 HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i); |
789 HashtableEntry<oop>* entry = the_table()->bucket(i); | 789 HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i); |
790 while (entry != NULL) { | 790 while (entry != NULL) { |
791 f->do_oop((oop*)entry->literal_addr()); | 791 f->do_oop((oop*)entry->literal_addr()); |
792 | 792 |
793 // Did the closure remove the literal from the table? | 793 // Did the closure remove the literal from the table? |
794 if (entry->literal() == NULL) { | 794 if (entry->literal() == NULL) { |
796 *p = entry->next(); | 796 *p = entry->next(); |
797 the_table()->free_entry(entry); | 797 the_table()->free_entry(entry); |
798 } else { | 798 } else { |
799 p = entry->next_addr(); | 799 p = entry->next_addr(); |
800 } | 800 } |
801 entry = (HashtableEntry<oop>*)HashtableEntry<oop>::make_ptr(*p); | 801 entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p); |
802 } | 802 } |
803 } | 803 } |
804 } | 804 } |
805 | 805 |
806 void StringTable::verify() { | 806 void StringTable::verify() { |
807 for (int i = 0; i < the_table()->table_size(); ++i) { | 807 for (int i = 0; i < the_table()->table_size(); ++i) { |
808 HashtableEntry<oop>* p = the_table()->bucket(i); | 808 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); |
809 for ( ; p != NULL; p = p->next()) { | 809 for ( ; p != NULL; p = p->next()) { |
810 oop s = p->literal(); | 810 oop s = p->literal(); |
811 guarantee(s != NULL, "interned string is NULL"); | 811 guarantee(s != NULL, "interned string is NULL"); |
812 guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace"); | 812 guarantee(s->is_perm() || !JavaObjectsInPerm, "interned string not in permspace"); |
813 unsigned int h = java_lang_String::hash_string(s); | 813 unsigned int h = java_lang_String::hash_string(s); |
819 } | 819 } |
820 | 820 |
821 void StringTable::dump(outputStream* st) { | 821 void StringTable::dump(outputStream* st) { |
822 NumberSeq summary; | 822 NumberSeq summary; |
823 for (int i = 0; i < the_table()->table_size(); ++i) { | 823 for (int i = 0; i < the_table()->table_size(); ++i) { |
824 HashtableEntry<oop>* p = the_table()->bucket(i); | 824 HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i); |
825 int count = 0; | 825 int count = 0; |
826 for ( ; p != NULL; p = p->next()) { | 826 for ( ; p != NULL; p = p->next()) { |
827 count++; | 827 count++; |
828 } | 828 } |
829 summary.add((double)count); | 829 summary.add((double)count); |