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(); |