Mercurial > hg > graal-compiler
comparison src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp @ 20278:2c6ef90f030a
8049421: G1 Class Unloading after completing a concurrent mark cycle
Reviewed-by: tschatzl, ehelin, brutisso, coleenp, roland, iveresov
Contributed-by: stefan.karlsson@oracle.com, mikael.gerdin@oracle.com
author | stefank |
---|---|
date | Mon, 07 Jul 2014 10:12:40 +0200 |
parents | 828056cf311f |
children | 7baf47cb97cb |
comparison
equal
deleted
inserted
replaced
20277:882004b9e7e1 | 20278:2c6ef90f030a |
---|---|
29 #include "memory/freeList.hpp" | 29 #include "memory/freeList.hpp" |
30 #include "runtime/globals.hpp" | 30 #include "runtime/globals.hpp" |
31 | 31 |
32 class CodeBlobClosure; | 32 class CodeBlobClosure; |
33 | 33 |
34 // The elements of the G1CodeRootChunk is either: | |
35 // 1) nmethod pointers | |
36 // 2) nodes in an internally chained free list | |
37 typedef union { | |
38 nmethod* _nmethod; | |
39 void* _link; | |
40 } NmethodOrLink; | |
41 | |
34 class G1CodeRootChunk : public CHeapObj<mtGC> { | 42 class G1CodeRootChunk : public CHeapObj<mtGC> { |
35 private: | 43 private: |
36 static const int NUM_ENTRIES = 32; | 44 static const int NUM_ENTRIES = 32; |
37 public: | 45 public: |
38 G1CodeRootChunk* _next; | 46 G1CodeRootChunk* _next; |
39 G1CodeRootChunk* _prev; | 47 G1CodeRootChunk* _prev; |
40 | 48 |
41 nmethod** _top; | 49 NmethodOrLink* _top; |
42 | 50 // First free position within the chunk. |
43 nmethod* _data[NUM_ENTRIES]; | 51 volatile NmethodOrLink* _free; |
44 | 52 |
45 nmethod** bottom() const { | 53 NmethodOrLink _data[NUM_ENTRIES]; |
46 return (nmethod**) &(_data[0]); | 54 |
47 } | 55 NmethodOrLink* bottom() const { |
48 | 56 return (NmethodOrLink*) &(_data[0]); |
49 nmethod** end() const { | 57 } |
50 return (nmethod**) &(_data[NUM_ENTRIES]); | 58 |
59 NmethodOrLink* end() const { | |
60 return (NmethodOrLink*) &(_data[NUM_ENTRIES]); | |
61 } | |
62 | |
63 bool is_link(NmethodOrLink* nmethod_or_link) { | |
64 return nmethod_or_link->_link == NULL || | |
65 (bottom() <= nmethod_or_link->_link | |
66 && nmethod_or_link->_link < end()); | |
67 } | |
68 | |
69 bool is_nmethod(NmethodOrLink* nmethod_or_link) { | |
70 return !is_link(nmethod_or_link); | |
51 } | 71 } |
52 | 72 |
53 public: | 73 public: |
54 G1CodeRootChunk(); | 74 G1CodeRootChunk(); |
55 ~G1CodeRootChunk() {} | 75 ~G1CodeRootChunk() {} |
83 bool is_empty() const { | 103 bool is_empty() const { |
84 return _top == bottom(); | 104 return _top == bottom(); |
85 } | 105 } |
86 | 106 |
87 bool is_full() const { | 107 bool is_full() const { |
88 return _top == (nmethod**)end(); | 108 return _top == end() && _free == NULL; |
89 } | 109 } |
90 | 110 |
91 bool contains(nmethod* method) { | 111 bool contains(nmethod* method) { |
92 nmethod** cur = bottom(); | 112 NmethodOrLink* cur = bottom(); |
93 while (cur != _top) { | 113 while (cur != _top) { |
94 if (*cur == method) return true; | 114 if (cur->_nmethod == method) return true; |
95 cur++; | 115 cur++; |
96 } | 116 } |
97 return false; | 117 return false; |
98 } | 118 } |
99 | 119 |
100 bool add(nmethod* method) { | 120 bool add(nmethod* method) { |
101 if (is_full()) return false; | 121 if (is_full()) { |
102 *_top = method; | 122 return false; |
103 _top++; | 123 } |
124 | |
125 if (_free != NULL) { | |
126 // Take from internally chained free list | |
127 NmethodOrLink* first_free = (NmethodOrLink*)_free; | |
128 _free = (NmethodOrLink*)_free->_link; | |
129 first_free->_nmethod = method; | |
130 } else { | |
131 // Take from top. | |
132 _top->_nmethod = method; | |
133 _top++; | |
134 } | |
135 | |
104 return true; | 136 return true; |
105 } | 137 } |
106 | 138 |
107 bool remove(nmethod* method) { | 139 bool remove_lock_free(nmethod* method); |
108 nmethod** cur = bottom(); | 140 |
109 while (cur != _top) { | 141 void nmethods_do(CodeBlobClosure* blk); |
110 if (*cur == method) { | 142 |
111 memmove(cur, cur + 1, (_top - (cur + 1)) * sizeof(nmethod**)); | 143 nmethod* pop() { |
112 _top--; | 144 if (_free != NULL) { |
113 return true; | 145 // Kill the free list. |
146 _free = NULL; | |
147 } | |
148 | |
149 while (!is_empty()) { | |
150 _top--; | |
151 if (is_nmethod(_top)) { | |
152 return _top->_nmethod; | |
114 } | 153 } |
115 cur++; | 154 } |
116 } | 155 |
117 return false; | 156 return NULL; |
118 } | |
119 | |
120 void nmethods_do(CodeBlobClosure* blk); | |
121 | |
122 nmethod* pop() { | |
123 if (is_empty()) { | |
124 return NULL; | |
125 } | |
126 _top--; | |
127 return *_top; | |
128 } | 157 } |
129 }; | 158 }; |
130 | 159 |
131 // Manages free chunks. | 160 // Manages free chunks. |
132 class G1CodeRootChunkManager VALUE_OBJ_CLASS_SPEC { | 161 class G1CodeRootChunkManager VALUE_OBJ_CLASS_SPEC { |
191 | 220 |
192 // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this | 221 // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this |
193 // method is likely to be repeatedly called with the same nmethod. | 222 // method is likely to be repeatedly called with the same nmethod. |
194 void add(nmethod* method); | 223 void add(nmethod* method); |
195 | 224 |
196 void remove(nmethod* method); | 225 void remove_lock_free(nmethod* method); |
197 nmethod* pop(); | 226 nmethod* pop(); |
198 | 227 |
199 bool contains(nmethod* method); | 228 bool contains(nmethod* method); |
200 | 229 |
201 void clear(); | 230 void clear(); |