Fri, 10 Oct 2014 15:51:58 +0200
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
1 /*
2 * Copyright (c) 2001, 2013, 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 */
25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONMANAGER_HPP
26 #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONMANAGER_HPP
28 #include "gc_implementation/g1/g1BiasedArray.hpp"
29 #include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
30 #include "gc_implementation/g1/heapRegionSet.hpp"
32 class HeapRegion;
33 class HeapRegionClosure;
34 class FreeRegionList;
36 class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
37 protected:
38 virtual HeapRegion* default_value() const { return NULL; }
39 };
41 // This class keeps track of the actual heap memory, auxiliary data
42 // and its metadata (i.e., HeapRegion instances) and the list of free regions.
43 //
44 // This allows maximum flexibility for deciding what to commit or uncommit given
45 // a request from outside.
46 //
47 // HeapRegions are kept in the _regions array in address order. A region's
48 // index in the array corresponds to its index in the heap (i.e., 0 is the
49 // region at the bottom of the heap, 1 is the one after it, etc.). Two
50 // regions that are consecutive in the array should also be adjacent in the
51 // address space (i.e., region(i).end() == region(i+1).bottom().
52 //
53 // We create a HeapRegion when we commit the region's address space
54 // for the first time. When we uncommit the address space of a
55 // region we retain the HeapRegion to be able to re-use it in the
56 // future (in case we recommit it).
57 //
58 // We keep track of three lengths:
59 //
60 // * _num_committed (returned by length()) is the number of currently
61 // committed regions. These may not be contiguous.
62 // * _allocated_heapregions_length (not exposed outside this class) is the
63 // number of regions+1 for which we have HeapRegions.
64 // * max_length() returns the maximum number of regions the heap can have.
65 //
67 class HeapRegionManager: public CHeapObj<mtGC> {
68 friend class VMStructs;
70 G1HeapRegionTable _regions;
72 G1RegionToSpaceMapper* _heap_mapper;
73 G1RegionToSpaceMapper* _prev_bitmap_mapper;
74 G1RegionToSpaceMapper* _next_bitmap_mapper;
75 G1RegionToSpaceMapper* _bot_mapper;
76 G1RegionToSpaceMapper* _cardtable_mapper;
77 G1RegionToSpaceMapper* _card_counts_mapper;
79 FreeRegionList _free_list;
81 // Each bit in this bitmap indicates that the corresponding region is available
82 // for allocation.
83 BitMap _available_map;
85 // The number of regions committed in the heap.
86 uint _num_committed;
88 // Internal only. The highest heap region +1 we allocated a HeapRegion instance for.
89 uint _allocated_heapregions_length;
91 HeapWord* heap_bottom() const { return _regions.bottom_address_mapped(); }
92 HeapWord* heap_end() const {return _regions.end_address_mapped(); }
94 void make_regions_available(uint index, uint num_regions = 1);
96 // Pass down commit calls to the VirtualSpace.
97 void commit_regions(uint index, size_t num_regions = 1);
98 void uncommit_regions(uint index, size_t num_regions = 1);
100 // Notify other data structures about change in the heap layout.
101 void update_committed_space(HeapWord* old_end, HeapWord* new_end);
102 // Calculate the starting region for each worker during parallel iteration so
103 // that they do not all start from the same region.
104 uint start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const;
106 // Find a contiguous set of empty or uncommitted regions of length num and return
107 // the index of the first region or G1_NO_HRM_INDEX if the search was unsuccessful.
108 // If only_empty is true, only empty regions are considered.
109 // Searches from bottom to top of the heap, doing a first-fit.
110 uint find_contiguous(size_t num, bool only_empty);
111 // Finds the next sequence of unavailable regions starting from start_idx. Returns the
112 // length of the sequence found. If this result is zero, no such sequence could be found,
113 // otherwise res_idx indicates the start index of these regions.
114 uint find_unavailable_from_idx(uint start_idx, uint* res_idx) const;
115 // Finds the next sequence of empty regions starting from start_idx, going backwards in
116 // the heap. Returns the length of the sequence found. If this value is zero, no
117 // sequence could be found, otherwise res_idx contains the start index of this range.
118 uint find_empty_from_idx_reverse(uint start_idx, uint* res_idx) const;
119 // Allocate a new HeapRegion for the given index.
120 HeapRegion* new_heap_region(uint hrm_index);
121 #ifdef ASSERT
122 public:
123 bool is_free(HeapRegion* hr) const;
124 #endif
125 // Returns whether the given region is available for allocation.
126 bool is_available(uint region) const;
128 public:
129 // Empty constructor, we'll initialize it with the initialize() method.
130 HeapRegionManager() : _regions(), _heap_mapper(NULL), _num_committed(0),
131 _next_bitmap_mapper(NULL), _prev_bitmap_mapper(NULL), _bot_mapper(NULL),
132 _allocated_heapregions_length(0), _available_map(),
133 _free_list("Free list", new MasterFreeRegionListMtSafeChecker())
134 { }
136 void initialize(G1RegionToSpaceMapper* heap_storage,
137 G1RegionToSpaceMapper* prev_bitmap,
138 G1RegionToSpaceMapper* next_bitmap,
139 G1RegionToSpaceMapper* bot,
140 G1RegionToSpaceMapper* cardtable,
141 G1RegionToSpaceMapper* card_counts);
143 // Return the "dummy" region used for G1AllocRegion. This is currently a hardwired
144 // new HeapRegion that owns HeapRegion at index 0. Since at the moment we commit
145 // the heap from the lowest address, this region (and its associated data
146 // structures) are available and we do not need to check further.
147 HeapRegion* get_dummy_region() { return new_heap_region(0); }
149 // Return the HeapRegion at the given index. Assume that the index
150 // is valid.
151 inline HeapRegion* at(uint index) const;
153 // If addr is within the committed space return its corresponding
154 // HeapRegion, otherwise return NULL.
155 inline HeapRegion* addr_to_region(HeapWord* addr) const;
157 // Insert the given region into the free region list.
158 inline void insert_into_free_list(HeapRegion* hr);
160 // Insert the given region list into the global free region list.
161 void insert_list_into_free_list(FreeRegionList* list) {
162 _free_list.add_ordered(list);
163 }
165 HeapRegion* allocate_free_region(bool is_old) {
166 HeapRegion* hr = _free_list.remove_region(is_old);
168 if (hr != NULL) {
169 assert(hr->next() == NULL, "Single region should not have next");
170 assert(is_available(hr->hrm_index()), "Must be committed");
171 }
172 return hr;
173 }
175 inline void allocate_free_regions_starting_at(uint first, uint num_regions);
177 // Remove all regions from the free list.
178 void remove_all_free_regions() {
179 _free_list.remove_all();
180 }
182 // Return the number of committed free regions in the heap.
183 uint num_free_regions() const {
184 return _free_list.length();
185 }
187 size_t total_capacity_bytes() const {
188 return num_free_regions() * HeapRegion::GrainBytes;
189 }
191 // Return the number of available (uncommitted) regions.
192 uint available() const { return max_length() - length(); }
194 // Return the number of regions that have been committed in the heap.
195 uint length() const { return _num_committed; }
197 // Return the maximum number of regions in the heap.
198 uint max_length() const { return (uint)_regions.length(); }
200 MemRegion reserved() const { return MemRegion(heap_bottom(), heap_end()); }
202 // Expand the sequence to reflect that the heap has grown. Either create new
203 // HeapRegions, or re-use existing ones. Returns the number of regions the
204 // sequence was expanded by. If a HeapRegion allocation fails, the resulting
205 // number of regions might be smaller than what's desired.
206 uint expand_by(uint num_regions);
208 // Makes sure that the regions from start to start+num_regions-1 are available
209 // for allocation. Returns the number of regions that were committed to achieve
210 // this.
211 uint expand_at(uint start, uint num_regions);
213 // Find a contiguous set of empty regions of length num. Returns the start index of
214 // that set, or G1_NO_HRM_INDEX.
215 uint find_contiguous_only_empty(size_t num) { return find_contiguous(num, true); }
216 // Find a contiguous set of empty or unavailable regions of length num. Returns the
217 // start index of that set, or G1_NO_HRM_INDEX.
218 uint find_contiguous_empty_or_unavailable(size_t num) { return find_contiguous(num, false); }
220 HeapRegion* next_region_in_heap(const HeapRegion* r) const;
222 // Apply blk->doHeapRegion() on all committed regions in address order,
223 // terminating the iteration early if doHeapRegion() returns true.
224 void iterate(HeapRegionClosure* blk) const;
226 void par_iterate(HeapRegionClosure* blk, uint worker_id, uint no_of_par_workers, jint claim_value) const;
228 // Uncommit up to num_regions_to_remove regions that are completely free.
229 // Return the actual number of uncommitted regions.
230 uint shrink_by(uint num_regions_to_remove);
232 void verify();
234 // Do some sanity checking.
235 void verify_optional() PRODUCT_RETURN;
236 };
238 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONMANAGER_HPP