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

changeset 7653
b6a1bf5222c5
parent 7652
ae374055ebce
child 7994
04ff2f6cd0eb
equal deleted inserted replaced
7652:ae374055ebce 7653:b6a1bf5222c5
1 /* 1 /*
2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2013, 2015, 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.
34 34
35 void G1HotCardCache::initialize(G1RegionToSpaceMapper* card_counts_storage) { 35 void G1HotCardCache::initialize(G1RegionToSpaceMapper* card_counts_storage) {
36 if (default_use_cache()) { 36 if (default_use_cache()) {
37 _use_cache = true; 37 _use_cache = true;
38 38
39 _hot_cache_size = (1 << G1ConcRSLogCacheSize); 39 _hot_cache_size = (size_t)1 << G1ConcRSLogCacheSize;
40 _hot_cache = NEW_C_HEAP_ARRAY(jbyte*, _hot_cache_size, mtGC); 40 _hot_cache = NEW_C_HEAP_ARRAY(jbyte*, _hot_cache_size, mtGC);
41 41
42 _n_hot = 0; 42 reset_hot_cache_internal();
43 _hot_cache_idx = 0;
44 43
45 // For refining the cards in the hot cache in parallel 44 // For refining the cards in the hot cache in parallel
46 _hot_cache_par_chunk_size = (int)(ParallelGCThreads > 0 ? ClaimChunkSize : _hot_cache_size); 45 _hot_cache_par_chunk_size = (int)(ParallelGCThreads > 0 ? ClaimChunkSize : _hot_cache_size);
47 _hot_cache_par_claimed_idx = 0; 46 _hot_cache_par_claimed_idx = 0;
48 47
62 if (!_card_counts.is_hot(count)) { 61 if (!_card_counts.is_hot(count)) {
63 // The card is not hot so do not store it in the cache; 62 // The card is not hot so do not store it in the cache;
64 // return it for immediate refining. 63 // return it for immediate refining.
65 return card_ptr; 64 return card_ptr;
66 } 65 }
66 // Otherwise, the card is hot.
67 size_t index = Atomic::add_ptr((intptr_t)1, (volatile intptr_t*)&_hot_cache_idx) - 1;
68 size_t masked_index = index & (_hot_cache_size - 1);
69 jbyte* current_ptr = _hot_cache[masked_index];
67 70
68 // Otherwise, the card is hot. 71 // Try to store the new card pointer into the cache. Compare-and-swap to guard
69 jbyte* res = NULL; 72 // against the unlikely event of a race resulting in another card pointer to
70 MutexLockerEx x(HotCardCache_lock, Mutex::_no_safepoint_check_flag); 73 // have already been written to the cache. In this case we will return
71 if (_n_hot == _hot_cache_size) { 74 // card_ptr in favor of the other option, which would be starting over. This
72 res = _hot_cache[_hot_cache_idx]; 75 // should be OK since card_ptr will likely be the older card already when/if
73 _n_hot--; 76 // this ever happens.
74 } 77 jbyte* previous_ptr = (jbyte*)Atomic::cmpxchg_ptr(card_ptr,
75 78 &_hot_cache[masked_index],
76 // Now _n_hot < _hot_cache_size, and we can insert at _hot_cache_idx. 79 current_ptr);
77 _hot_cache[_hot_cache_idx] = card_ptr; 80 return (previous_ptr == current_ptr) ? previous_ptr : card_ptr;
78 _hot_cache_idx++;
79
80 if (_hot_cache_idx == _hot_cache_size) {
81 // Wrap around
82 _hot_cache_idx = 0;
83 }
84 _n_hot++;
85
86 return res;
87 } 81 }
88 82
89 void G1HotCardCache::drain(uint worker_i, 83 void G1HotCardCache::drain(uint worker_i,
90 G1RemSet* g1rs, 84 G1RemSet* g1rs,
91 DirtyCardQueue* into_cset_dcq) { 85 DirtyCardQueue* into_cset_dcq) {
94 return; 88 return;
95 } 89 }
96 90
97 assert(_hot_cache != NULL, "Logic"); 91 assert(_hot_cache != NULL, "Logic");
98 assert(!use_cache(), "cache should be disabled"); 92 assert(!use_cache(), "cache should be disabled");
99 int start_idx; 93 while (_hot_cache_par_claimed_idx < _hot_cache_size) {
94 size_t end_idx = Atomic::add_ptr((intptr_t)_hot_cache_par_chunk_size,
95 (volatile intptr_t*)&_hot_cache_par_claimed_idx);
96 size_t start_idx = end_idx - _hot_cache_par_chunk_size;
97 // The current worker has successfully claimed the chunk [start_idx..end_idx)
98 end_idx = MIN2(end_idx, _hot_cache_size);
99 for (size_t i = start_idx; i < end_idx; i++) {
100 jbyte* card_ptr = _hot_cache[i];
101 if (card_ptr != NULL) {
102 if (g1rs->refine_card(card_ptr, worker_i, true)) {
103 // The part of the heap spanned by the card contains references
104 // that point into the current collection set.
105 // We need to record the card pointer in the DirtyCardQueueSet
106 // that we use for such cards.
107 //
108 // The only time we care about recording cards that contain
109 // references that point into the collection set is during
110 // RSet updating while within an evacuation pause.
111 // In this case worker_i should be the id of a GC worker thread
112 assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
113 assert(worker_i < ParallelGCThreads,
114 err_msg("incorrect worker id: %u", worker_i));
100 115
101 while ((start_idx = _hot_cache_par_claimed_idx) < _n_hot) { // read once 116 into_cset_dcq->enqueue(card_ptr);
102 int end_idx = start_idx + _hot_cache_par_chunk_size;
103
104 if (start_idx ==
105 Atomic::cmpxchg(end_idx, &_hot_cache_par_claimed_idx, start_idx)) {
106 // The current worker has successfully claimed the chunk [start_idx..end_idx)
107 end_idx = MIN2(end_idx, _n_hot);
108 for (int i = start_idx; i < end_idx; i++) {
109 jbyte* card_ptr = _hot_cache[i];
110 if (card_ptr != NULL) {
111 if (g1rs->refine_card(card_ptr, worker_i, true)) {
112 // The part of the heap spanned by the card contains references
113 // that point into the current collection set.
114 // We need to record the card pointer in the DirtyCardQueueSet
115 // that we use for such cards.
116 //
117 // The only time we care about recording cards that contain
118 // references that point into the collection set is during
119 // RSet updating while within an evacuation pause.
120 // In this case worker_i should be the id of a GC worker thread
121 assert(SafepointSynchronize::is_at_safepoint(), "Should be at a safepoint");
122 assert(worker_i < (ParallelGCThreads == 0 ? 1 : ParallelGCThreads),
123 err_msg("incorrect worker id: "UINT32_FORMAT, worker_i));
124
125 into_cset_dcq->enqueue(card_ptr);
126 }
127 } 117 }
118 } else {
119 break;
128 } 120 }
129 } 121 }
130 } 122 }
123
131 // The existing entries in the hot card cache, which were just refined 124 // The existing entries in the hot card cache, which were just refined
132 // above, are discarded prior to re-enabling the cache near the end of the GC. 125 // above, are discarded prior to re-enabling the cache near the end of the GC.
133 } 126 }
134 127
135 void G1HotCardCache::reset_card_counts(HeapRegion* hr) { 128 void G1HotCardCache::reset_card_counts(HeapRegion* hr) {

mercurial