< prev index next >

src/hotspot/share/classfile/stringTable.cpp

Print this page


   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/altHashing.hpp"
  27 #include "classfile/compactHashtable.inline.hpp"
  28 #include "classfile/javaClasses.inline.hpp"
  29 #include "classfile/stringTable.hpp"
  30 #include "classfile/systemDictionary.hpp"
  31 #include "gc/shared/collectedHeap.hpp"
  32 #include "gc/shared/oopStorage.inline.hpp"
  33 #include "gc/shared/oopStorageParState.inline.hpp"
  34 #include "logging/log.hpp"
  35 #include "logging/logStream.hpp"
  36 #include "memory/allocation.inline.hpp"
  37 #include "memory/filemap.hpp"

  38 #include "memory/metaspaceShared.inline.hpp"
  39 #include "memory/resourceArea.hpp"
  40 #include "memory/universe.hpp"
  41 #include "oops/access.inline.hpp"
  42 #include "oops/oop.inline.hpp"
  43 #include "oops/typeArrayOop.inline.hpp"
  44 #include "oops/weakHandle.inline.hpp"
  45 #include "runtime/atomic.hpp"
  46 #include "runtime/handles.inline.hpp"
  47 #include "runtime/mutexLocker.hpp"
  48 #include "runtime/safepointVerifiers.hpp"
  49 #include "runtime/timerTrace.hpp"
  50 #include "runtime/interfaceSupport.inline.hpp"
  51 #include "services/diagnosticCommand.hpp"
  52 #include "utilities/concurrentHashTable.inline.hpp"
  53 #include "utilities/concurrentHashTableTasks.inline.hpp"
  54 #include "utilities/macros.hpp"
  55 
  56 // We prefer short chains of avg 2
  57 #define PREF_AVG_LIST_LEN   2
  58 // 2^24 is max size
  59 #define END_SIZE           24
  60 // If a chain gets to 32 something might be wrong
  61 #define REHASH_LEN         32
  62 // If we have as many dead items as 50% of the number of bucket
  63 #define CLEAN_DEAD_HIGH_WATER_MARK 0.5
  64 
  65 // --------------------------------------------------------------------------

















  66 StringTable* StringTable::_the_table = NULL;
  67 CompactHashtable<oop, char> StringTable::_shared_table;
  68 volatile bool StringTable::_shared_string_mapped = false;
  69 volatile bool StringTable::_alt_hash = false;
  70 
  71 static juint murmur_seed = 0;
  72 
  73 uintx hash_string(const jchar* s, int len, bool useAlt) {
  74   return  useAlt ?
  75     AltHashing::murmur3_32(murmur_seed, s, len) :
  76     java_lang_String::hash_code(s, len);
  77 }
  78 
  79 class StringTableConfig : public StringTableHash::BaseConfig {
  80  private:
  81  public:
  82   static uintx get_hash(WeakHandle<vm_string_table_data> const& value,
  83                         bool* is_dead) {
  84     EXCEPTION_MARK;
  85     oop val_oop = value.peek();
  86     if (val_oop == NULL) {
  87       *is_dead = true;


 761                          _verbose.value());
 762   VMThread::execute(&dumper);
 763 }
 764 
 765 int StringtableDCmd::num_arguments() {
 766   ResourceMark rm;
 767   StringtableDCmd* dcmd = new StringtableDCmd(NULL, false);
 768   if (dcmd != NULL) {
 769     DCmdMark mark(dcmd);
 770     return dcmd->_dcmdparser.num_arguments();
 771   } else {
 772     return 0;
 773   }
 774 }
 775 
 776 // Sharing
 777 #if INCLUDE_CDS_JAVA_HEAP
 778 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
 779   assert(hash == java_lang_String::hash_code(name, len),
 780          "hash must be computed using java_lang_String::hash_code");
 781   return _shared_table.lookup((const char*)name, hash, len);
 782 }
 783 
 784 oop StringTable::create_archived_string(oop s, Thread* THREAD) {
 785   assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
 786 
 787   if (MetaspaceShared::is_archive_object(s)) {
 788     return s;
 789   }
 790 
 791   oop new_s = NULL;
 792   typeArrayOop v = java_lang_String::value_no_keepalive(s);
 793   typeArrayOop new_v =
 794     (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
 795   if (new_v == NULL) {
 796     return NULL;
 797   }
 798   new_s = MetaspaceShared::archive_heap_object(s, THREAD);
 799   if (new_s == NULL) {
 800     return NULL;
 801   }
 802 
 803   // adjust the pointer to the 'value' field in the new String oop
 804   java_lang_String::set_value_raw(new_s, new_v);
 805   return new_s;
 806 }
 807 









 808 struct CopyToArchive : StackObj {
 809   CompactStringTableWriter* _writer;
 810   CopyToArchive(CompactStringTableWriter* writer) : _writer(writer) {}
 811   bool operator()(WeakHandle<vm_string_table_data>* val) {
 812     oop s = val->peek();
 813     if (s == NULL) {
 814       return true;
 815     }
 816     unsigned int hash = java_lang_String::hash_code(s);
 817     if (hash == 0) {
 818       return true;
 819     }
 820 
 821     java_lang_String::set_hash(s, hash);
 822     oop new_s = StringTable::create_archived_string(s, Thread::current());
 823     if (new_s == NULL) {
 824       return true;
 825     }
 826 
 827     val->replace(new_s);


 832 };
 833 
 834 void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) {
 835   assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
 836 
 837   CopyToArchive copy(writer);
 838   StringTable::the_table()->_local_table->do_scan(Thread::current(), copy);
 839 }
 840 
 841 void StringTable::write_to_archive() {
 842   assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
 843 
 844   _shared_table.reset();
 845   int num_buckets = the_table()->_items_count / SharedSymbolTableBucketSize;
 846   // calculation of num_buckets can result in zero buckets, we need at least one
 847   CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
 848                                   &MetaspaceShared::stats()->string);
 849 
 850   // Copy the interned strings into the "string space" within the java heap
 851   copy_shared_string_table(&writer);
 852   writer.dump(&_shared_table);
 853 }
 854 
 855 void StringTable::serialize(SerializeClosure* soc) {
 856   _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
 857   _shared_table.serialize(soc);
 858 
 859   if (soc->writing()) {
 860     // Sanity. Make sure we don't use the shared table at dump time
 861     _shared_table.reset();
 862   } else if (!_shared_string_mapped) {
 863     _shared_table.reset();
 864   }
 865 }
 866 









 867 void StringTable::shared_oops_do(OopClosure* f) {
 868   _shared_table.oops_do(f);

 869 }
 870 #endif //INCLUDE_CDS_JAVA_HEAP


   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/altHashing.hpp"
  27 #include "classfile/compactHashtable.hpp"
  28 #include "classfile/javaClasses.inline.hpp"
  29 #include "classfile/stringTable.hpp"
  30 #include "classfile/systemDictionary.hpp"
  31 #include "gc/shared/collectedHeap.hpp"
  32 #include "gc/shared/oopStorage.inline.hpp"
  33 #include "gc/shared/oopStorageParState.inline.hpp"
  34 #include "logging/log.hpp"
  35 #include "logging/logStream.hpp"
  36 #include "memory/allocation.inline.hpp"
  37 #include "memory/filemap.hpp"
  38 #include "memory/heapShared.inline.hpp"
  39 #include "memory/metaspaceShared.inline.hpp"
  40 #include "memory/resourceArea.hpp"
  41 #include "memory/universe.hpp"
  42 #include "oops/access.inline.hpp"
  43 #include "oops/oop.inline.hpp"
  44 #include "oops/typeArrayOop.inline.hpp"
  45 #include "oops/weakHandle.inline.hpp"
  46 #include "runtime/atomic.hpp"
  47 #include "runtime/handles.inline.hpp"
  48 #include "runtime/mutexLocker.hpp"
  49 #include "runtime/safepointVerifiers.hpp"
  50 #include "runtime/timerTrace.hpp"
  51 #include "runtime/interfaceSupport.inline.hpp"
  52 #include "services/diagnosticCommand.hpp"
  53 #include "utilities/concurrentHashTable.inline.hpp"
  54 #include "utilities/concurrentHashTableTasks.inline.hpp"
  55 #include "utilities/macros.hpp"
  56 
  57 // We prefer short chains of avg 2
  58 #define PREF_AVG_LIST_LEN   2
  59 // 2^24 is max size
  60 #define END_SIZE           24
  61 // If a chain gets to 32 something might be wrong
  62 #define REHASH_LEN         32
  63 // If we have as many dead items as 50% of the number of bucket
  64 #define CLEAN_DEAD_HIGH_WATER_MARK 0.5
  65 
  66 // --------------------------------------------------------------------------
  67 inline oop read_string_from_compact_hashtable(address base_address, u4 offset) {
  68   assert(sizeof(narrowOop) == sizeof(offset), "must be");
  69   narrowOop v = (narrowOop)offset;
  70   return HeapShared::decode_from_archive(v);
  71 }
  72 
  73 inline bool string_equals_compact_hashtable_entry(oop value, const jchar* key, int len) {
  74   return java_lang_String::equals(value, (jchar*)key, len);
  75 }
  76 
  77 static CompactHashtable<
  78   const jchar*, oop,
  79   read_string_from_compact_hashtable,
  80   string_equals_compact_hashtable_entry
  81 > _shared_table;
  82 
  83 // --------------------------------------------------------------------------
  84 StringTable* StringTable::_the_table = NULL;

  85 volatile bool StringTable::_shared_string_mapped = false;
  86 volatile bool StringTable::_alt_hash = false;
  87 
  88 static juint murmur_seed = 0;
  89 
  90 uintx hash_string(const jchar* s, int len, bool useAlt) {
  91   return  useAlt ?
  92     AltHashing::murmur3_32(murmur_seed, s, len) :
  93     java_lang_String::hash_code(s, len);
  94 }
  95 
  96 class StringTableConfig : public StringTableHash::BaseConfig {
  97  private:
  98  public:
  99   static uintx get_hash(WeakHandle<vm_string_table_data> const& value,
 100                         bool* is_dead) {
 101     EXCEPTION_MARK;
 102     oop val_oop = value.peek();
 103     if (val_oop == NULL) {
 104       *is_dead = true;


 778                          _verbose.value());
 779   VMThread::execute(&dumper);
 780 }
 781 
 782 int StringtableDCmd::num_arguments() {
 783   ResourceMark rm;
 784   StringtableDCmd* dcmd = new StringtableDCmd(NULL, false);
 785   if (dcmd != NULL) {
 786     DCmdMark mark(dcmd);
 787     return dcmd->_dcmdparser.num_arguments();
 788   } else {
 789     return 0;
 790   }
 791 }
 792 
 793 // Sharing
 794 #if INCLUDE_CDS_JAVA_HEAP
 795 oop StringTable::lookup_shared(jchar* name, int len, unsigned int hash) {
 796   assert(hash == java_lang_String::hash_code(name, len),
 797          "hash must be computed using java_lang_String::hash_code");
 798   return _shared_table.lookup(name, hash, len);
 799 }
 800 
 801 oop StringTable::create_archived_string(oop s, Thread* THREAD) {
 802   assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
 803 
 804   if (MetaspaceShared::is_archive_object(s)) {
 805     return s;
 806   }
 807 
 808   oop new_s = NULL;
 809   typeArrayOop v = java_lang_String::value_no_keepalive(s);
 810   typeArrayOop new_v =
 811     (typeArrayOop)MetaspaceShared::archive_heap_object(v, THREAD);
 812   if (new_v == NULL) {
 813     return NULL;
 814   }
 815   new_s = MetaspaceShared::archive_heap_object(s, THREAD);
 816   if (new_s == NULL) {
 817     return NULL;
 818   }
 819 
 820   // adjust the pointer to the 'value' field in the new String oop
 821   java_lang_String::set_value_raw(new_s, new_v);
 822   return new_s;
 823 }
 824 
 825 class CompactStringTableWriter: public CompactHashtableWriter {
 826 public:
 827   CompactStringTableWriter(int num_entries, CompactHashtableStats* stats) :
 828     CompactHashtableWriter(num_entries, stats) {}
 829   void add(unsigned int hash, oop string) {
 830     CompactHashtableWriter::add(hash, CompressedOops::encode(string));
 831   }
 832 };
 833 
 834 struct CopyToArchive : StackObj {
 835   CompactStringTableWriter* _writer;
 836   CopyToArchive(CompactStringTableWriter* writer) : _writer(writer) {}
 837   bool operator()(WeakHandle<vm_string_table_data>* val) {
 838     oop s = val->peek();
 839     if (s == NULL) {
 840       return true;
 841     }
 842     unsigned int hash = java_lang_String::hash_code(s);
 843     if (hash == 0) {
 844       return true;
 845     }
 846 
 847     java_lang_String::set_hash(s, hash);
 848     oop new_s = StringTable::create_archived_string(s, Thread::current());
 849     if (new_s == NULL) {
 850       return true;
 851     }
 852 
 853     val->replace(new_s);


 858 };
 859 
 860 void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) {
 861   assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
 862 
 863   CopyToArchive copy(writer);
 864   StringTable::the_table()->_local_table->do_scan(Thread::current(), copy);
 865 }
 866 
 867 void StringTable::write_to_archive() {
 868   assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
 869 
 870   _shared_table.reset();
 871   int num_buckets = the_table()->_items_count / SharedSymbolTableBucketSize;
 872   // calculation of num_buckets can result in zero buckets, we need at least one
 873   CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
 874                                   &MetaspaceShared::stats()->string);
 875 
 876   // Copy the interned strings into the "string space" within the java heap
 877   copy_shared_string_table(&writer);
 878   writer.dump(&_shared_table, "string");
 879 }
 880 
 881 void StringTable::serialize(SerializeClosure* soc) {

 882   _shared_table.serialize(soc);
 883 
 884   if (soc->writing()) {
 885     // Sanity. Make sure we don't use the shared table at dump time
 886     _shared_table.reset();
 887   } else if (!_shared_string_mapped) {
 888     _shared_table.reset();
 889   }
 890 }
 891 
 892 class SharedStringIterator {
 893   OopClosure* _oop_closure;
 894 public:
 895   SharedStringIterator(OopClosure* f) : _oop_closure(f) {}
 896   void do_value(oop string) {
 897     _oop_closure->do_oop(&string);
 898   }
 899 };
 900 
 901 void StringTable::shared_oops_do(OopClosure* f) {
 902   SharedStringIterator iter(f);
 903   _shared_table.iterate(&iter);
 904 }
 905 #endif //INCLUDE_CDS_JAVA_HEAP
< prev index next >