|
1 /* |
|
2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
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 |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 #ifndef SHARE_GC_SHARED_OOPSTORAGEPARSTATE_INLINE_HPP |
|
26 #define SHARE_GC_SHARED_OOPSTORAGEPARSTATE_INLINE_HPP |
|
27 |
|
28 #include "gc/shared/oopStorage.inline.hpp" |
|
29 #include "memory/allocation.hpp" |
|
30 #include "metaprogramming/conditional.hpp" |
|
31 #include "utilities/macros.hpp" |
|
32 |
|
33 #if INCLUDE_ALL_GCS |
|
34 |
|
35 ////////////////////////////////////////////////////////////////////////////// |
|
36 // Support for parallel and optionally concurrent state iteration. |
|
37 // |
|
38 // Parallel iteration is for the exclusive use of the GC. Other iteration |
|
39 // clients must use serial iteration. |
|
40 // |
|
41 // Concurrent Iteration |
|
42 // |
|
43 // Iteration involves the _active_list, which contains all of the blocks owned |
|
44 // by a storage object. This is a doubly-linked list, linked through |
|
45 // dedicated fields in the blocks. |
|
46 // |
|
47 // At most one concurrent ParState can exist at a time for a given storage |
|
48 // object. |
|
49 // |
|
50 // A concurrent ParState sets the associated storage's |
|
51 // _concurrent_iteration_active flag true when the state is constructed, and |
|
52 // sets it false when the state is destroyed. These assignments are made with |
|
53 // _active_mutex locked. Meanwhile, empty block deletion is not done while |
|
54 // _concurrent_iteration_active is true. The flag check and the dependent |
|
55 // removal of a block from the _active_list is performed with _active_mutex |
|
56 // locked. This prevents concurrent iteration and empty block deletion from |
|
57 // interfering with with each other. |
|
58 // |
|
59 // Both allocate() and delete_empty_blocks_concurrent() lock the |
|
60 // _allocate_mutex while performing their respective list manipulations, |
|
61 // preventing them from interfering with each other. |
|
62 // |
|
63 // When allocate() creates a new block, it is added to the front of the |
|
64 // _active_list. Then _active_head is set to the new block. When concurrent |
|
65 // iteration is started (by a parallel worker thread calling the state's |
|
66 // iterate() function), the current _active_head is used as the initial block |
|
67 // for the iteration, with iteration proceeding down the list headed by that |
|
68 // block. |
|
69 // |
|
70 // As a result, the list over which concurrent iteration operates is stable. |
|
71 // However, once the iteration is started, later allocations may add blocks to |
|
72 // the front of the list that won't be examined by the iteration. And while |
|
73 // the list is stable, concurrent allocate() and release() operations may |
|
74 // change the set of allocated entries in a block at any time during the |
|
75 // iteration. |
|
76 // |
|
77 // As a result, a concurrent iteration handler must accept that some |
|
78 // allocations and releases that occur after the iteration started will not be |
|
79 // seen by the iteration. Further, some may overlap examination by the |
|
80 // iteration. To help with this, allocate() and release() have an invariant |
|
81 // that an entry's value must be NULL when it is not in use. |
|
82 // |
|
83 // An in-progress delete_empty_blocks_concurrent() operation can contend with |
|
84 // the start of a concurrent iteration over the _active_mutex. Since both are |
|
85 // under GC control, that potential contention can be eliminated by never |
|
86 // scheduling both operations to run at the same time. |
|
87 // |
|
88 // ParState<concurrent, is_const> |
|
89 // concurrent must be true if iteration is concurrent with the |
|
90 // mutator, false if iteration is at a safepoint. |
|
91 // |
|
92 // is_const must be true if the iteration is over a constant storage |
|
93 // object, false if the iteration may modify the storage object. |
|
94 // |
|
95 // ParState([const] OopStorage* storage) |
|
96 // Construct an object for managing an iteration over storage. For a |
|
97 // concurrent ParState, empty block deletion for the associated storage |
|
98 // is inhibited for the life of the ParState. There can be no more |
|
99 // than one live concurrent ParState at a time for a given storage object. |
|
100 // |
|
101 // template<typename F> void iterate(F f) |
|
102 // Repeatedly claims a block from the associated storage that has |
|
103 // not been processed by this iteration (possibly by other threads), |
|
104 // and applies f to each entry in the claimed block. Assume p is of |
|
105 // type const oop* or oop*, according to is_const. Then f(p) must be |
|
106 // a valid expression whose value is ignored. Concurrent uses must |
|
107 // be prepared for an entry's value to change at any time, due to |
|
108 // mutator activity. |
|
109 // |
|
110 // template<typename Closure> void oops_do(Closure* cl) |
|
111 // Wrapper around iterate, providing an adaptation layer allowing |
|
112 // the use of OopClosures and similar objects for iteration. Assume |
|
113 // p is of type const oop* or oop*, according to is_const. Then |
|
114 // cl->do_oop(p) must be a valid expression whose value is ignored. |
|
115 // Concurrent uses must be prepared for the entry's value to change |
|
116 // at any time, due to mutator activity. |
|
117 // |
|
118 // Optional operations, provided only if !concurrent && !is_const. |
|
119 // These are not provided when is_const, because the storage object |
|
120 // may be modified by the iteration infrastructure, even if the |
|
121 // provided closure doesn't modify the storage object. These are not |
|
122 // provided when concurrent because any pre-filtering behavior by the |
|
123 // iteration infrastructure is inappropriate for concurrent iteration; |
|
124 // modifications of the storage by the mutator could result in the |
|
125 // pre-filtering being applied (successfully or not) to objects that |
|
126 // are unrelated to what the closure finds in the entry. |
|
127 // |
|
128 // template<typename Closure> void weak_oops_do(Closure* cl) |
|
129 // template<typename IsAliveClosure, typename Closure> |
|
130 // void weak_oops_do(IsAliveClosure* is_alive, Closure* cl) |
|
131 // Wrappers around iterate, providing an adaptation layer allowing |
|
132 // the use of is-alive closures and OopClosures for iteration. |
|
133 // Assume p is of type oop*. Then |
|
134 // |
|
135 // - cl->do_oop(p) must be a valid expression whose value is ignored. |
|
136 // |
|
137 // - is_alive->do_object_b(*p) must be a valid expression whose value |
|
138 // is convertible to bool. |
|
139 // |
|
140 // If *p == NULL then neither is_alive nor cl will be invoked for p. |
|
141 // If is_alive->do_object_b(*p) is false, then cl will not be |
|
142 // invoked on p. |
|
143 |
|
144 class OopStorage::BasicParState VALUE_OBJ_CLASS_SPEC { |
|
145 OopStorage* _storage; |
|
146 void* volatile _next_block; |
|
147 bool _concurrent; |
|
148 |
|
149 // Noncopyable. |
|
150 BasicParState(const BasicParState&); |
|
151 BasicParState& operator=(const BasicParState&); |
|
152 |
|
153 void update_iteration_state(bool value); |
|
154 void ensure_iteration_started(); |
|
155 Block* claim_next_block(); |
|
156 |
|
157 // Wrapper for iteration handler; ignore handler result and return true. |
|
158 template<typename F> class AlwaysTrueFn; |
|
159 |
|
160 public: |
|
161 BasicParState(OopStorage* storage, bool concurrent); |
|
162 ~BasicParState(); |
|
163 |
|
164 template<bool is_const, typename F> void iterate(F f) { |
|
165 // Wrap f in ATF so we can use Block::iterate. |
|
166 AlwaysTrueFn<F> atf_f(f); |
|
167 ensure_iteration_started(); |
|
168 typename Conditional<is_const, const Block*, Block*>::type block; |
|
169 while ((block = claim_next_block()) != NULL) { |
|
170 block->iterate(atf_f); |
|
171 } |
|
172 } |
|
173 }; |
|
174 |
|
175 template<typename F> |
|
176 class OopStorage::BasicParState::AlwaysTrueFn VALUE_OBJ_CLASS_SPEC { |
|
177 F _f; |
|
178 |
|
179 public: |
|
180 AlwaysTrueFn(F f) : _f(f) {} |
|
181 |
|
182 template<typename OopPtr> // [const] oop* |
|
183 bool operator()(OopPtr ptr) const { _f(ptr); return true; } |
|
184 }; |
|
185 |
|
186 template<bool concurrent, bool is_const> |
|
187 class OopStorage::ParState VALUE_OBJ_CLASS_SPEC { |
|
188 BasicParState _basic_state; |
|
189 |
|
190 public: |
|
191 ParState(const OopStorage* storage) : |
|
192 // For simplicity, always recorded as non-const. |
|
193 _basic_state(const_cast<OopStorage*>(storage), concurrent) |
|
194 {} |
|
195 |
|
196 template<typename F> |
|
197 void iterate(F f) { |
|
198 _basic_state.template iterate<is_const>(f); |
|
199 } |
|
200 |
|
201 template<typename Closure> |
|
202 void oops_do(Closure* cl) { |
|
203 this->iterate(oop_fn(cl)); |
|
204 } |
|
205 }; |
|
206 |
|
207 template<> |
|
208 class OopStorage::ParState<false, false> VALUE_OBJ_CLASS_SPEC { |
|
209 BasicParState _basic_state; |
|
210 |
|
211 public: |
|
212 ParState(OopStorage* storage) : |
|
213 _basic_state(storage, false) |
|
214 {} |
|
215 |
|
216 template<typename F> |
|
217 void iterate(F f) { |
|
218 _basic_state.template iterate<false>(f); |
|
219 } |
|
220 |
|
221 template<typename Closure> |
|
222 void oops_do(Closure* cl) { |
|
223 this->iterate(oop_fn(cl)); |
|
224 } |
|
225 |
|
226 template<typename Closure> |
|
227 void weak_oops_do(Closure* cl) { |
|
228 this->iterate(skip_null_fn(oop_fn(cl))); |
|
229 } |
|
230 |
|
231 template<typename IsAliveClosure, typename Closure> |
|
232 void weak_oops_do(IsAliveClosure* is_alive, Closure* cl) { |
|
233 this->iterate(if_alive_fn(is_alive, oop_fn(cl))); |
|
234 } |
|
235 }; |
|
236 |
|
237 #endif // INCLUDE_ALL_GCS |
|
238 |
|
239 #endif // include guard |