663 664 void StringtableDCmd::execute(DCmdSource source, TRAPS) { 665 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpStrings, 666 _verbose.value()); 667 VMThread::execute(&dumper); 668 } 669 670 int StringtableDCmd::num_arguments() { 671 ResourceMark rm; 672 StringtableDCmd* dcmd = new StringtableDCmd(NULL, false); 673 if (dcmd != NULL) { 674 DCmdMark mark(dcmd); 675 return dcmd->_dcmdparser.num_arguments(); 676 } else { 677 return 0; 678 } 679 } 680 681 #if INCLUDE_CDS_JAVA_HEAP 682 // Sharing 683 oop StringTable::archive_string(oop s, Thread* THREAD) { 684 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump"); 685 686 oop new_s = NULL; 687 typeArrayOop v = java_lang_String::value(s); 688 typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD); 689 if (new_v == NULL) { 690 return NULL; 691 } 692 new_s = MetaspaceShared::archive_heap_object(s, THREAD); 693 if (new_s == NULL) { 694 return NULL; 695 } 696 697 // adjust the pointer to the 'value' field in the new String oop 698 java_lang_String::set_value_raw(new_s, new_v); 699 return new_s; 700 } 701 702 bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space, 703 CompactStringTableWriter* writer) { 704 assert(UseG1GC, "Only support G1 GC"); 705 assert(UseCompressedOops && UseCompressedClassPointers, 706 "Only support UseCompressedOops and UseCompressedClassPointers enabled"); 707 708 Thread* THREAD = Thread::current(); 709 G1CollectedHeap::heap()->begin_archive_alloc_range(); 710 for (int i = 0; i < the_table()->table_size(); ++i) { 711 HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i); 712 for ( ; bucket != NULL; bucket = bucket->next()) { 713 oop s = bucket->literal(); 714 unsigned int hash = java_lang_String::hash_code(s); 715 if (hash == 0) { 716 continue; 717 } 718 719 java_lang_String::set_hash(s, hash); 720 oop new_s = archive_string(s, THREAD); 721 if (new_s == NULL) { 722 continue; 723 } 724 725 // set the archived string in bucket 726 bucket->set_literal(new_s); 727 728 // add to the compact table 729 writer->add(hash, new_s); 730 } 731 } 732 733 G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity()); 734 assert(string_space->length() <= 2, "sanity"); 735 return true; 736 } 737 738 void StringTable::write_to_archive(GrowableArray<MemRegion> *string_space) { 739 assert(UseG1GC, "Only support G1 GC"); 740 assert(UseCompressedOops && UseCompressedClassPointers, 741 "Only support UseCompressedOops and UseCompressedClassPointers enabled"); 742 743 _shared_table.reset(); 744 int num_buckets = the_table()->number_of_entries() / 745 SharedSymbolTableBucketSize; 746 // calculation of num_buckets can result in zero buckets, we need at least one 747 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1, 748 &MetaspaceShared::stats()->string); 749 750 // Copy the interned strings into the "string space" within the java heap 751 if (copy_shared_string(string_space, &writer)) { 752 writer.dump(&_shared_table); 753 } 754 } 755 756 void StringTable::serialize(SerializeClosure* soc) { 757 _shared_table.set_type(CompactHashtable<oop, char>::_string_table); 758 _shared_table.serialize(soc); 759 760 if (soc->writing()) { 761 _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time | 663 664 void StringtableDCmd::execute(DCmdSource source, TRAPS) { 665 VM_DumpHashtable dumper(output(), VM_DumpHashtable::DumpStrings, 666 _verbose.value()); 667 VMThread::execute(&dumper); 668 } 669 670 int StringtableDCmd::num_arguments() { 671 ResourceMark rm; 672 StringtableDCmd* dcmd = new StringtableDCmd(NULL, false); 673 if (dcmd != NULL) { 674 DCmdMark mark(dcmd); 675 return dcmd->_dcmdparser.num_arguments(); 676 } else { 677 return 0; 678 } 679 } 680 681 #if INCLUDE_CDS_JAVA_HEAP 682 // Sharing 683 oop StringTable::create_archived_string(oop s, Thread* THREAD) { 684 assert(DumpSharedSpaces, "this function is only used with -Xshare:dump"); 685 686 oop new_s = NULL; 687 typeArrayOop v = java_lang_String::value(s); 688 typeArrayOop new_v = (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD); 689 if (new_v == NULL) { 690 return NULL; 691 } 692 new_s = MetaspaceShared::archive_heap_object(s, THREAD); 693 if (new_s == NULL) { 694 return NULL; 695 } 696 697 // adjust the pointer to the 'value' field in the new String oop 698 java_lang_String::set_value_raw(new_s, new_v); 699 return new_s; 700 } 701 702 bool StringTable::copy_shared_string(GrowableArray<MemRegion> *string_space, 703 CompactStringTableWriter* writer) { 704 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be"); 705 706 Thread* THREAD = Thread::current(); 707 G1CollectedHeap::heap()->begin_archive_alloc_range(); 708 for (int i = 0; i < the_table()->table_size(); ++i) { 709 HashtableEntry<oop, mtSymbol>* bucket = the_table()->bucket(i); 710 for ( ; bucket != NULL; bucket = bucket->next()) { 711 oop s = bucket->literal(); 712 unsigned int hash = java_lang_String::hash_code(s); 713 if (hash == 0) { 714 continue; 715 } 716 717 java_lang_String::set_hash(s, hash); 718 oop new_s = create_archived_string(s, THREAD); 719 if (new_s == NULL) { 720 continue; 721 } 722 723 // set the archived string in bucket 724 bucket->set_literal(new_s); 725 726 // add to the compact table 727 writer->add(hash, new_s); 728 } 729 } 730 731 G1CollectedHeap::heap()->end_archive_alloc_range(string_space, os::vm_allocation_granularity()); 732 assert(string_space->length() <= 2, "sanity"); 733 return true; 734 } 735 736 void StringTable::write_to_archive(GrowableArray<MemRegion> *string_space) { 737 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be"); 738 739 _shared_table.reset(); 740 int num_buckets = the_table()->number_of_entries() / 741 SharedSymbolTableBucketSize; 742 // calculation of num_buckets can result in zero buckets, we need at least one 743 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1, 744 &MetaspaceShared::stats()->string); 745 746 // Copy the interned strings into the "string space" within the java heap 747 if (copy_shared_string(string_space, &writer)) { 748 writer.dump(&_shared_table); 749 } 750 } 751 752 void StringTable::serialize(SerializeClosure* soc) { 753 _shared_table.set_type(CompactHashtable<oop, char>::_string_table); 754 _shared_table.serialize(soc); 755 756 if (soc->writing()) { 757 _shared_table.reset(); // Sanity. Make sure we don't use the shared table at dump time |