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

changeset 6992
2c6ef90f030a
parent 6932
828056cf311f
child 6993
870c03421152
equal deleted inserted replaced
6991:882004b9e7e1 6992:2c6ef90f030a
28 #include "gc_implementation/g1/g1CodeCacheRemSet.hpp" 28 #include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
29 #include "memory/iterator.hpp" 29 #include "memory/iterator.hpp"
30 30
31 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC 31 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
32 32
33 G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL) { 33 G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL), _free(NULL) {
34 _top = bottom(); 34 _top = bottom();
35 } 35 }
36 36
37 void G1CodeRootChunk::reset() { 37 void G1CodeRootChunk::reset() {
38 _next = _prev = NULL; 38 _next = _prev = NULL;
39 _free = NULL;
39 _top = bottom(); 40 _top = bottom();
40 } 41 }
41 42
42 void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) { 43 void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
43 nmethod** cur = bottom(); 44 NmethodOrLink* cur = bottom();
44 while (cur != _top) { 45 while (cur != _top) {
45 cl->do_code_blob(*cur); 46 if (is_nmethod(cur)) {
47 cl->do_code_blob(cur->_nmethod);
48 }
46 cur++; 49 cur++;
47 } 50 }
51 }
52
53 bool G1CodeRootChunk::remove_lock_free(nmethod* method) {
54 NmethodOrLink* cur = bottom();
55
56 for (NmethodOrLink* cur = bottom(); cur != _top; cur++) {
57 if (cur->_nmethod == method) {
58 bool result = Atomic::cmpxchg_ptr(NULL, &cur->_nmethod, method) == method;
59
60 if (!result) {
61 // Someone else cleared out this entry.
62 return false;
63 }
64
65 // The method was cleared. Time to link it into the free list.
66 NmethodOrLink* prev_free;
67 do {
68 prev_free = (NmethodOrLink*)_free;
69 cur->_link = prev_free;
70 } while (Atomic::cmpxchg_ptr(cur, &_free, prev_free) != prev_free);
71
72 return true;
73 }
74 }
75
76 return false;
48 } 77 }
49 78
50 G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) { 79 G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
51 _free_list.initialize(); 80 _free_list.initialize();
52 _free_list.set_size(G1CodeRootChunk::word_size()); 81 _free_list.set_size(G1CodeRootChunk::word_size());
138 clear(); 167 clear();
139 } 168 }
140 169
141 void G1CodeRootSet::add(nmethod* method) { 170 void G1CodeRootSet::add(nmethod* method) {
142 if (!contains(method)) { 171 if (!contains(method)) {
143 // Try to add the nmethod. If there is not enough space, get a new chunk. 172 // Find the first chunk thatisn't full.
144 if (_list.head() == NULL || _list.head()->is_full()) { 173 G1CodeRootChunk* cur = _list.head();
145 G1CodeRootChunk* cur = new_chunk(); 174 while (cur != NULL) {
175 if (!cur->is_full()) {
176 break;
177 }
178 cur = cur->next();
179 }
180
181 // All chunks are full, get a new chunk.
182 if (cur == NULL) {
183 cur = new_chunk();
146 _list.return_chunk_at_head(cur); 184 _list.return_chunk_at_head(cur);
147 } 185 }
148 bool result = _list.head()->add(method); 186
187 // Add the nmethod.
188 bool result = cur->add(method);
189
149 guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method)); 190 guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
191
150 _length++; 192 _length++;
151 } 193 }
152 } 194 }
153 195
154 void G1CodeRootSet::remove(nmethod* method) { 196 void G1CodeRootSet::remove_lock_free(nmethod* method) {
155 G1CodeRootChunk* found = find(method); 197 G1CodeRootChunk* found = find(method);
156 if (found != NULL) { 198 if (found != NULL) {
157 bool result = found->remove(method); 199 bool result = found->remove_lock_free(method);
158 guarantee(result, err_msg("could not find nmethod "PTR_FORMAT" during removal although we previously found it", method)); 200 if (result) {
159 // eventually free completely emptied chunk 201 Atomic::dec_ptr((volatile intptr_t*)&_length);
160 if (found->is_empty()) { 202 }
161 _list.remove_chunk(found);
162 free(found);
163 }
164 _length--;
165 } 203 }
166 assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method)); 204 assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
167 } 205 }
168 206
169 nmethod* G1CodeRootSet::pop() { 207 nmethod* G1CodeRootSet::pop() {
170 do { 208 while (true) {
171 G1CodeRootChunk* cur = _list.head(); 209 G1CodeRootChunk* cur = _list.head();
172 if (cur == NULL) { 210 if (cur == NULL) {
173 assert(_length == 0, "when there are no chunks, there should be no elements"); 211 assert(_length == 0, "when there are no chunks, there should be no elements");
174 return NULL; 212 return NULL;
175 } 213 }
178 _length--; 216 _length--;
179 return result; 217 return result;
180 } else { 218 } else {
181 free(_list.get_chunk_at_head()); 219 free(_list.get_chunk_at_head());
182 } 220 }
183 } while (true); 221 }
184 } 222 }
185 223
186 G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) { 224 G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
187 G1CodeRootChunk* cur = _list.head(); 225 G1CodeRootChunk* cur = _list.head();
188 while (cur != NULL) { 226 while (cur != NULL) {

mercurial