Thu, 21 Aug 2014 16:44:41 +0200
8055098: WB API should be extended to provide information about size and age of object.
Summary: Extend the WhiteBox API to provide information about the size and age of objects. Further add a mechanism to trigger a young GC.
Reviewed-by: tschatzl, sjohanss
Contributed-by: Leonid Mesnik <leonid.mesnik@oracle.com>
ysr@777 | 1 | /* |
mikael@6198 | 2 | * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. |
ysr@777 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
ysr@777 | 4 | * |
ysr@777 | 5 | * This code is free software; you can redistribute it and/or modify it |
ysr@777 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ysr@777 | 7 | * published by the Free Software Foundation. |
ysr@777 | 8 | * |
ysr@777 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
ysr@777 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
ysr@777 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
ysr@777 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
ysr@777 | 13 | * accompanied this code). |
ysr@777 | 14 | * |
ysr@777 | 15 | * You should have received a copy of the GNU General Public License version |
ysr@777 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
ysr@777 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
ysr@777 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
ysr@777 | 22 | * |
ysr@777 | 23 | */ |
ysr@777 | 24 | |
stefank@2314 | 25 | #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP |
stefank@2314 | 26 | #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP |
stefank@2314 | 27 | |
tschatzl@5773 | 28 | #include "gc_implementation/g1/g1BiasedArray.hpp" |
tschatzl@7051 | 29 | #include "gc_implementation/g1/g1RegionToSpaceMapper.hpp" |
tschatzl@7050 | 30 | #include "gc_implementation/g1/heapRegionSet.hpp" |
tschatzl@5773 | 31 | |
ysr@777 | 32 | class HeapRegion; |
ysr@777 | 33 | class HeapRegionClosure; |
tonyp@2963 | 34 | class FreeRegionList; |
tonyp@2963 | 35 | |
tschatzl@5773 | 36 | class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> { |
tschatzl@5773 | 37 | protected: |
tschatzl@7050 | 38 | virtual HeapRegion* default_value() const { return NULL; } |
tschatzl@5773 | 39 | }; |
tschatzl@5773 | 40 | |
tschatzl@7051 | 41 | // This class keeps track of the actual heap memory, auxiliary data |
tschatzl@7051 | 42 | // and its metadata (i.e., HeapRegion instances) and the list of free regions. |
tschatzl@7051 | 43 | // |
tschatzl@7051 | 44 | // This allows maximum flexibility for deciding what to commit or uncommit given |
tschatzl@7051 | 45 | // a request from outside. |
tschatzl@7051 | 46 | // |
tschatzl@7051 | 47 | // HeapRegions are kept in the _regions array in address order. A region's |
tschatzl@7051 | 48 | // index in the array corresponds to its index in the heap (i.e., 0 is the |
tschatzl@7051 | 49 | // region at the bottom of the heap, 1 is the one after it, etc.). Two |
tschatzl@7051 | 50 | // regions that are consecutive in the array should also be adjacent in the |
tschatzl@7051 | 51 | // address space (i.e., region(i).end() == region(i+1).bottom(). |
tonyp@2963 | 52 | // |
tonyp@2963 | 53 | // We create a HeapRegion when we commit the region's address space |
tonyp@2963 | 54 | // for the first time. When we uncommit the address space of a |
tonyp@2963 | 55 | // region we retain the HeapRegion to be able to re-use it in the |
tonyp@2963 | 56 | // future (in case we recommit it). |
tonyp@2963 | 57 | // |
tonyp@2963 | 58 | // We keep track of three lengths: |
tonyp@2963 | 59 | // |
tschatzl@7051 | 60 | // * _num_committed (returned by length()) is the number of currently |
tschatzl@7051 | 61 | // committed regions. These may not be contiguous. |
tschatzl@7051 | 62 | // * _allocated_heapregions_length (not exposed outside this class) is the |
tschatzl@7051 | 63 | // number of regions+1 for which we have HeapRegions. |
tschatzl@5773 | 64 | // * max_length() returns the maximum number of regions the heap can have. |
tonyp@2963 | 65 | // |
ysr@777 | 66 | |
zgu@3900 | 67 | class HeapRegionSeq: public CHeapObj<mtGC> { |
tonyp@3168 | 68 | friend class VMStructs; |
ysr@777 | 69 | |
tschatzl@5773 | 70 | G1HeapRegionTable _regions; |
ysr@777 | 71 | |
tschatzl@7051 | 72 | G1RegionToSpaceMapper* _heap_mapper; |
tschatzl@7051 | 73 | G1RegionToSpaceMapper* _prev_bitmap_mapper; |
tschatzl@7051 | 74 | G1RegionToSpaceMapper* _next_bitmap_mapper; |
tschatzl@7051 | 75 | G1RegionToSpaceMapper* _bot_mapper; |
tschatzl@7051 | 76 | G1RegionToSpaceMapper* _cardtable_mapper; |
tschatzl@7051 | 77 | G1RegionToSpaceMapper* _card_counts_mapper; |
tonyp@2963 | 78 | |
tschatzl@7050 | 79 | FreeRegionList _free_list; |
tonyp@2963 | 80 | |
tschatzl@7051 | 81 | // Each bit in this bitmap indicates that the corresponding region is available |
tschatzl@7051 | 82 | // for allocation. |
tschatzl@7051 | 83 | BitMap _available_map; |
tschatzl@7051 | 84 | |
tschatzl@7050 | 85 | // The number of regions committed in the heap. |
tschatzl@7050 | 86 | uint _num_committed; |
tonyp@2963 | 87 | |
tschatzl@7050 | 88 | // Internal only. The highest heap region +1 we allocated a HeapRegion instance for. |
tschatzl@7050 | 89 | uint _allocated_heapregions_length; |
tonyp@2963 | 90 | |
tschatzl@7050 | 91 | HeapWord* heap_bottom() const { return _regions.bottom_address_mapped(); } |
tschatzl@7050 | 92 | HeapWord* heap_end() const {return _regions.end_address_mapped(); } |
tonyp@2963 | 93 | |
tschatzl@7050 | 94 | void make_regions_available(uint index, uint num_regions = 1); |
brutisso@5074 | 95 | |
tschatzl@7050 | 96 | // Pass down commit calls to the VirtualSpace. |
tschatzl@7050 | 97 | void commit_regions(uint index, size_t num_regions = 1); |
tschatzl@7050 | 98 | void uncommit_regions(uint index, size_t num_regions = 1); |
ysr@777 | 99 | |
tschatzl@7050 | 100 | // Notify other data structures about change in the heap layout. |
tschatzl@7050 | 101 | void update_committed_space(HeapWord* old_end, HeapWord* new_end); |
tschatzl@7050 | 102 | // Calculate the starting region for each worker during parallel iteration so |
tschatzl@7050 | 103 | // that they do not all start from the same region. |
tschatzl@7050 | 104 | uint start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const; |
tschatzl@5773 | 105 | |
tschatzl@7051 | 106 | // Find a contiguous set of empty or uncommitted regions of length num and return |
tschatzl@7051 | 107 | // the index of the first region or G1_NO_HRS_INDEX if the search was unsuccessful. |
tschatzl@7051 | 108 | // If only_empty is true, only empty regions are considered. |
tschatzl@7051 | 109 | // Searches from bottom to top of the heap, doing a first-fit. |
tschatzl@7051 | 110 | uint find_contiguous(size_t num, bool only_empty); |
tschatzl@7050 | 111 | // Finds the next sequence of unavailable regions starting from start_idx. Returns the |
tschatzl@7050 | 112 | // length of the sequence found. If this result is zero, no such sequence could be found, |
tschatzl@7050 | 113 | // otherwise res_idx indicates the start index of these regions. |
tschatzl@7050 | 114 | uint find_unavailable_from_idx(uint start_idx, uint* res_idx) const; |
tschatzl@7050 | 115 | // Finds the next sequence of empty regions starting from start_idx, going backwards in |
tschatzl@7050 | 116 | // the heap. Returns the length of the sequence found. If this value is zero, no |
tschatzl@7050 | 117 | // sequence could be found, otherwise res_idx contains the start index of this range. |
tschatzl@7050 | 118 | uint find_empty_from_idx_reverse(uint start_idx, uint* res_idx) const; |
tschatzl@7051 | 119 | // Allocate a new HeapRegion for the given index. |
tschatzl@7051 | 120 | HeapRegion* new_heap_region(uint hrs_index); |
tschatzl@7050 | 121 | #ifdef ASSERT |
tschatzl@7050 | 122 | public: |
tschatzl@7050 | 123 | bool is_free(HeapRegion* hr) const; |
tschatzl@7050 | 124 | #endif |
tschatzl@7050 | 125 | // Returns whether the given region is available for allocation. |
tschatzl@7050 | 126 | bool is_available(uint region) const; |
ysr@777 | 127 | |
tschatzl@7050 | 128 | public: |
tschatzl@7050 | 129 | // Empty constructor, we'll initialize it with the initialize() method. |
tschatzl@7051 | 130 | HeapRegionSeq() : _regions(), _heap_mapper(NULL), _num_committed(0), |
tschatzl@7051 | 131 | _next_bitmap_mapper(NULL), _prev_bitmap_mapper(NULL), _bot_mapper(NULL), |
tschatzl@7051 | 132 | _allocated_heapregions_length(0), _available_map(), |
tschatzl@7051 | 133 | _free_list("Free list", new MasterFreeRegionListMtSafeChecker()) |
tschatzl@7050 | 134 | { } |
tschatzl@7050 | 135 | |
tschatzl@7051 | 136 | void initialize(G1RegionToSpaceMapper* heap_storage, |
tschatzl@7051 | 137 | G1RegionToSpaceMapper* prev_bitmap, |
tschatzl@7051 | 138 | G1RegionToSpaceMapper* next_bitmap, |
tschatzl@7051 | 139 | G1RegionToSpaceMapper* bot, |
tschatzl@7051 | 140 | G1RegionToSpaceMapper* cardtable, |
tschatzl@7051 | 141 | G1RegionToSpaceMapper* card_counts); |
tschatzl@7050 | 142 | |
tschatzl@7050 | 143 | // Return the "dummy" region used for G1AllocRegion. This is currently a hardwired |
tschatzl@7050 | 144 | // new HeapRegion that owns HeapRegion at index 0. Since at the moment we commit |
tschatzl@7050 | 145 | // the heap from the lowest address, this region (and its associated data |
tschatzl@7050 | 146 | // structures) are available and we do not need to check further. |
tschatzl@7050 | 147 | HeapRegion* get_dummy_region() { return new_heap_region(0); } |
ysr@777 | 148 | |
tonyp@2963 | 149 | // Return the HeapRegion at the given index. Assume that the index |
tonyp@2963 | 150 | // is valid. |
tonyp@3713 | 151 | inline HeapRegion* at(uint index) const; |
ysr@777 | 152 | |
tonyp@2963 | 153 | // If addr is within the committed space return its corresponding |
tonyp@2963 | 154 | // HeapRegion, otherwise return NULL. |
tonyp@2963 | 155 | inline HeapRegion* addr_to_region(HeapWord* addr) const; |
ysr@777 | 156 | |
tschatzl@7050 | 157 | // Insert the given region into the free region list. |
tschatzl@7050 | 158 | inline void insert_into_free_list(HeapRegion* hr); |
tschatzl@7050 | 159 | |
tschatzl@7050 | 160 | // Insert the given region list into the global free region list. |
tschatzl@7050 | 161 | void insert_list_into_free_list(FreeRegionList* list) { |
tschatzl@7050 | 162 | _free_list.add_ordered(list); |
tschatzl@7050 | 163 | } |
tschatzl@7050 | 164 | |
tschatzl@7050 | 165 | HeapRegion* allocate_free_region(bool is_old) { |
tschatzl@7050 | 166 | HeapRegion* hr = _free_list.remove_region(is_old); |
tschatzl@7050 | 167 | |
tschatzl@7050 | 168 | if (hr != NULL) { |
tschatzl@7050 | 169 | assert(hr->next() == NULL, "Single region should not have next"); |
tschatzl@7050 | 170 | assert(is_available(hr->hrs_index()), "Must be committed"); |
tschatzl@7050 | 171 | } |
tschatzl@7050 | 172 | return hr; |
tschatzl@7050 | 173 | } |
tschatzl@7050 | 174 | |
tschatzl@7050 | 175 | inline void allocate_free_regions_starting_at(uint first, uint num_regions); |
tschatzl@7050 | 176 | |
tschatzl@7050 | 177 | // Remove all regions from the free list. |
tschatzl@7050 | 178 | void remove_all_free_regions() { |
tschatzl@7050 | 179 | _free_list.remove_all(); |
tschatzl@7050 | 180 | } |
tschatzl@7050 | 181 | |
tschatzl@7050 | 182 | // Return the number of committed free regions in the heap. |
tschatzl@7050 | 183 | uint num_free_regions() const { |
tschatzl@7050 | 184 | return _free_list.length(); |
tschatzl@7050 | 185 | } |
tschatzl@7050 | 186 | |
tschatzl@7050 | 187 | size_t total_capacity_bytes() const { |
tschatzl@7050 | 188 | return num_free_regions() * HeapRegion::GrainBytes; |
tschatzl@7050 | 189 | } |
tschatzl@7050 | 190 | |
tschatzl@7050 | 191 | // Return the number of available (uncommitted) regions. |
tschatzl@7050 | 192 | uint available() const { return max_length() - length(); } |
tschatzl@7050 | 193 | |
tonyp@2963 | 194 | // Return the number of regions that have been committed in the heap. |
tschatzl@7050 | 195 | uint length() const { return _num_committed; } |
tonyp@2963 | 196 | |
tonyp@2963 | 197 | // Return the maximum number of regions in the heap. |
tschatzl@5773 | 198 | uint max_length() const { return (uint)_regions.length(); } |
tonyp@2963 | 199 | |
tschatzl@7050 | 200 | MemRegion reserved() const { return MemRegion(heap_bottom(), heap_end()); } |
ysr@777 | 201 | |
tschatzl@7050 | 202 | // Expand the sequence to reflect that the heap has grown. Either create new |
tschatzl@7050 | 203 | // HeapRegions, or re-use existing ones. Returns the number of regions the |
tschatzl@7050 | 204 | // sequence was expanded by. If a HeapRegion allocation fails, the resulting |
tschatzl@7050 | 205 | // number of regions might be smaller than what's desired. |
tschatzl@7050 | 206 | uint expand_by(uint num_regions); |
tschatzl@7050 | 207 | |
tschatzl@7050 | 208 | // Makes sure that the regions from start to start+num_regions-1 are available |
tschatzl@7050 | 209 | // for allocation. Returns the number of regions that were committed to achieve |
tschatzl@7050 | 210 | // this. |
tschatzl@7050 | 211 | uint expand_at(uint start, uint num_regions); |
tschatzl@7050 | 212 | |
tschatzl@7051 | 213 | // Find a contiguous set of empty regions of length num. Returns the start index of |
tschatzl@7051 | 214 | // that set, or G1_NO_HRS_INDEX. |
tschatzl@7051 | 215 | uint find_contiguous_only_empty(size_t num) { return find_contiguous(num, true); } |
tschatzl@7051 | 216 | // Find a contiguous set of empty or unavailable regions of length num. Returns the |
tschatzl@7051 | 217 | // start index of that set, or G1_NO_HRS_INDEX. |
tschatzl@7051 | 218 | uint find_contiguous_empty_or_unavailable(size_t num) { return find_contiguous(num, false); } |
tschatzl@7050 | 219 | |
tschatzl@7050 | 220 | HeapRegion* next_region_in_heap(const HeapRegion* r) const; |
ysr@777 | 221 | |
tonyp@2963 | 222 | // Apply blk->doHeapRegion() on all committed regions in address order, |
tonyp@2963 | 223 | // terminating the iteration early if doHeapRegion() returns true. |
tonyp@2963 | 224 | void iterate(HeapRegionClosure* blk) const; |
ysr@777 | 225 | |
tschatzl@7050 | 226 | void par_iterate(HeapRegionClosure* blk, uint worker_id, uint no_of_par_workers, jint claim_value) const; |
ysr@777 | 227 | |
tschatzl@7050 | 228 | // Uncommit up to num_regions_to_remove regions that are completely free. |
tschatzl@7050 | 229 | // Return the actual number of uncommitted regions. |
brutisso@5074 | 230 | uint shrink_by(uint num_regions_to_remove); |
ysr@777 | 231 | |
tschatzl@7050 | 232 | void verify(); |
tschatzl@7050 | 233 | |
tonyp@2963 | 234 | // Do some sanity checking. |
tonyp@2963 | 235 | void verify_optional() PRODUCT_RETURN; |
ysr@777 | 236 | }; |
stefank@2314 | 237 | |
stefank@2314 | 238 | #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP |