Skip to content

Commit 94af3c2

Browse files
committed
8329203: Parallel: Investigate Mark-Compact for Full GC to decrease memory usage
Reviewed-by: rkennke, gli
1 parent 1e5a278 commit 94af3c2

File tree

9 files changed

+517
-1135
lines changed

9 files changed

+517
-1135
lines changed

src/hotspot/share/gc/parallel/parMarkBitMap.cpp

Lines changed: 1 addition & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ bool
3737
ParMarkBitMap::initialize(MemRegion covered_region)
3838
{
3939
const idx_t bits = bits_required(covered_region);
40-
// The bits will be divided evenly between two bitmaps; each of them should be
41-
// an integral number of words.
42-
assert(is_aligned(bits, (BitsPerWord * 2)), "region size unaligned");
4340

4441
const size_t words = bits / BitsPerWord;
4542
const size_t raw_bytes = words * sizeof(idx_t);
@@ -61,8 +58,7 @@ ParMarkBitMap::initialize(MemRegion covered_region)
6158
_region_start = covered_region.start();
6259
_region_size = covered_region.word_size();
6360
BitMap::bm_word_t* map = (BitMap::bm_word_t*)_virtual_space->reserved_low_addr();
64-
_beg_bits = BitMapView(map, bits / 2);
65-
_end_bits = BitMapView(map + words / 2, bits / 2);
61+
_beg_bits = BitMapView(map, bits);
6662
return true;
6763
}
6864

@@ -77,176 +73,6 @@ ParMarkBitMap::initialize(MemRegion covered_region)
7773
return false;
7874
}
7975

80-
bool
81-
ParMarkBitMap::mark_obj(HeapWord* addr, size_t size)
82-
{
83-
const idx_t beg_bit = addr_to_bit(addr);
84-
if (_beg_bits.par_set_bit(beg_bit)) {
85-
const idx_t end_bit = addr_to_bit(addr + size - 1);
86-
bool end_bit_ok = _end_bits.par_set_bit(end_bit);
87-
assert(end_bit_ok, "concurrency problem");
88-
return true;
89-
}
90-
return false;
91-
}
92-
93-
inline bool
94-
ParMarkBitMap::is_live_words_in_range_in_cache(ParCompactionManager* cm, HeapWord* beg_addr) const {
95-
return cm->last_query_begin() == beg_addr;
96-
}
97-
98-
inline void
99-
ParMarkBitMap::update_live_words_in_range_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj, size_t result) const {
100-
cm->set_last_query_begin(beg_addr);
101-
cm->set_last_query_object(end_obj);
102-
cm->set_last_query_return(result);
103-
}
104-
105-
size_t
106-
ParMarkBitMap::live_words_in_range_helper(HeapWord* beg_addr, oop end_obj) const
107-
{
108-
assert(beg_addr <= cast_from_oop<HeapWord*>(end_obj), "bad range");
109-
assert(is_marked(end_obj), "end_obj must be live");
110-
111-
idx_t live_bits = 0;
112-
113-
// The bitmap routines require the right boundary to be word-aligned.
114-
const idx_t end_bit = addr_to_bit(cast_from_oop<HeapWord*>(end_obj));
115-
const idx_t range_end = align_range_end(end_bit);
116-
117-
idx_t beg_bit = find_obj_beg(addr_to_bit(beg_addr), range_end);
118-
while (beg_bit < end_bit) {
119-
idx_t tmp_end = find_obj_end(beg_bit, range_end);
120-
assert(tmp_end < end_bit, "missing end bit");
121-
live_bits += tmp_end - beg_bit + 1;
122-
beg_bit = find_obj_beg(tmp_end + 1, range_end);
123-
}
124-
return bits_to_words(live_bits);
125-
}
126-
127-
size_t
128-
ParMarkBitMap::live_words_in_range_use_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_oop) const
129-
{
130-
HeapWord* last_beg = cm->last_query_begin();
131-
HeapWord* last_obj = cast_from_oop<HeapWord*>(cm->last_query_object());
132-
HeapWord* end_obj = cast_from_oop<HeapWord*>(end_oop);
133-
134-
size_t last_ret = cm->last_query_return();
135-
if (end_obj > last_obj) {
136-
last_ret = last_ret + live_words_in_range_helper(last_obj, end_oop);
137-
last_obj = end_obj;
138-
} else if (end_obj < last_obj) {
139-
// The cached value is for an object that is to the left (lower address) of the current
140-
// end_obj. Calculate back from that cached value.
141-
if (pointer_delta(end_obj, beg_addr) > pointer_delta(last_obj, end_obj)) {
142-
last_ret = last_ret - live_words_in_range_helper(end_obj, cast_to_oop(last_obj));
143-
} else {
144-
last_ret = live_words_in_range_helper(beg_addr, end_oop);
145-
}
146-
last_obj = end_obj;
147-
}
148-
149-
update_live_words_in_range_cache(cm, last_beg, cast_to_oop(last_obj), last_ret);
150-
return last_ret;
151-
}
152-
153-
size_t
154-
ParMarkBitMap::live_words_in_range(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const
155-
{
156-
// Try to reuse result from ParCompactionManager cache first.
157-
if (is_live_words_in_range_in_cache(cm, beg_addr)) {
158-
return live_words_in_range_use_cache(cm, beg_addr, end_obj);
159-
}
160-
size_t ret = live_words_in_range_helper(beg_addr, end_obj);
161-
update_live_words_in_range_cache(cm, beg_addr, end_obj, ret);
162-
return ret;
163-
}
164-
165-
ParMarkBitMap::IterationStatus
166-
ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure,
167-
idx_t range_beg, idx_t range_end) const
168-
{
169-
DEBUG_ONLY(verify_bit(range_beg);)
170-
DEBUG_ONLY(verify_bit(range_end);)
171-
assert(range_beg <= range_end, "live range invalid");
172-
173-
// The bitmap routines require the right boundary to be word-aligned.
174-
const idx_t search_end = align_range_end(range_end);
175-
176-
idx_t cur_beg = range_beg;
177-
while (true) {
178-
cur_beg = find_obj_beg(cur_beg, search_end);
179-
if (cur_beg >= range_end) {
180-
break;
181-
}
182-
183-
const size_t size = obj_size(cur_beg);
184-
IterationStatus status = live_closure->do_addr(bit_to_addr(cur_beg), size);
185-
if (status != incomplete) {
186-
assert(status == would_overflow || status == full, "sanity");
187-
return status;
188-
}
189-
190-
cur_beg += words_to_bits(size);
191-
if (cur_beg >= range_end) {
192-
break;
193-
}
194-
}
195-
196-
return complete;
197-
}
198-
199-
ParMarkBitMap::IterationStatus
200-
ParMarkBitMap::iterate(ParMarkBitMapClosure* live_closure,
201-
ParMarkBitMapClosure* dead_closure,
202-
idx_t range_beg, idx_t range_end,
203-
idx_t dead_range_end) const
204-
{
205-
DEBUG_ONLY(verify_bit(range_beg);)
206-
DEBUG_ONLY(verify_bit(range_end);)
207-
DEBUG_ONLY(verify_bit(dead_range_end);)
208-
assert(range_beg <= range_end, "live range invalid");
209-
assert(range_end <= dead_range_end, "dead range invalid");
210-
211-
// The bitmap routines require the right boundary to be word-aligned.
212-
const idx_t dead_search_end = align_range_end(dead_range_end);
213-
214-
idx_t cur_beg = range_beg;
215-
if (range_beg < range_end && is_unmarked(range_beg)) {
216-
// The range starts with dead space. Look for the next object, then fill.
217-
// This must be the beginning of old/eden/from/to-space, so it's must be
218-
// large enough for a filler.
219-
cur_beg = find_obj_beg(range_beg + 1, dead_search_end);
220-
const idx_t dead_space_end = cur_beg - 1;
221-
const size_t size = obj_size(range_beg, dead_space_end);
222-
dead_closure->do_addr(bit_to_addr(range_beg), size);
223-
}
224-
225-
while (cur_beg < range_end) {
226-
const size_t size = obj_size(cur_beg);
227-
IterationStatus status = live_closure->do_addr(bit_to_addr(cur_beg), size);
228-
if (status != incomplete) {
229-
assert(status == would_overflow || status == full, "sanity");
230-
return status;
231-
}
232-
233-
const idx_t dead_space_beg = cur_beg + words_to_bits(size);
234-
if (dead_space_beg >= dead_search_end) {
235-
break;
236-
}
237-
// Look for the start of the next object.
238-
cur_beg = find_obj_beg(dead_space_beg, dead_search_end);
239-
if (cur_beg > dead_space_beg) {
240-
// Found dead space; compute the size and invoke the dead closure.
241-
const idx_t dead_space_end = cur_beg - 1;
242-
dead_closure->do_addr(bit_to_addr(dead_space_beg),
243-
obj_size(dead_space_beg, dead_space_end));
244-
}
245-
}
246-
247-
return complete;
248-
}
249-
25076
#ifdef ASSERT
25177
void ParMarkBitMap::verify_clear() const
25278
{

src/hotspot/share/gc/parallel/parMarkBitMap.hpp

Lines changed: 6 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,14 @@ class ParMarkBitMap: public CHeapObj<mtGC>
3939
typedef BitMap::idx_t idx_t;
4040

4141
// Values returned by the iterate() methods.
42-
enum IterationStatus { incomplete, complete, full, would_overflow };
42+
enum IterationStatus { incomplete, complete, full };
4343

4444
inline ParMarkBitMap();
4545
bool initialize(MemRegion covered_region);
4646

4747
// Atomically mark an object as live.
48-
bool mark_obj(HeapWord* addr, size_t size);
49-
inline bool mark_obj(oop obj, size_t size);
50-
51-
// Return whether the specified begin or end bit is set.
52-
inline bool is_obj_beg(idx_t bit) const;
53-
inline bool is_obj_end(idx_t bit) const;
48+
inline bool mark_obj(HeapWord* addr);
49+
inline bool mark_obj(oop obj);
5450

5551
// Traditional interface for testing whether an object is marked or not (these
5652
// test only the begin bits).
@@ -68,61 +64,6 @@ class ParMarkBitMap: public CHeapObj<mtGC>
6864
inline static size_t bits_to_words(idx_t bits);
6965
inline static idx_t words_to_bits(size_t words);
7066

71-
// Return the size in words of an object given a begin bit and an end bit, or
72-
// the equivalent beg_addr and end_addr.
73-
inline size_t obj_size(idx_t beg_bit, idx_t end_bit) const;
74-
inline size_t obj_size(HeapWord* beg_addr, HeapWord* end_addr) const;
75-
76-
// Return the size in words of the object (a search is done for the end bit).
77-
inline size_t obj_size(idx_t beg_bit) const;
78-
inline size_t obj_size(HeapWord* addr) const;
79-
80-
// Apply live_closure to each live object that lies completely within the
81-
// range [live_range_beg, live_range_end). This is used to iterate over the
82-
// compacted region of the heap. Return values:
83-
//
84-
// complete The iteration is complete. All objects in the range
85-
// were processed and the closure is not full;
86-
// closure->source() is set one past the end of the range.
87-
//
88-
// full The closure is full; closure->source() is set to one
89-
// past the end of the last object processed.
90-
//
91-
// would_overflow The next object in the range would overflow the closure;
92-
// closure->source() is set to the start of that object.
93-
IterationStatus iterate(ParMarkBitMapClosure* live_closure,
94-
idx_t range_beg, idx_t range_end) const;
95-
inline IterationStatus iterate(ParMarkBitMapClosure* live_closure,
96-
HeapWord* range_beg,
97-
HeapWord* range_end) const;
98-
99-
// Apply live closure as above and additionally apply dead_closure to all dead
100-
// space in the range [range_beg, dead_range_end). Note that dead_range_end
101-
// must be >= range_end. This is used to iterate over the dense prefix.
102-
//
103-
// This method assumes that if the first bit in the range (range_beg) is not
104-
// marked, then dead space begins at that point and the dead_closure is
105-
// applied. Thus callers must ensure that range_beg is not in the middle of a
106-
// live object.
107-
IterationStatus iterate(ParMarkBitMapClosure* live_closure,
108-
ParMarkBitMapClosure* dead_closure,
109-
idx_t range_beg, idx_t range_end,
110-
idx_t dead_range_end) const;
111-
inline IterationStatus iterate(ParMarkBitMapClosure* live_closure,
112-
ParMarkBitMapClosure* dead_closure,
113-
HeapWord* range_beg,
114-
HeapWord* range_end,
115-
HeapWord* dead_range_end) const;
116-
117-
// Return the number of live words in the range [beg_addr, end_obj) due to
118-
// objects that start in the range. If a live object extends onto the range,
119-
// the caller must detect and account for any live words due to that object.
120-
// If a live object extends beyond the end of the range, only the words within
121-
// the range are included in the result. The end of the range must be a live object,
122-
// which is the case when updating pointers. This allows a branch to be removed
123-
// from inside the loop.
124-
size_t live_words_in_range(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const;
125-
12667
inline HeapWord* region_start() const;
12768
inline HeapWord* region_end() const;
12869
inline size_t region_size() const;
@@ -141,11 +82,12 @@ class ParMarkBitMap: public CHeapObj<mtGC>
14182
// respectively) in the range [beg, end). If no object is found, return end.
14283
// end must be word-aligned.
14384
inline idx_t find_obj_beg(idx_t beg, idx_t end) const;
144-
inline idx_t find_obj_end(idx_t beg, idx_t end) const;
14585

14686
inline HeapWord* find_obj_beg(HeapWord* beg, HeapWord* end) const;
147-
inline HeapWord* find_obj_end(HeapWord* beg, HeapWord* end) const;
14887

88+
// Return the address of the last obj-start in the range [beg, end). If no
89+
// object is found, return end.
90+
inline HeapWord* find_obj_beg_reverse(HeapWord* beg, HeapWord* end) const;
14991
// Clear a range of bits or the entire bitmap (both begin and end bits are
15092
// cleared).
15193
inline void clear_range(idx_t beg, idx_t end);
@@ -158,7 +100,6 @@ class ParMarkBitMap: public CHeapObj<mtGC>
158100
void print_on_error(outputStream* st) const {
159101
st->print_cr("Marking Bits: (ParMarkBitMap*) " PTR_FORMAT, p2i(this));
160102
_beg_bits.print_on_error(st, " Begin Bits: ");
161-
_end_bits.print_on_error(st, " End Bits: ");
162103
}
163104

164105
#ifdef ASSERT
@@ -168,11 +109,6 @@ class ParMarkBitMap: public CHeapObj<mtGC>
168109
#endif // #ifdef ASSERT
169110

170111
private:
171-
size_t live_words_in_range_helper(HeapWord* beg_addr, oop end_obj) const;
172-
173-
bool is_live_words_in_range_in_cache(ParCompactionManager* cm, HeapWord* beg_addr) const;
174-
size_t live_words_in_range_use_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj) const;
175-
void update_live_words_in_range_cache(ParCompactionManager* cm, HeapWord* beg_addr, oop end_obj, size_t result) const;
176112

177113
// Each bit in the bitmap represents one unit of 'object granularity.' Objects
178114
// are double-word aligned in 32-bit VMs, but not in 64-bit VMs, so the 32-bit
@@ -183,7 +119,6 @@ class ParMarkBitMap: public CHeapObj<mtGC>
183119
HeapWord* _region_start;
184120
size_t _region_size;
185121
BitMapView _beg_bits;
186-
BitMapView _end_bits;
187122
PSVirtualSpace* _virtual_space;
188123
size_t _reserved_byte_size;
189124
};

0 commit comments

Comments
 (0)