equal
deleted
inserted
replaced
28 #include "classfile/javaClasses.inline.hpp" |
28 #include "classfile/javaClasses.inline.hpp" |
29 #include "classfile/stringTable.hpp" |
29 #include "classfile/stringTable.hpp" |
30 #include "classfile/systemDictionary.hpp" |
30 #include "classfile/systemDictionary.hpp" |
31 #include "gc/shared/collectedHeap.hpp" |
31 #include "gc/shared/collectedHeap.hpp" |
32 #include "gc/shared/oopStorage.inline.hpp" |
32 #include "gc/shared/oopStorage.inline.hpp" |
|
33 #include "gc/shared/oopStorageSet.hpp" |
33 #include "logging/log.hpp" |
34 #include "logging/log.hpp" |
34 #include "logging/logStream.hpp" |
35 #include "logging/logStream.hpp" |
35 #include "memory/allocation.inline.hpp" |
36 #include "memory/allocation.inline.hpp" |
36 #include "memory/filemap.hpp" |
37 #include "memory/filemap.hpp" |
37 #include "memory/heapShared.inline.hpp" |
38 #include "memory/heapShared.inline.hpp" |
56 |
57 |
57 // We prefer short chains of avg 2 |
58 // We prefer short chains of avg 2 |
58 const double PREF_AVG_LIST_LEN = 2.0; |
59 const double PREF_AVG_LIST_LEN = 2.0; |
59 // 2^24 is max size |
60 // 2^24 is max size |
60 const size_t END_SIZE = 24; |
61 const size_t END_SIZE = 24; |
61 // If a chain gets to 32 something might be wrong |
62 // If a chain gets to 100 something might be wrong |
62 const size_t REHASH_LEN = 32; |
63 const size_t REHASH_LEN = 100; |
63 // If we have as many dead items as 50% of the number of bucket |
64 // If we have as many dead items as 50% of the number of bucket |
64 const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5; |
65 const double CLEAN_DEAD_HIGH_WATER_MARK = 0.5; |
65 |
66 |
66 #if INCLUDE_CDS_JAVA_HEAP |
67 #if INCLUDE_CDS_JAVA_HEAP |
67 inline oop read_string_from_compact_hashtable(address base_address, u4 offset) { |
68 inline oop read_string_from_compact_hashtable(address base_address, u4 offset) { |
77 > _shared_table; |
78 > _shared_table; |
78 #endif |
79 #endif |
79 |
80 |
80 // -------------------------------------------------------------------------- |
81 // -------------------------------------------------------------------------- |
81 |
82 |
82 typedef ConcurrentHashTable<WeakHandle<vm_string_table_data>, |
83 typedef ConcurrentHashTable<StringTableConfig, mtSymbol> StringTableHash; |
83 StringTableConfig, mtSymbol> StringTableHash; |
|
84 static StringTableHash* _local_table = NULL; |
84 static StringTableHash* _local_table = NULL; |
85 |
85 |
86 volatile bool StringTable::_has_work = false; |
86 volatile bool StringTable::_has_work = false; |
87 volatile bool StringTable::_needs_rehashing = false; |
87 volatile bool StringTable::_needs_rehashing = false; |
88 |
88 |
89 volatile size_t StringTable::_uncleaned_items_count = 0; |
89 volatile size_t StringTable::_uncleaned_items_count = 0; |
90 OopStorage* StringTable::_weak_handles = NULL; |
|
91 |
90 |
92 static size_t _current_size = 0; |
91 static size_t _current_size = 0; |
93 static volatile size_t _items_count = 0; |
92 static volatile size_t _items_count = 0; |
94 |
93 |
95 volatile bool _alt_hash = false; |
94 volatile bool _alt_hash = false; |
99 return useAlt ? |
98 return useAlt ? |
100 AltHashing::murmur3_32(murmur_seed, s, len) : |
99 AltHashing::murmur3_32(murmur_seed, s, len) : |
101 java_lang_String::hash_code(s, len); |
100 java_lang_String::hash_code(s, len); |
102 } |
101 } |
103 |
102 |
104 class StringTableConfig : public StringTableHash::BaseConfig { |
103 class StringTableConfig : public StackObj { |
105 private: |
104 private: |
106 public: |
105 public: |
107 static uintx get_hash(WeakHandle<vm_string_table_data> const& value, |
106 typedef WeakHandle<vm_string_table_data> Value; |
108 bool* is_dead) { |
107 |
|
108 static uintx get_hash(Value const& value, bool* is_dead) { |
109 EXCEPTION_MARK; |
109 EXCEPTION_MARK; |
110 oop val_oop = value.peek(); |
110 oop val_oop = value.peek(); |
111 if (val_oop == NULL) { |
111 if (val_oop == NULL) { |
112 *is_dead = true; |
112 *is_dead = true; |
113 return 0; |
113 return 0; |
122 } |
122 } |
123 vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "get hash from oop"); |
123 vm_exit_out_of_memory(length, OOM_MALLOC_ERROR, "get hash from oop"); |
124 return 0; |
124 return 0; |
125 } |
125 } |
126 // We use default allocation/deallocation but counted |
126 // We use default allocation/deallocation but counted |
127 static void* allocate_node(size_t size, |
127 static void* allocate_node(size_t size, Value const& value) { |
128 WeakHandle<vm_string_table_data> const& value) { |
|
129 StringTable::item_added(); |
128 StringTable::item_added(); |
130 return StringTableHash::BaseConfig::allocate_node(size, value); |
129 return AllocateHeap(size, mtSymbol); |
131 } |
130 } |
132 static void free_node(void* memory, |
131 static void free_node(void* memory, Value const& value) { |
133 WeakHandle<vm_string_table_data> const& value) { |
|
134 value.release(); |
132 value.release(); |
135 StringTableHash::BaseConfig::free_node(memory, value); |
133 FreeHeap(memory); |
136 StringTable::item_removed(); |
134 StringTable::item_removed(); |
137 } |
135 } |
138 }; |
136 }; |
139 |
137 |
140 class StringTableLookupJchar : StackObj { |
138 class StringTableLookupJchar : StackObj { |
206 for (ret = 1; ((size_t)1 << ret) < val; ++ret); |
204 for (ret = 1; ((size_t)1 << ret) < val; ++ret); |
207 return ret; |
205 return ret; |
208 } |
206 } |
209 |
207 |
210 void StringTable::create_table() { |
208 void StringTable::create_table() { |
211 _weak_handles = new OopStorage("StringTable weak", |
|
212 StringTableWeakAlloc_lock, |
|
213 StringTableWeakActive_lock); |
|
214 size_t start_size_log_2 = ceil_log2(StringTableSize); |
209 size_t start_size_log_2 = ceil_log2(StringTableSize); |
215 _current_size = ((size_t)1) << start_size_log_2; |
210 _current_size = ((size_t)1) << start_size_log_2; |
216 log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", |
211 log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")", |
217 _current_size, start_size_log_2); |
212 _current_size, start_size_log_2); |
218 _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN); |
213 _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN); |
342 } |
337 } |
343 found_string = do_lookup(name, len, hash); |
338 found_string = do_lookup(name, len, hash); |
344 if (found_string != NULL) { |
339 if (found_string != NULL) { |
345 return found_string; |
340 return found_string; |
346 } |
341 } |
347 return do_intern(string_or_null_h, name, len, hash, CHECK_NULL); |
342 return do_intern(string_or_null_h, name, len, hash, THREAD); |
348 } |
343 } |
349 |
344 |
350 oop StringTable::do_intern(Handle string_or_null_h, const jchar* name, |
345 oop StringTable::do_intern(Handle string_or_null_h, const jchar* name, |
351 int len, uintx hash, TRAPS) { |
346 int len, uintx hash, TRAPS) { |
352 HandleMark hm(THREAD); // cleanup strings created |
347 HandleMark hm(THREAD); // cleanup strings created |
388 } while(true); |
383 } while(true); |
389 } |
384 } |
390 |
385 |
391 void StringTable::oops_do(OopClosure* f) { |
386 void StringTable::oops_do(OopClosure* f) { |
392 assert(f != NULL, "No closure"); |
387 assert(f != NULL, "No closure"); |
393 _weak_handles->oops_do(f); |
388 OopStorageSet::string_table_weak()->oops_do(f); |
394 } |
389 } |
395 |
390 |
396 // Concurrent work |
391 // Concurrent work |
397 void StringTable::grow(JavaThread* jt) { |
392 void StringTable::grow(JavaThread* jt) { |
398 StringTableHash::GrowTask gt(_local_table); |
393 StringTableHash::GrowTask gt(_local_table); |
494 bool StringTable::do_rehash() { |
489 bool StringTable::do_rehash() { |
495 if (!_local_table->is_safepoint_safe()) { |
490 if (!_local_table->is_safepoint_safe()) { |
496 return false; |
491 return false; |
497 } |
492 } |
498 |
493 |
499 // We use max size |
494 // We use current size, not max size. |
500 StringTableHash* new_table = new StringTableHash(END_SIZE, END_SIZE, REHASH_LEN); |
495 size_t new_size = _local_table->get_size_log2(Thread::current()); |
|
496 StringTableHash* new_table = new StringTableHash(new_size, END_SIZE, REHASH_LEN); |
501 // Use alt hash from now on |
497 // Use alt hash from now on |
502 _alt_hash = true; |
498 _alt_hash = true; |
503 if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) { |
499 if (!_local_table->try_move_nodes_to(Thread::current(), new_table)) { |
504 _alt_hash = false; |
500 _alt_hash = false; |
505 delete new_table; |
501 delete new_table; |