Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/heapRegionSeq.cpp @ 20337:1f1d373cd044
8038423: G1: Decommit memory within heap
Summary: Allow G1 to decommit memory of arbitrary regions within the heap and their associated auxiliary data structures card table, BOT, hot card cache, and mark bitmaps.
Reviewed-by: mgerdin, brutisso, jwilhelm
author | tschatzl |
---|---|
date | Thu, 21 Aug 2014 11:47:10 +0200 |
parents | 6701abbc4441 |
children |
comparison
equal
deleted
inserted
replaced
20336:6701abbc4441 | 20337:1f1d373cd044 |
---|---|
28 #include "gc_implementation/g1/heapRegionSet.inline.hpp" | 28 #include "gc_implementation/g1/heapRegionSet.inline.hpp" |
29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" | 29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" |
30 #include "gc_implementation/g1/concurrentG1Refine.hpp" | 30 #include "gc_implementation/g1/concurrentG1Refine.hpp" |
31 #include "memory/allocation.hpp" | 31 #include "memory/allocation.hpp" |
32 | 32 |
33 void HeapRegionSeq::initialize(ReservedSpace reserved) { | 33 void HeapRegionSeq::initialize(G1RegionToSpaceMapper* heap_storage, |
34 _reserved = reserved; | 34 G1RegionToSpaceMapper* prev_bitmap, |
35 _storage.initialize(reserved, 0); | 35 G1RegionToSpaceMapper* next_bitmap, |
36 | 36 G1RegionToSpaceMapper* bot, |
37 _num_committed = 0; | 37 G1RegionToSpaceMapper* cardtable, |
38 | 38 G1RegionToSpaceMapper* card_counts) { |
39 _allocated_heapregions_length = 0; | 39 _allocated_heapregions_length = 0; |
40 | 40 |
41 _regions.initialize((HeapWord*)_storage.low_boundary(), (HeapWord*)_storage.high_boundary(), HeapRegion::GrainBytes); | 41 _heap_mapper = heap_storage; |
42 | |
43 _prev_bitmap_mapper = prev_bitmap; | |
44 _next_bitmap_mapper = next_bitmap; | |
45 | |
46 _bot_mapper = bot; | |
47 _cardtable_mapper = cardtable; | |
48 | |
49 _card_counts_mapper = card_counts; | |
50 | |
51 MemRegion reserved = heap_storage->reserved(); | |
52 _regions.initialize(reserved.start(), reserved.end(), HeapRegion::GrainBytes); | |
53 | |
54 _available_map.resize(_regions.length(), false); | |
55 _available_map.clear(); | |
42 } | 56 } |
43 | 57 |
44 bool HeapRegionSeq::is_available(uint region) const { | 58 bool HeapRegionSeq::is_available(uint region) const { |
45 return region < _num_committed; | 59 return _available_map.at(region); |
46 } | 60 } |
47 | 61 |
48 #ifdef ASSERT | 62 #ifdef ASSERT |
49 bool HeapRegionSeq::is_free(HeapRegion* hr) const { | 63 bool HeapRegionSeq::is_free(HeapRegion* hr) const { |
50 return _free_list.contains(hr); | 64 return _free_list.contains(hr); |
56 MemRegion mr(bottom, bottom + HeapRegion::GrainWords); | 70 MemRegion mr(bottom, bottom + HeapRegion::GrainWords); |
57 assert(reserved().contains(mr), "invariant"); | 71 assert(reserved().contains(mr), "invariant"); |
58 return new HeapRegion(hrs_index, G1CollectedHeap::heap()->bot_shared(), mr); | 72 return new HeapRegion(hrs_index, G1CollectedHeap::heap()->bot_shared(), mr); |
59 } | 73 } |
60 | 74 |
61 void HeapRegionSeq::update_committed_space(HeapWord* old_end, | |
62 HeapWord* new_end) { | |
63 assert(old_end != new_end, "don't call this otherwise"); | |
64 // We may not have officially committed the area. So construct and use a separate one. | |
65 MemRegion new_committed(heap_bottom(), new_end); | |
66 // Tell the card table about the update. | |
67 Universe::heap()->barrier_set()->resize_covered_region(new_committed); | |
68 // Tell the BOT about the update. | |
69 G1CollectedHeap::heap()->bot_shared()->resize(new_committed.word_size()); | |
70 // Tell the hot card cache about the update | |
71 G1CollectedHeap::heap()->concurrent_g1_refine()->hot_card_cache()->resize_card_counts(new_committed.byte_size()); | |
72 } | |
73 | |
74 void HeapRegionSeq::commit_regions(uint index, size_t num_regions) { | 75 void HeapRegionSeq::commit_regions(uint index, size_t num_regions) { |
75 guarantee(num_regions > 0, "Must commit more than zero regions"); | 76 guarantee(num_regions > 0, "Must commit more than zero regions"); |
76 guarantee(_num_committed + num_regions <= max_length(), "Cannot commit more than the maximum amount of regions"); | 77 guarantee(_num_committed + num_regions <= max_length(), "Cannot commit more than the maximum amount of regions"); |
77 | 78 |
78 _storage.expand_by(num_regions * HeapRegion::GrainBytes); | 79 _num_committed += (uint)num_regions; |
79 update_committed_space(heap_top(), heap_top() + num_regions * HeapRegion::GrainWords); | 80 |
81 _heap_mapper->commit_regions(index, num_regions); | |
82 | |
83 // Also commit auxiliary data | |
84 _prev_bitmap_mapper->commit_regions(index, num_regions); | |
85 _next_bitmap_mapper->commit_regions(index, num_regions); | |
86 | |
87 _bot_mapper->commit_regions(index, num_regions); | |
88 _cardtable_mapper->commit_regions(index, num_regions); | |
89 | |
90 _card_counts_mapper->commit_regions(index, num_regions); | |
80 } | 91 } |
81 | 92 |
82 void HeapRegionSeq::uncommit_regions(uint start, size_t num_regions) { | 93 void HeapRegionSeq::uncommit_regions(uint start, size_t num_regions) { |
83 guarantee(num_regions >= 1, "Need to specify at least one region to uncommit"); | 94 guarantee(num_regions >= 1, err_msg("Need to specify at least one region to uncommit, tried to uncommit zero regions at %u", start)); |
84 guarantee(_num_committed >= num_regions, "pre-condition"); | 95 guarantee(_num_committed >= num_regions, "pre-condition"); |
85 | 96 |
86 // Print before uncommitting. | 97 // Print before uncommitting. |
87 if (G1CollectedHeap::heap()->hr_printer()->is_active()) { | 98 if (G1CollectedHeap::heap()->hr_printer()->is_active()) { |
88 for (uint i = start; i < start + num_regions; i++) { | 99 for (uint i = start; i < start + num_regions; i++) { |
89 HeapRegion* hr = at(i); | 100 HeapRegion* hr = at(i); |
90 G1CollectedHeap::heap()->hr_printer()->uncommit(hr->bottom(), hr->end()); | 101 G1CollectedHeap::heap()->hr_printer()->uncommit(hr->bottom(), hr->end()); |
91 } | 102 } |
92 } | 103 } |
93 | 104 |
94 HeapWord* old_end = heap_top(); | |
95 _num_committed -= (uint)num_regions; | 105 _num_committed -= (uint)num_regions; |
96 OrderAccess::fence(); | 106 |
97 | 107 _available_map.par_clear_range(start, start + num_regions, BitMap::unknown_range); |
98 _storage.shrink_by(num_regions * HeapRegion::GrainBytes); | 108 _heap_mapper->uncommit_regions(start, num_regions); |
99 update_committed_space(old_end, heap_top()); | 109 |
110 // Also uncommit auxiliary data | |
111 _prev_bitmap_mapper->uncommit_regions(start, num_regions); | |
112 _next_bitmap_mapper->uncommit_regions(start, num_regions); | |
113 | |
114 _bot_mapper->uncommit_regions(start, num_regions); | |
115 _cardtable_mapper->uncommit_regions(start, num_regions); | |
116 | |
117 _card_counts_mapper->uncommit_regions(start, num_regions); | |
100 } | 118 } |
101 | 119 |
102 void HeapRegionSeq::make_regions_available(uint start, uint num_regions) { | 120 void HeapRegionSeq::make_regions_available(uint start, uint num_regions) { |
103 guarantee(num_regions > 0, "No point in calling this for zero regions"); | 121 guarantee(num_regions > 0, "No point in calling this for zero regions"); |
104 commit_regions(start, num_regions); | 122 commit_regions(start, num_regions); |
108 _regions.set_by_index(i, new_hr); | 126 _regions.set_by_index(i, new_hr); |
109 _allocated_heapregions_length = MAX2(_allocated_heapregions_length, i + 1); | 127 _allocated_heapregions_length = MAX2(_allocated_heapregions_length, i + 1); |
110 } | 128 } |
111 } | 129 } |
112 | 130 |
113 _num_committed += (size_t)num_regions; | 131 _available_map.par_set_range(start, start + num_regions, BitMap::unknown_range); |
114 | |
115 OrderAccess::fence(); | |
116 | 132 |
117 for (uint i = start; i < start + num_regions; i++) { | 133 for (uint i = start; i < start + num_regions; i++) { |
118 assert(is_available(i), err_msg("Just made region %u available but is apparently not.", i)); | 134 assert(is_available(i), err_msg("Just made region %u available but is apparently not.", i)); |
119 HeapRegion* hr = at(i); | 135 HeapRegion* hr = at(i); |
120 if (G1CollectedHeap::heap()->hr_printer()->is_active()) { | 136 if (G1CollectedHeap::heap()->hr_printer()->is_active()) { |
127 insert_into_free_list(at(i)); | 143 insert_into_free_list(at(i)); |
128 } | 144 } |
129 } | 145 } |
130 | 146 |
131 uint HeapRegionSeq::expand_by(uint num_regions) { | 147 uint HeapRegionSeq::expand_by(uint num_regions) { |
132 // Only ever expand from the end of the heap. | 148 return expand_at(0, num_regions); |
133 return expand_at(_num_committed, num_regions); | |
134 } | 149 } |
135 | 150 |
136 uint HeapRegionSeq::expand_at(uint start, uint num_regions) { | 151 uint HeapRegionSeq::expand_at(uint start, uint num_regions) { |
137 if (num_regions == 0) { | 152 if (num_regions == 0) { |
138 return 0; | 153 return 0; |
332 uint removed = 0; | 347 uint removed = 0; |
333 uint cur = _allocated_heapregions_length - 1; | 348 uint cur = _allocated_heapregions_length - 1; |
334 uint idx_last_found = 0; | 349 uint idx_last_found = 0; |
335 uint num_last_found = 0; | 350 uint num_last_found = 0; |
336 | 351 |
337 if ((num_last_found = find_empty_from_idx_reverse(cur, &idx_last_found)) > 0) { | 352 while ((removed < num_regions_to_remove) && |
353 (num_last_found = find_empty_from_idx_reverse(cur, &idx_last_found)) > 0) { | |
338 // Only allow uncommit from the end of the heap. | 354 // Only allow uncommit from the end of the heap. |
339 if ((idx_last_found + num_last_found) != _allocated_heapregions_length) { | 355 if ((idx_last_found + num_last_found) != _allocated_heapregions_length) { |
340 return 0; | 356 return 0; |
341 } | 357 } |
342 uint to_remove = MIN2(num_regions_to_remove - removed, num_last_found); | 358 uint to_remove = MIN2(num_regions_to_remove - removed, num_last_found); |