src/share/vm/gc_implementation/g1/g1StringDedupTable.cpp

changeset 8452
04a62a3d51d7
parent 0
f90c822e73f8
child 9327
f96fcd9e1e1b
equal deleted inserted replaced
8451:649f01d13b2d 8452:04a62a3d51d7
1 /* 1 /*
2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
26 #include "classfile/altHashing.hpp" 26 #include "classfile/altHashing.hpp"
27 #include "classfile/javaClasses.hpp" 27 #include "classfile/javaClasses.hpp"
28 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" 28 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
29 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" 29 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
30 #include "gc_implementation/g1/g1StringDedupTable.hpp" 30 #include "gc_implementation/g1/g1StringDedupTable.hpp"
31 #include "gc_implementation/shared/concurrentGCThread.hpp"
31 #include "memory/gcLocker.hpp" 32 #include "memory/gcLocker.hpp"
32 #include "memory/padded.inline.hpp" 33 #include "memory/padded.inline.hpp"
33 #include "oops/typeArrayOop.hpp" 34 #include "oops/typeArrayOop.hpp"
34 #include "runtime/mutexLocker.hpp" 35 #include "runtime/mutexLocker.hpp"
35 36
36 // 37 //
37 // Freelist in the deduplication table entry cache. Links table 38 // List of deduplication table entries. Links table
38 // entries together using their _next fields. 39 // entries together using their _next fields.
39 // 40 //
40 class G1StringDedupEntryFreeList : public CHeapObj<mtGC> { 41 class G1StringDedupEntryList : public CHeapObj<mtGC> {
41 private: 42 private:
42 G1StringDedupEntry* _list; 43 G1StringDedupEntry* _list;
43 size_t _length; 44 size_t _length;
44 45
45 public: 46 public:
46 G1StringDedupEntryFreeList() : 47 G1StringDedupEntryList() :
47 _list(NULL), 48 _list(NULL),
48 _length(0) { 49 _length(0) {
49 } 50 }
50 51
51 void add(G1StringDedupEntry* entry) { 52 void add(G1StringDedupEntry* entry) {
59 if (entry != NULL) { 60 if (entry != NULL) {
60 _list = entry->next(); 61 _list = entry->next();
61 _length--; 62 _length--;
62 } 63 }
63 return entry; 64 return entry;
65 }
66
67 G1StringDedupEntry* remove_all() {
68 G1StringDedupEntry* list = _list;
69 _list = NULL;
70 return list;
64 } 71 }
65 72
66 size_t length() { 73 size_t length() {
67 return _length; 74 return _length;
68 } 75 }
82 // Allocations are synchronized by StringDedupTable_lock as part of a table 89 // Allocations are synchronized by StringDedupTable_lock as part of a table
83 // modification. 90 // modification.
84 // 91 //
85 class G1StringDedupEntryCache : public CHeapObj<mtGC> { 92 class G1StringDedupEntryCache : public CHeapObj<mtGC> {
86 private: 93 private:
87 // One freelist per GC worker to allow lock less freeing of 94 // One cache/overflow list per GC worker to allow lock less freeing of
88 // entries while doing a parallel scan of the table. Using 95 // entries while doing a parallel scan of the table. Using PaddedEnd to
89 // PaddedEnd to avoid false sharing. 96 // avoid false sharing.
90 PaddedEnd<G1StringDedupEntryFreeList>* _lists; 97 size_t _nlists;
91 size_t _nlists; 98 size_t _max_list_length;
99 PaddedEnd<G1StringDedupEntryList>* _cached;
100 PaddedEnd<G1StringDedupEntryList>* _overflowed;
92 101
93 public: 102 public:
94 G1StringDedupEntryCache(); 103 G1StringDedupEntryCache(size_t max_size);
95 ~G1StringDedupEntryCache(); 104 ~G1StringDedupEntryCache();
96 105
97 // Get a table entry from the cache freelist, or allocate a new 106 // Set max number of table entries to cache.
98 // entry if the cache is empty. 107 void set_max_size(size_t max_size);
108
109 // Get a table entry from the cache, or allocate a new entry if the cache is empty.
99 G1StringDedupEntry* alloc(); 110 G1StringDedupEntry* alloc();
100 111
101 // Insert a table entry into the cache freelist. 112 // Insert a table entry into the cache.
102 void free(G1StringDedupEntry* entry, uint worker_id); 113 void free(G1StringDedupEntry* entry, uint worker_id);
103 114
104 // Returns current number of entries in the cache. 115 // Returns current number of entries in the cache.
105 size_t size(); 116 size_t size();
106 117
107 // If the cache has grown above the given max size, trim it down 118 // Deletes overflowed entries.
108 // and deallocate the memory occupied by trimmed of entries. 119 void delete_overflowed();
109 void trim(size_t max_size);
110 }; 120 };
111 121
112 G1StringDedupEntryCache::G1StringDedupEntryCache() { 122 G1StringDedupEntryCache::G1StringDedupEntryCache(size_t max_size) :
113 _nlists = MAX2(ParallelGCThreads, (size_t)1); 123 _nlists(MAX2(ParallelGCThreads, (size_t)1)),
114 _lists = PaddedArray<G1StringDedupEntryFreeList, mtGC>::create_unfreeable((uint)_nlists); 124 _max_list_length(0),
125 _cached(PaddedArray<G1StringDedupEntryList, mtGC>::create_unfreeable((uint)_nlists)),
126 _overflowed(PaddedArray<G1StringDedupEntryList, mtGC>::create_unfreeable((uint)_nlists)) {
127 set_max_size(max_size);
115 } 128 }
116 129
117 G1StringDedupEntryCache::~G1StringDedupEntryCache() { 130 G1StringDedupEntryCache::~G1StringDedupEntryCache() {
118 ShouldNotReachHere(); 131 ShouldNotReachHere();
119 } 132 }
120 133
134 void G1StringDedupEntryCache::set_max_size(size_t size) {
135 _max_list_length = size / _nlists;
136 }
137
121 G1StringDedupEntry* G1StringDedupEntryCache::alloc() { 138 G1StringDedupEntry* G1StringDedupEntryCache::alloc() {
122 for (size_t i = 0; i < _nlists; i++) { 139 for (size_t i = 0; i < _nlists; i++) {
123 G1StringDedupEntry* entry = _lists[i].remove(); 140 G1StringDedupEntry* entry = _cached[i].remove();
124 if (entry != NULL) { 141 if (entry != NULL) {
125 return entry; 142 return entry;
126 } 143 }
127 } 144 }
128 return new G1StringDedupEntry(); 145 return new G1StringDedupEntry();
129 } 146 }
130 147
131 void G1StringDedupEntryCache::free(G1StringDedupEntry* entry, uint worker_id) { 148 void G1StringDedupEntryCache::free(G1StringDedupEntry* entry, uint worker_id) {
132 assert(entry->obj() != NULL, "Double free"); 149 assert(entry->obj() != NULL, "Double free");
133 assert(worker_id < _nlists, "Invalid worker id"); 150 assert(worker_id < _nlists, "Invalid worker id");
151
134 entry->set_obj(NULL); 152 entry->set_obj(NULL);
135 entry->set_hash(0); 153 entry->set_hash(0);
136 _lists[worker_id].add(entry); 154
155 if (_cached[worker_id].length() < _max_list_length) {
156 // Cache is not full
157 _cached[worker_id].add(entry);
158 } else {
159 // Cache is full, add to overflow list for later deletion
160 _overflowed[worker_id].add(entry);
161 }
137 } 162 }
138 163
139 size_t G1StringDedupEntryCache::size() { 164 size_t G1StringDedupEntryCache::size() {
140 size_t size = 0; 165 size_t size = 0;
141 for (size_t i = 0; i < _nlists; i++) { 166 for (size_t i = 0; i < _nlists; i++) {
142 size += _lists[i].length(); 167 size += _cached[i].length();
143 } 168 }
144 return size; 169 return size;
145 } 170 }
146 171
147 void G1StringDedupEntryCache::trim(size_t max_size) { 172 void G1StringDedupEntryCache::delete_overflowed() {
148 size_t cache_size = 0; 173 double start = os::elapsedTime();
174 uintx count = 0;
175
149 for (size_t i = 0; i < _nlists; i++) { 176 for (size_t i = 0; i < _nlists; i++) {
150 G1StringDedupEntryFreeList* list = &_lists[i]; 177 G1StringDedupEntry* entry;
151 cache_size += list->length(); 178
152 while (cache_size > max_size) { 179 {
153 G1StringDedupEntry* entry = list->remove(); 180 // The overflow list can be modified during safepoints, therefore
154 assert(entry != NULL, "Should not be null"); 181 // we temporarily join the suspendible thread set while removing
155 cache_size--; 182 // all entries from the list.
183 SuspendibleThreadSetJoiner sts_join;
184 entry = _overflowed[i].remove_all();
185 }
186
187 // Delete all entries
188 while (entry != NULL) {
189 G1StringDedupEntry* next = entry->next();
156 delete entry; 190 delete entry;
157 } 191 entry = next;
192 count++;
193 }
194 }
195
196 double end = os::elapsedTime();
197 if (PrintStringDeduplicationStatistics) {
198 gclog_or_tty->print_cr("[GC concurrent-string-deduplication, deleted " UINTX_FORMAT " entries, " G1_STRDEDUP_TIME_FORMAT "]", count, end - start);
158 } 199 }
159 } 200 }
160 201
161 G1StringDedupTable* G1StringDedupTable::_table = NULL; 202 G1StringDedupTable* G1StringDedupTable::_table = NULL;
162 G1StringDedupEntryCache* G1StringDedupTable::_entry_cache = NULL; 203 G1StringDedupEntryCache* G1StringDedupTable::_entry_cache = NULL;
190 FREE_C_HEAP_ARRAY(G1StringDedupEntry*, _buckets, mtGC); 231 FREE_C_HEAP_ARRAY(G1StringDedupEntry*, _buckets, mtGC);
191 } 232 }
192 233
193 void G1StringDedupTable::create() { 234 void G1StringDedupTable::create() {
194 assert(_table == NULL, "One string deduplication table allowed"); 235 assert(_table == NULL, "One string deduplication table allowed");
195 _entry_cache = new G1StringDedupEntryCache(); 236 _entry_cache = new G1StringDedupEntryCache((size_t)(_min_size * _max_cache_factor));
196 _table = new G1StringDedupTable(_min_size); 237 _table = new G1StringDedupTable(_min_size);
197 } 238 }
198 239
199 void G1StringDedupTable::add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list) { 240 void G1StringDedupTable::add(typeArrayOop value, unsigned int hash, G1StringDedupEntry** list) {
200 G1StringDedupEntry* entry = _entry_cache->alloc(); 241 G1StringDedupEntry* entry = _entry_cache->alloc();
372 return NULL; 413 return NULL;
373 } 414 }
374 415
375 // Update statistics 416 // Update statistics
376 _resize_count++; 417 _resize_count++;
418
419 // Update max cache size
420 _entry_cache->set_max_size((size_t)(size * _max_cache_factor));
377 421
378 // Allocate the new table. The new table will be populated by workers 422 // Allocate the new table. The new table will be populated by workers
379 // calling unlink_or_oops_do() and finally installed by finish_resize(). 423 // calling unlink_or_oops_do() and finally installed by finish_resize().
380 return new G1StringDedupTable(size, _table->_hash_seed); 424 return new G1StringDedupTable(size, _table->_hash_seed);
381 } 425 }
425 // Scan the partition followed by the sibling partition in the second half of the table 469 // Scan the partition followed by the sibling partition in the second half of the table
426 removed += unlink_or_oops_do(cl, partition_begin, partition_end, worker_id); 470 removed += unlink_or_oops_do(cl, partition_begin, partition_end, worker_id);
427 removed += unlink_or_oops_do(cl, table_half + partition_begin, table_half + partition_end, worker_id); 471 removed += unlink_or_oops_do(cl, table_half + partition_begin, table_half + partition_end, worker_id);
428 } 472 }
429 473
430 // Delayed update avoid contention on the table lock 474 // Delayed update to avoid contention on the table lock
431 if (removed > 0) { 475 if (removed > 0) {
432 MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag); 476 MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag);
433 _table->_entries -= removed; 477 _table->_entries -= removed;
434 _entries_removed += removed; 478 _entries_removed += removed;
435 } 479 }
543 entry1 = (*entry1)->next_addr(); 587 entry1 = (*entry1)->next_addr();
544 } 588 }
545 } 589 }
546 } 590 }
547 591
548 void G1StringDedupTable::trim_entry_cache() { 592 void G1StringDedupTable::clean_entry_cache() {
549 MutexLockerEx ml(StringDedupTable_lock, Mutex::_no_safepoint_check_flag); 593 _entry_cache->delete_overflowed();
550 size_t max_cache_size = (size_t)(_table->_size * _max_cache_factor);
551 _entry_cache->trim(max_cache_size);
552 } 594 }
553 595
554 void G1StringDedupTable::print_statistics(outputStream* st) { 596 void G1StringDedupTable::print_statistics(outputStream* st) {
555 st->print_cr( 597 st->print_cr(
556 " [Table]\n" 598 " [Table]\n"

mercurial