1.1 --- a/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp Mon Jun 27 11:27:57 2016 +0000 1.2 +++ b/src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp Thu Jun 30 17:28:39 2016 +0300 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. 1.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.8 * 1.9 * This code is free software; you can redistribute it and/or modify it 1.10 @@ -28,22 +28,23 @@ 1.11 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 1.12 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" 1.13 #include "gc_implementation/g1/g1StringDedupTable.hpp" 1.14 +#include "gc_implementation/shared/concurrentGCThread.hpp" 1.15 #include "memory/gcLocker.hpp" 1.16 #include "memory/padded.inline.hpp" 1.17 #include "oops/typeArrayOop.hpp" 1.18 #include "runtime/mutexLocker.hpp" 1.19 1.20 // 1.21 -// Freelist in the deduplication table entry cache. Links table 1.22 +// List of deduplication table entries. Links table 1.23 // entries together using their _next fields. 1.24 // 1.25 -class G1StringDedupEntryFreeList : public CHeapObj<mtGC> { 1.26 +class G1StringDedupEntryList : public CHeapObj<mtGC> { 1.27 private: 1.28 G1StringDedupEntry* _list; 1.29 size_t _length; 1.30 1.31 public: 1.32 - G1StringDedupEntryFreeList() : 1.33 + G1StringDedupEntryList() : 1.34 _list(NULL), 1.35 _length(0) { 1.36 } 1.37 @@ -63,6 +64,12 @@ 1.38 return entry; 1.39 } 1.40 1.41 + G1StringDedupEntry* remove_all() { 1.42 + G1StringDedupEntry* list = _list; 1.43 + _list = NULL; 1.44 + return list; 1.45 + } 1.46 + 1.47 size_t length() { 1.48 return _length; 1.49 } 1.50 @@ -84,43 +91,53 @@ 1.51 // 1.52 class G1StringDedupEntryCache : public CHeapObj<mtGC> { 1.53 private: 1.54 - // One freelist per GC worker to allow lock less freeing of 1.55 - // entries while doing a parallel scan of the table. Using 1.56 - // PaddedEnd to avoid false sharing. 1.57 - PaddedEnd<G1StringDedupEntryFreeList>* _lists; 1.58 - size_t _nlists; 1.59 + // One cache/overflow list per GC worker to allow lock less freeing of 1.60 + // entries while doing a parallel scan of the table. Using PaddedEnd to 1.61 + // avoid false sharing. 1.62 + size_t _nlists; 1.63 + size_t _max_list_length; 1.64 + PaddedEnd<G1StringDedupEntryList>* _cached; 1.65 + PaddedEnd<G1StringDedupEntryList>* _overflowed; 1.66 1.67 public: 1.68 - G1StringDedupEntryCache(); 1.69 + G1StringDedupEntryCache(size_t max_size); 1.70 ~G1StringDedupEntryCache(); 1.71 1.72 - // Get a table entry from the cache freelist, or allocate a new 1.73 - // entry if the cache is empty. 1.74 + // Set max number of table entries to cache. 1.75 + void set_max_size(size_t max_size); 1.76 + 1.77 + // Get a table entry from the cache, or allocate a new entry if the cache is empty. 1.78 G1StringDedupEntry* alloc(); 1.79 1.80 - // Insert a table entry into the cache freelist. 1.81 + // Insert a table entry into the cache. 1.82 void free(G1StringDedupEntry* entry, uint worker_id); 1.83 1.84 // Returns current number of entries in the cache. 1.85 size_t size(); 1.86 1.87 - // If the cache has grown above the given max size, trim it down 1.88 - // and deallocate the memory occupied by trimmed of entries. 1.89 - void trim(size_t max_size); 1.90 + // Deletes overflowed entries. 1.91 + void delete_overflowed(); 1.92 }; 1.93 1.94 -G1StringDedupEntryCache::G1StringDedupEntryCache() { 1.95 - _nlists = MAX2(ParallelGCThreads, (size_t)1); 1.96 - _lists = PaddedArray<G1StringDedupEntryFreeList, mtGC>::create_unfreeable((uint)_nlists); 1.97 +G1StringDedupEntryCache::G1StringDedupEntryCache(size_t max_size) : 1.98 + _nlists(MAX2(ParallelGCThreads, (size_t)1)), 1.99 + _max_list_length(0), 1.100 + _cached(PaddedArray<G1StringDedupEntryList, mtGC>::create_unfreeable((uint)_nlists)), 1.101 + _overflowed(PaddedArray<G1StringDedupEntryList, mtGC>::create_unfreeable((uint)_nlists)) { 1.102 + set_max_size(max_size); 1.103 } 1.104 1.105 G1StringDedupEntryCache::~G1StringDedupEntryCache() { 1.106 ShouldNotReachHere(); 1.107 } 1.108 1.109 +void G1StringDedupEntryCache::set_max_size(size_t size) { 1.110 + _max_list_length = size / _nlists; 1.111 +} 1.112 + 1.113 G1StringDedupEntry* G1StringDedupEntryCache::alloc() { 1.114 for (size_t i = 0; i < _nlists; i++) { 1.115 - G1StringDedupEntry* entry = _lists[i].remove(); 1.116 + G1StringDedupEntry* entry = _cached[i].remove(); 1.117 if (entry != NULL) { 1.118 return entry; 1.119 } 1.120 @@ -131,31 +148,55 @@ 1.121 void G1StringDedupEntryCache::free(G1StringDedupEntry* entry, uint worker_id) { 1.122 assert(entry->obj() != NULL, "Double free"); 1.123 assert(worker_id < _nlists, "Invalid worker id"); 1.124 + 1.125 entry->set_obj(NULL); 1.126 entry->set_hash(0); 1.127 - _lists[worker_id].add(entry); 1.128 + 1.129 + if (_cached[worker_id].length() < _max_list_length) { 1.130 + // Cache is not full 1.131 + _cached[worker_id].add(entry); 1.132 + } else { 1.133 + // Cache is full, add to overflow list for later deletion 1.134 + _overflowed[worker_id].add(entry); 1.135 + } 1.136 } 1.137 1.138 size_t G1StringDedupEntryCache::size() { 1.139 size_t size = 0; 1.140 for (size_t i = 0; i < _nlists; i++) { 1.141 - size += _lists[i].length(); 1.142 + size += _cached[i].length(); 1.143 } 1.144 return size; 1.145 } 1.146 1.147 -void G1StringDedupEntryCache::trim(size_t max_size) { 1.148 - size_t cache_size = 0; 1.149 +void G1StringDedupEntryCache::delete_overflowed() { 1.150 + double start = os::elapsedTime(); 1.151 + uintx count = 0; 1.152 + 1.153 for (size_t i = 0; i < _nlists; i++) { 1.154 - G1StringDedupEntryFreeList* list = &_lists[i]; 1.155 - cache_size += list->length(); 1.156 - while (cache_size > max_size) { 1.157 - G1StringDedupEntry* entry = list->remove(); 1.158 - assert(entry != NULL, "Should not be null"); 1.159 - cache_size--; 1.160 + G1StringDedupEntry* entry; 1.161 + 1.162 + { 1.163 + // The overflow list can be modified during safepoints, therefore 1.164 + // we temporarily join the suspendible thread set while removing 1.165 + // all entries from the list. 1.166 + SuspendibleThreadSetJoiner sts_join; 1.167 + entry = _overflowed[i].remove_all(); 1.168 + } 1.169 + 1.170 + // Delete all entries 1.171 + while (entry != NULL) { 1.172 + G1StringDedupEntry* next = entry->next(); 1.173 delete entry; 1.174 + entry = next; 1.175 + count++; 1.176 } 1.177 } 1.178 + 1.179 + double end = os::elapsedTime(); 1.180 + if (PrintStringDeduplicationStatistics) { 1.181 + gclog_or_tty->print_cr("[GC concurrent-string-deduplication, deleted " UINTX_FORMAT " entries, " G1_STRDEDUP_TIME_FORMAT "]", count, end - start); 1.182 + } 1.183 } 1.184 1.185 G1StringDedupTable* G1StringDedupTable::_table = NULL; 1.186 @@ -192,7 +233,7 @@ 1.187 1.188 void G1StringDedupTable::create() { 1.189 assert(_table == NULL, "One string deduplication table allowed"); 1.190 - _entry_cache = new G1StringDedupEntryCache(); 1.191 + _entry_cache = new G1StringDedupEntryCache((size_t)(_min_size * _max_cache_factor)); 1.192 _table = new G1StringDedupTable(_min_size); 1.193 } 1.194 1.195 @@ -375,6 +416,9 @@ 1.196 // Update statistics 1.197 _resize_count++; 1.198 1.199 + // Update max cache size 1.200 + _entry_cache->set_max_size((size_t)(size * _max_cache_factor)); 1.201 + 1.202 // Allocate the new table. The new table will be populated by workers 1.203 // calling unlink_or_oops_do() and finally installed by finish_resize(). 1.204 return new G1StringDedupTable(size, _table->_hash_seed); 1.205 @@ -427,7 +471,7 @@ 1.206 removed += unlink_or_oops_do(cl, table_half + partition_begin, table_half + partition_end, worker_id); 1.207 } 1.208 1.209 - // Delayed update avoid contention on the table lock 1.210 + // Delayed update to avoid contention on the table lock 1.211 if (removed > 0) { 1.212 MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag); 1.213 _table->_entries -= removed; 1.214 @@ -545,10 +589,8 @@ 1.215 } 1.216 } 1.217 1.218 -void G1StringDedupTable::trim_entry_cache() { 1.219 - MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag); 1.220 - size_t max_cache_size = (size_t)(_table->_size * _max_cache_factor); 1.221 - _entry_cache->trim(max_cache_size); 1.222 +void G1StringDedupTable::clean_entry_cache() { 1.223 + _entry_cache->delete_overflowed(); 1.224 } 1.225 1.226 void G1StringDedupTable::print_statistics(outputStream* st) {