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 bool StringTable::_shared_string_mapped = false;
68 CompactHashtable<oop, char> StringTable::_shared_table;
69 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;
88 return 0;
89 }
159 return _hash;
160 }
161
162 bool equals(WeakHandle<vm_string_table_data>* value, bool* is_dead) {
163 oop val_oop = value->peek();
164 if (val_oop == NULL) {
165 // dead oop, mark this hash dead for cleaning
166 *is_dead = true;
167 return false;
168 }
169 bool equals = java_lang_String::equals(_find(), val_oop);
170 if (!equals) {
171 return false;
172 }
173 // Need to resolve weak handle and Handleize through possible safepoint.
174 _found = Handle(_thread, value->resolve());
175 return true;
176 }
177 };
178
179 static size_t ceil_pow_2(uintx val) {
180 size_t ret;
181 for (ret = 1; ((size_t)1 << ret) < val; ++ret);
182 return ret;
183 }
184
185 StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0),
186 _needs_rehashing(false), _weak_handles(NULL), _items(0), _uncleaned_items(0) {
187 _weak_handles = new OopStorage("StringTable weak",
188 StringTableWeakAlloc_lock,
189 StringTableWeakActive_lock);
190 size_t start_size_log_2 = ceil_pow_2(StringTableSize);
191 _current_size = ((size_t)1) << start_size_log_2;
192 log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
193 _current_size, start_size_log_2);
194 _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
195 }
196
197 size_t StringTable::item_added() {
198 return Atomic::add((size_t)1, &(the_table()->_items));
199 }
200
201 size_t StringTable::add_items_to_clean(size_t ndead) {
202 size_t total = Atomic::add((size_t)ndead, &(the_table()->_uncleaned_items));
203 log_trace(stringtable)(
204 "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT,
205 the_table()->_uncleaned_items, ndead, total);
206 return total;
207 }
208
209 void StringTable::item_removed() {
210 Atomic::add((size_t)-1, &(the_table()->_items));
211 }
212
213 double StringTable::get_load_factor() {
214 return (_items*1.0)/_current_size;
215 }
216
217 double StringTable::get_dead_factor() {
218 return (_uncleaned_items*1.0)/_current_size;
219 }
220
221 size_t StringTable::table_size(Thread* thread) {
222 return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
223 : Thread::current());
224 }
225
226 void StringTable::trigger_concurrent_work() {
227 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
228 the_table()->_has_work = true;
229 Service_lock->notify_all();
230 }
231
232 // Probing
233 oop StringTable::lookup(Symbol* symbol) {
234 ResourceMark rm;
235 int length;
236 jchar* chars = symbol->as_unicode(length);
237 return lookup(chars, length);
238 }
389 bool ret = _real_boc->do_object_b(obj);
390 if (!ret) {
391 ++_count;
392 }
393 ++_count_total;
394 return ret;
395 }
396 };
397
398 void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f,
399 int* processed, int* removed) {
400 DoNothingClosure dnc;
401 assert(is_alive != NULL, "No closure");
402 StringTableIsAliveCounter stiac(is_alive);
403 OopClosure* tmp = f != NULL ? f : &dnc;
404
405 StringTable::the_table()->_weak_handles->weak_oops_do(&stiac, tmp);
406
407 // This is the serial case without ParState.
408 // Just set the correct number and check for a cleaning phase.
409 the_table()->_uncleaned_items = stiac._count;
410 StringTable::the_table()->check_concurrent_work();
411
412 if (processed != NULL) {
413 *processed = (int) stiac._count_total;
414 }
415 if (removed != NULL) {
416 *removed = (int) stiac._count;
417 }
418 }
419
420 void StringTable::oops_do(OopClosure* f) {
421 assert(f != NULL, "No closure");
422 StringTable::the_table()->_weak_handles->oops_do(f);
423 }
424
425 void StringTable::possibly_parallel_unlink(
426 OopStorage::ParState<false, false>* _par_state_string, BoolObjectClosure* cl,
427 int* processed, int* removed)
428 {
429 DoNothingClosure dnc;
430 assert(cl != NULL, "No closure");
431 StringTableIsAliveCounter stiac(cl);
432
433 _par_state_string->weak_oops_do(&stiac, &dnc);
434
435 // Accumulate the dead strings.
436 the_table()->add_items_to_clean(stiac._count);
437
438 *processed = (int) stiac._count_total;
439 *removed = (int) stiac._count;
440 }
441
442 void StringTable::possibly_parallel_oops_do(
443 OopStorage::ParState<false /* concurrent */, false /* const */>*
444 _par_state_string, OopClosure* f)
445 {
446 assert(f != NULL, "No closure");
447 _par_state_string->oops_do(f);
448 }
449
450 // Concurrent work
451 void StringTable::grow(JavaThread* jt) {
452 StringTableHash::GrowTask gt(_local_table);
453 if (!gt.prepare(jt)) {
454 return;
455 }
456 log_trace(stringtable)("Started to grow");
826 }
827
828 val->replace(new_s);
829 // add to the compact table
830 _writer->add(hash, new_s);
831 return true;
832 }
833 };
834
835 void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) {
836 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
837
838 CopyToArchive copy(writer);
839 StringTable::the_table()->_local_table->do_scan(Thread::current(), copy);
840 }
841
842 void StringTable::write_to_archive() {
843 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
844
845 _shared_table.reset();
846 int num_buckets = the_table()->_items / SharedSymbolTableBucketSize;
847 // calculation of num_buckets can result in zero buckets, we need at least one
848 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
849 &MetaspaceShared::stats()->string);
850
851 // Copy the interned strings into the "string space" within the java heap
852 copy_shared_string_table(&writer);
853 writer.dump(&_shared_table);
854 }
855
856 void StringTable::serialize(SerializeClosure* soc) {
857 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
858 _shared_table.serialize(soc);
859
860 if (soc->writing()) {
861 // Sanity. Make sure we don't use the shared table at dump time
862 _shared_table.reset();
863 } else if (!_shared_string_mapped) {
864 _shared_table.reset();
865 }
866 }
|
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;
88 return 0;
89 }
159 return _hash;
160 }
161
162 bool equals(WeakHandle<vm_string_table_data>* value, bool* is_dead) {
163 oop val_oop = value->peek();
164 if (val_oop == NULL) {
165 // dead oop, mark this hash dead for cleaning
166 *is_dead = true;
167 return false;
168 }
169 bool equals = java_lang_String::equals(_find(), val_oop);
170 if (!equals) {
171 return false;
172 }
173 // Need to resolve weak handle and Handleize through possible safepoint.
174 _found = Handle(_thread, value->resolve());
175 return true;
176 }
177 };
178
179 static size_t log2_ceil(uintx val) {
180 size_t ret;
181 for (ret = 1; ((size_t)1 << ret) < val; ++ret);
182 return ret;
183 }
184
185 StringTable::StringTable() : _local_table(NULL), _current_size(0), _has_work(0),
186 _needs_rehashing(false), _weak_handles(NULL), _items_count(0), _uncleaned_items_count(0) {
187 _weak_handles = new OopStorage("StringTable weak",
188 StringTableWeakAlloc_lock,
189 StringTableWeakActive_lock);
190 size_t start_size_log_2 = log2_ceil(StringTableSize);
191 _current_size = ((size_t)1) << start_size_log_2;
192 log_trace(stringtable)("Start size: " SIZE_FORMAT " (" SIZE_FORMAT ")",
193 _current_size, start_size_log_2);
194 _local_table = new StringTableHash(start_size_log_2, END_SIZE, REHASH_LEN);
195 }
196
197 size_t StringTable::item_added() {
198 return Atomic::add((size_t)1, &(the_table()->_items_count));
199 }
200
201 size_t StringTable::add_items_count_to_clean(size_t ndead) {
202 size_t total = Atomic::add((size_t)ndead, &(the_table()->_uncleaned_items_count));
203 log_trace(stringtable)(
204 "Uncleaned items:" SIZE_FORMAT " added: " SIZE_FORMAT " total:" SIZE_FORMAT,
205 the_table()->_uncleaned_items_count, ndead, total);
206 return total;
207 }
208
209 void StringTable::item_removed() {
210 Atomic::add((size_t)-1, &(the_table()->_items_count));
211 }
212
213 double StringTable::get_load_factor() {
214 return (double)_items_count/_current_size;
215 }
216
217 double StringTable::get_dead_factor() {
218 return (double)_uncleaned_items_count/_current_size;
219 }
220
221 size_t StringTable::table_size(Thread* thread) {
222 return ((size_t)(1)) << _local_table->get_size_log2(thread != NULL ? thread
223 : Thread::current());
224 }
225
226 void StringTable::trigger_concurrent_work() {
227 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
228 the_table()->_has_work = true;
229 Service_lock->notify_all();
230 }
231
232 // Probing
233 oop StringTable::lookup(Symbol* symbol) {
234 ResourceMark rm;
235 int length;
236 jchar* chars = symbol->as_unicode(length);
237 return lookup(chars, length);
238 }
389 bool ret = _real_boc->do_object_b(obj);
390 if (!ret) {
391 ++_count;
392 }
393 ++_count_total;
394 return ret;
395 }
396 };
397
398 void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f,
399 int* processed, int* removed) {
400 DoNothingClosure dnc;
401 assert(is_alive != NULL, "No closure");
402 StringTableIsAliveCounter stiac(is_alive);
403 OopClosure* tmp = f != NULL ? f : &dnc;
404
405 StringTable::the_table()->_weak_handles->weak_oops_do(&stiac, tmp);
406
407 // This is the serial case without ParState.
408 // Just set the correct number and check for a cleaning phase.
409 the_table()->_uncleaned_items_count = stiac._count;
410 StringTable::the_table()->check_concurrent_work();
411
412 if (processed != NULL) {
413 *processed = (int) stiac._count_total;
414 }
415 if (removed != NULL) {
416 *removed = (int) stiac._count;
417 }
418 }
419
420 void StringTable::oops_do(OopClosure* f) {
421 assert(f != NULL, "No closure");
422 StringTable::the_table()->_weak_handles->oops_do(f);
423 }
424
425 void StringTable::possibly_parallel_unlink(
426 OopStorage::ParState<false, false>* _par_state_string, BoolObjectClosure* cl,
427 int* processed, int* removed)
428 {
429 DoNothingClosure dnc;
430 assert(cl != NULL, "No closure");
431 StringTableIsAliveCounter stiac(cl);
432
433 _par_state_string->weak_oops_do(&stiac, &dnc);
434
435 // Accumulate the dead strings.
436 the_table()->add_items_count_to_clean(stiac._count);
437
438 *processed = (int) stiac._count_total;
439 *removed = (int) stiac._count;
440 }
441
442 void StringTable::possibly_parallel_oops_do(
443 OopStorage::ParState<false /* concurrent */, false /* const */>*
444 _par_state_string, OopClosure* f)
445 {
446 assert(f != NULL, "No closure");
447 _par_state_string->oops_do(f);
448 }
449
450 // Concurrent work
451 void StringTable::grow(JavaThread* jt) {
452 StringTableHash::GrowTask gt(_local_table);
453 if (!gt.prepare(jt)) {
454 return;
455 }
456 log_trace(stringtable)("Started to grow");
826 }
827
828 val->replace(new_s);
829 // add to the compact table
830 _writer->add(hash, new_s);
831 return true;
832 }
833 };
834
835 void StringTable::copy_shared_string_table(CompactStringTableWriter* writer) {
836 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
837
838 CopyToArchive copy(writer);
839 StringTable::the_table()->_local_table->do_scan(Thread::current(), copy);
840 }
841
842 void StringTable::write_to_archive() {
843 assert(MetaspaceShared::is_heap_object_archiving_allowed(), "must be");
844
845 _shared_table.reset();
846 int num_buckets = the_table()->_items_count / SharedSymbolTableBucketSize;
847 // calculation of num_buckets can result in zero buckets, we need at least one
848 CompactStringTableWriter writer(num_buckets > 1 ? num_buckets : 1,
849 &MetaspaceShared::stats()->string);
850
851 // Copy the interned strings into the "string space" within the java heap
852 copy_shared_string_table(&writer);
853 writer.dump(&_shared_table);
854 }
855
856 void StringTable::serialize(SerializeClosure* soc) {
857 _shared_table.set_type(CompactHashtable<oop, char>::_string_table);
858 _shared_table.serialize(soc);
859
860 if (soc->writing()) {
861 // Sanity. Make sure we don't use the shared table at dump time
862 _shared_table.reset();
863 } else if (!_shared_string_mapped) {
864 _shared_table.reset();
865 }
866 }
|