23
23
24
24
#include " precompiled.hpp"
25
25
#include " classfile/classLoaderData.hpp"
26
- #include " classfile/classLoaderDataGraph .hpp"
26
+ #include " gc/shared/taskqueue.inline .hpp"
27
27
#include " gc/z/zAddress.inline.hpp"
28
- #include " gc/z/zBarrier.inline.hpp"
29
28
#include " gc/z/zGlobals.hpp"
30
29
#include " gc/z/zGranuleMap.inline.hpp"
31
30
#include " gc/z/zHeapIterator.hpp"
31
+ #include " gc/z/zLock.inline.hpp"
32
32
#include " gc/z/zOop.inline.hpp"
33
- #include " gc/z/zRootsIterator.hpp"
34
- #include " gc/z/zStat.hpp"
35
33
#include " memory/iterator.inline.hpp"
36
34
#include " runtime/stackWatermarkSet.hpp"
37
35
#include " utilities/bitMap.inline.hpp"
38
- #include " utilities/stack.inline.hpp"
39
36
40
37
class ZHeapIteratorBitMap : public CHeapObj <mtGC> {
41
38
private:
42
- CHeapBitMap _map ;
39
+ CHeapBitMap _bitmap ;
43
40
44
41
public:
45
42
ZHeapIteratorBitMap (size_t size_in_bits) :
46
- _map (size_in_bits) {}
43
+ _bitmap (size_in_bits, mtGC ) {}
47
44
48
45
bool try_set_bit (size_t index) {
49
- if (_map.at (index )) {
50
- return false ;
46
+ return _bitmap.par_set_bit (index );
47
+ }
48
+ };
49
+
50
+ class ZHeapIteratorContext {
51
+ private:
52
+ ZHeapIterator* const _iter;
53
+ ZHeapIteratorQueue* const _queue;
54
+ ZHeapIteratorArrayQueue* const _array_queue;
55
+ const uint _worker_id;
56
+ ZStatTimerDisable _timer_disable;
57
+
58
+ public:
59
+ ZHeapIteratorContext (ZHeapIterator* iter, uint worker_id) :
60
+ _iter (iter),
61
+ _queue (_iter->_queues.queue(worker_id)),
62
+ _array_queue (_iter->_array_queues.queue(worker_id)),
63
+ _worker_id (worker_id) {}
64
+
65
+ void mark_and_push (oop obj) const {
66
+ if (_iter->mark_object (obj)) {
67
+ _queue->push (obj);
51
68
}
69
+ }
70
+
71
+ void push_array (const ObjArrayTask& array) const {
72
+ _array_queue->push (array);
73
+ }
74
+
75
+ bool pop (oop& obj) const {
76
+ return _queue->pop_overflow (obj) || _queue->pop_local (obj);
77
+ }
78
+
79
+ bool pop_array (ObjArrayTask& array) const {
80
+ return _array_queue->pop_overflow (array) || _array_queue->pop_local (array);
81
+ }
52
82
53
- _map.set_bit (index );
54
- return true ;
83
+ bool steal (oop& obj) const {
84
+ return _iter->_queues .steal (_worker_id, obj);
85
+ }
86
+
87
+ bool steal_array (ObjArrayTask& array) const {
88
+ return _iter->_array_queues .steal (_worker_id, array);
89
+ }
90
+
91
+ bool is_drained () const {
92
+ return _queue->is_empty () && _array_queue->is_empty ();
55
93
}
56
94
};
57
95
58
96
template <bool Concurrent, bool Weak>
59
97
class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure {
60
98
private:
61
- ZHeapIterator* const _iter ;
99
+ const ZHeapIteratorContext& _context ;
62
100
63
101
oop load_oop (oop* p) {
64
102
if (Weak) {
@@ -73,12 +111,12 @@ class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure {
73
111
}
74
112
75
113
public:
76
- ZHeapIteratorRootOopClosure (ZHeapIterator* iter ) :
77
- _iter (iter ) {}
114
+ ZHeapIteratorRootOopClosure (const ZHeapIteratorContext& context ) :
115
+ _context (context ) {}
78
116
79
117
virtual void do_oop (oop* p) {
80
118
const oop obj = load_oop (p);
81
- _iter-> push (obj);
119
+ _context. mark_and_push (obj);
82
120
}
83
121
84
122
virtual void do_oop (narrowOop* p) {
@@ -94,8 +132,8 @@ class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure {
94
132
template <bool VisitReferents>
95
133
class ZHeapIteratorOopClosure : public ClaimMetadataVisitingOopIterateClosure {
96
134
private:
97
- ZHeapIterator* const _iter ;
98
- const oop _base;
135
+ const ZHeapIteratorContext& _context ;
136
+ const oop _base;
99
137
100
138
oop load_oop (oop* p) {
101
139
if (VisitReferents) {
@@ -106,9 +144,9 @@ class ZHeapIteratorOopClosure : public ClaimMetadataVisitingOopIterateClosure {
106
144
}
107
145
108
146
public:
109
- ZHeapIteratorOopClosure (ZHeapIterator* iter , oop base) :
147
+ ZHeapIteratorOopClosure (const ZHeapIteratorContext& context , oop base) :
110
148
ClaimMetadataVisitingOopIterateClosure (ClassLoaderData::_claim_other),
111
- _iter (iter ),
149
+ _context (context ),
112
150
_base (base) {}
113
151
114
152
virtual ReferenceIterationMode reference_iteration_mode () {
@@ -117,7 +155,7 @@ class ZHeapIteratorOopClosure : public ClaimMetadataVisitingOopIterateClosure {
117
155
118
156
virtual void do_oop (oop* p) {
119
157
const oop obj = load_oop (p);
120
- _iter-> push (obj);
158
+ _context. mark_and_push (obj);
121
159
}
122
160
123
161
virtual void do_oop (narrowOop* p) {
@@ -131,16 +169,50 @@ class ZHeapIteratorOopClosure : public ClaimMetadataVisitingOopIterateClosure {
131
169
#endif
132
170
};
133
171
134
- ZHeapIterator::ZHeapIterator () :
135
- _visit_stack(),
136
- _visit_map(ZAddressOffsetMax) {}
172
+ ZHeapIterator::ZHeapIterator (uint nworkers, bool visit_weaks) :
173
+ _visit_weaks(visit_weaks),
174
+ _timer_disable(),
175
+ _bitmaps(ZAddressOffsetMax),
176
+ _bitmaps_lock(),
177
+ _queues(nworkers),
178
+ _array_queues(nworkers),
179
+ _roots(),
180
+ _concurrent_roots(),
181
+ _weak_roots(),
182
+ _concurrent_weak_roots(),
183
+ _terminator(nworkers, &_queues) {
184
+
185
+ // Create queues
186
+ for (uint i = 0 ; i < _queues.size (); i++) {
187
+ ZHeapIteratorQueue* const queue = new ZHeapIteratorQueue ();
188
+ queue->initialize ();
189
+ _queues.register_queue (i, queue);
190
+ }
191
+
192
+ // Create array queues
193
+ for (uint i = 0 ; i < _array_queues.size (); i++) {
194
+ ZHeapIteratorArrayQueue* const array_queue = new ZHeapIteratorArrayQueue ();
195
+ array_queue->initialize ();
196
+ _array_queues.register_queue (i, array_queue);
197
+ }
198
+ }
137
199
138
200
ZHeapIterator::~ZHeapIterator () {
139
- ZVisitMapIterator iter (&_visit_map);
140
- for (ZHeapIteratorBitMap* map; iter.next (&map);) {
141
- delete map;
201
+ // Destroy bitmaps
202
+ ZHeapIteratorBitMapsIterator iter (&_bitmaps);
203
+ for (ZHeapIteratorBitMap* bitmap; iter.next (&bitmap);) {
204
+ delete bitmap;
205
+ }
206
+
207
+ // Destroy array queues
208
+ for (uint i = 0 ; i < _array_queues.size (); i++) {
209
+ delete _array_queues.queue (i);
210
+ }
211
+
212
+ // Destroy queues
213
+ for (uint i = 0 ; i < _queues.size (); i++) {
214
+ delete _queues.queue (i);
142
215
}
143
- ClassLoaderDataGraph::clear_claimed_marks (ClassLoaderData::_claim_other);
144
216
}
145
217
146
218
static size_t object_index_max () {
@@ -154,75 +226,137 @@ static size_t object_index(oop obj) {
154
226
return (offset & mask) >> ZObjectAlignmentSmallShift;
155
227
}
156
228
157
- ZHeapIteratorBitMap* ZHeapIterator::object_map (oop obj) {
229
+ ZHeapIteratorBitMap* ZHeapIterator::object_bitmap (oop obj) {
158
230
const uintptr_t offset = ZAddress::offset (ZOop::to_address (obj));
159
- ZHeapIteratorBitMap* map = _visit_map.get (offset);
160
- if (map == NULL ) {
161
- map = new ZHeapIteratorBitMap (object_index_max ());
162
- _visit_map.put (offset, map);
231
+ ZHeapIteratorBitMap* bitmap = _bitmaps.get_acquire (offset);
232
+ if (bitmap == NULL ) {
233
+ ZLocker<ZLock> locker (&_bitmaps_lock);
234
+ bitmap = _bitmaps.get (offset);
235
+ if (bitmap == NULL ) {
236
+ // Install new bitmap
237
+ bitmap = new ZHeapIteratorBitMap (object_index_max ());
238
+ _bitmaps.release_put (offset, bitmap);
239
+ }
163
240
}
164
241
165
- return map ;
242
+ return bitmap ;
166
243
}
167
244
168
- void ZHeapIterator::push (oop obj) {
245
+ bool ZHeapIterator::mark_object (oop obj) {
169
246
if (obj == NULL ) {
170
- // Ignore
171
- return ;
247
+ return false ;
172
248
}
173
249
174
- ZHeapIteratorBitMap* const map = object_map (obj);
250
+ ZHeapIteratorBitMap* const bitmap = object_bitmap (obj);
175
251
const size_t index = object_index (obj);
176
- if (!map->try_set_bit (index )) {
177
- // Already pushed
178
- return ;
179
- }
180
-
181
- // Push
182
- _visit_stack.push (obj);
252
+ return bitmap->try_set_bit (index );
183
253
}
184
254
185
- template <typename RootsIterator, bool Concurrent, bool Weak>
186
- void ZHeapIterator::push_roots () {
187
- ZHeapIteratorRootOopClosure<Concurrent, Weak> cl (this );
188
- RootsIterator roots;
189
- roots.oops_do (&cl);
255
+ template <bool Concurrent, bool Weak, typename RootsIterator>
256
+ void ZHeapIterator::push_roots (const ZHeapIteratorContext& context, RootsIterator& iter) {
257
+ ZHeapIteratorRootOopClosure<Concurrent, Weak> cl (context);
258
+ iter.oops_do (&cl);
190
259
}
191
260
192
261
template <bool VisitReferents>
193
- void ZHeapIterator::push_fields ( oop obj) {
194
- ZHeapIteratorOopClosure<VisitReferents> cl (this , obj);
262
+ void ZHeapIterator::follow_object ( const ZHeapIteratorContext& context, oop obj) {
263
+ ZHeapIteratorOopClosure<VisitReferents> cl (context , obj);
195
264
obj->oop_iterate (&cl);
196
265
}
197
266
267
+ void ZHeapIterator::follow_array (const ZHeapIteratorContext& context, oop obj) {
268
+ // Follow klass
269
+ ZHeapIteratorOopClosure<false /* VisitReferents */ > cl (context, obj);
270
+ cl.do_klass (obj->klass ());
271
+
272
+ // Push array chunk
273
+ context.push_array (ObjArrayTask (obj, 0 /* index */ ));
274
+ }
275
+
276
+ void ZHeapIterator::follow_array_chunk (const ZHeapIteratorContext& context, const ObjArrayTask& array) {
277
+ const objArrayOop obj = objArrayOop (array.obj ());
278
+ const int length = obj->length ();
279
+ const int start = array.index ();
280
+ const int stride = MIN2<int >(length - start, ObjArrayMarkingStride);
281
+ const int end = start + stride;
282
+
283
+ // Push remaining array chunk first
284
+ if (end < length) {
285
+ context.push_array (ObjArrayTask (obj, end));
286
+ }
287
+
288
+ // Follow array chunk
289
+ ZHeapIteratorOopClosure<false /* VisitReferents */ > cl (context, obj);
290
+ obj->oop_iterate_range (&cl, start, end);
291
+ }
292
+
198
293
template <bool VisitWeaks>
199
- void ZHeapIterator::objects_do (ObjectClosure* cl) {
200
- ZStatTimerDisable disable;
294
+ void ZHeapIterator::visit_and_follow (const ZHeapIteratorContext& context, ObjectClosure* cl, oop obj) {
295
+ // Visit
296
+ cl->do_object (obj);
201
297
202
- // Push roots to visit
203
- push_roots<ZRootsIterator, false /* Concurrent */ , false /* Weak */ >();
204
- push_roots<ZConcurrentRootsIteratorClaimOther, true /* Concurrent */ , false /* Weak */ >();
205
- if (VisitWeaks) {
206
- push_roots<ZWeakRootsIterator, false /* Concurrent */ , true /* Weak */ >();
207
- push_roots<ZConcurrentWeakRootsIterator, true /* Concurrent */ , true /* Weak */ >();
298
+ // Follow
299
+ if (obj->is_objArray ()) {
300
+ follow_array (context, obj);
301
+ } else {
302
+ follow_object<VisitWeaks>(context, obj);
208
303
}
304
+ }
209
305
210
- // Drain stack
211
- while (!_visit_stack.is_empty ()) {
212
- const oop obj = _visit_stack.pop ();
306
+ template <bool VisitWeaks>
307
+ void ZHeapIterator::drain (const ZHeapIteratorContext& context, ObjectClosure* cl) {
308
+ ObjArrayTask array;
309
+ oop obj;
213
310
214
- // Visit object
215
- cl->do_object (obj);
311
+ do {
312
+ while (context.pop (obj)) {
313
+ visit_and_follow<VisitWeaks>(context, cl, obj);
314
+ }
216
315
217
- // Push fields to visit
218
- push_fields<VisitWeaks>(obj);
316
+ if (context.pop_array (array)) {
317
+ follow_array_chunk (context, array);
318
+ }
319
+ } while (!context.is_drained ());
320
+ }
321
+
322
+ template <bool VisitWeaks>
323
+ void ZHeapIterator::steal (const ZHeapIteratorContext& context, ObjectClosure* cl) {
324
+ ObjArrayTask array;
325
+ oop obj;
326
+
327
+ if (context.steal_array (array)) {
328
+ follow_array_chunk (context, array);
329
+ } else if (context.steal (obj)) {
330
+ visit_and_follow<VisitWeaks>(context, cl, obj);
331
+ }
332
+ }
333
+
334
+ template <bool VisitWeaks>
335
+ void ZHeapIterator::drain_and_steal (const ZHeapIteratorContext& context, ObjectClosure* cl) {
336
+ do {
337
+ drain<VisitWeaks>(context, cl);
338
+ steal<VisitWeaks>(context, cl);
339
+ } while (!context.is_drained () || !_terminator.offer_termination ());
340
+ }
341
+
342
+ template <bool VisitWeaks>
343
+ void ZHeapIterator::object_iterate_inner (const ZHeapIteratorContext& context, ObjectClosure* cl) {
344
+ push_roots<false /* Concurrent */ , false /* Weak */ >(context, _roots);
345
+ push_roots<true /* Concurrent */ , false /* Weak */ >(context, _concurrent_roots);
346
+ if (VisitWeaks) {
347
+ push_roots<false /* Concurrent */ , true /* Weak */ >(context, _weak_roots);
348
+ push_roots<true /* Concurrent */ , true /* Weak */ >(context, _concurrent_weak_roots);
219
349
}
350
+
351
+ drain_and_steal<VisitWeaks>(context, cl);
220
352
}
221
353
222
- void ZHeapIterator::objects_do (ObjectClosure* cl, bool visit_weaks) {
223
- if (visit_weaks) {
224
- objects_do<true /* VisitWeaks */ >(cl);
354
+ void ZHeapIterator::object_iterate (ObjectClosure* cl, uint worker_id) {
355
+ ZHeapIteratorContext context (this , worker_id);
356
+
357
+ if (_visit_weaks) {
358
+ object_iterate_inner<true /* VisitWeaks */ >(context, cl);
225
359
} else {
226
- objects_do <false /* VisitWeaks */ >(cl);
360
+ object_iterate_inner <false /* VisitWeaks */ >(context, cl);
227
361
}
228
362
}
1 commit comments
bridgekeeper[bot] commentedon Oct 12, 2020
Review
Issues