heapRegionSeq.cpp 8.6 KB
Newer Older
1
/*
2
 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
22 23 24
 *
 */

25
#include "precompiled.hpp"
26 27
#include "gc_implementation/g1/heapRegion.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
28
#include "gc_implementation/g1/heapRegionSet.hpp"
29 30
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "memory/allocation.hpp"
31

32
// Private
33

34 35
uint HeapRegionSeq::find_contiguous_from(uint from, uint num) {
  uint len = length();
36 37
  assert(num > 1, "use this only for sequences of length 2 or greater");
  assert(from <= len,
38
         err_msg("from: %u should be valid and <= than %u", from, len));
39

40 41 42
  uint curr = from;
  uint first = G1_NULL_HRS_INDEX;
  uint num_so_far = 0;
43 44 45
  while (curr < len && num_so_far < num) {
    if (at(curr)->is_empty()) {
      if (first == G1_NULL_HRS_INDEX) {
46 47 48 49 50 51
        first = curr;
        num_so_far = 1;
      } else {
        num_so_far += 1;
      }
    } else {
52
      first = G1_NULL_HRS_INDEX;
53 54 55 56 57 58
      num_so_far = 0;
    }
    curr += 1;
  }
  assert(num_so_far <= num, "post-condition");
  if (num_so_far == num) {
T
tonyp 已提交
59
    // we found enough space for the humongous object
60 61
    assert(from <= first && first < len, "post-condition");
    assert(first < curr && (curr - first) == num, "post-condition");
62
    for (uint i = first; i < first + num; ++i) {
63
      assert(at(i)->is_empty(), "post-condition");
64 65 66 67
    }
    return first;
  } else {
    // we failed to find enough space for the humongous object
68
    return G1_NULL_HRS_INDEX;
69 70 71
  }
}

72
// Public
73

74
void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end) {
75
  assert((uintptr_t) bottom % HeapRegion::GrainBytes == 0,
76
         "bottom should be heap region aligned");
77
  assert((uintptr_t) end % HeapRegion::GrainBytes == 0,
78
         "end should be heap region aligned");
79

80 81 82
  _next_search_index = 0;
  _allocated_length = 0;

83
  _regions.initialize(bottom, end, HeapRegion::GrainBytes);
84
}
85

86 87 88 89 90
MemRegion HeapRegionSeq::expand_by(HeapWord* old_end,
                                   HeapWord* new_end,
                                   FreeRegionList* list) {
  assert(old_end < new_end, "don't call it otherwise");
  G1CollectedHeap* g1h = G1CollectedHeap::heap();
91

92
  HeapWord* next_bottom = old_end;
93
  assert(heap_bottom() <= next_bottom, "invariant");
94
  while (next_bottom < new_end) {
95
    assert(next_bottom < heap_end(), "invariant");
96
    uint index = length();
97

98
    assert(index < max_length(), "otherwise we cannot expand further");
99 100
    if (index == 0) {
      // We have not allocated any regions so far
101
      assert(next_bottom == heap_bottom(), "invariant");
102
    } else {
103 104 105 106 107 108 109 110 111 112
      // next_bottom should match the end of the last/previous region
      assert(next_bottom == at(index - 1)->end(), "invariant");
    }

    if (index == _allocated_length) {
      // We have to allocate a new HeapRegion.
      HeapRegion* new_hr = g1h->new_heap_region(index, next_bottom);
      if (new_hr == NULL) {
        // allocation failed, we bail out and return what we have done so far
        return MemRegion(old_end, next_bottom);
113
      }
114 115
      assert(_regions.get_by_index(index) == NULL, "invariant");
      _regions.set_by_index(index, new_hr);
116
      increment_allocated_length();
117
    }
118 119
    // Have to increment the length first, otherwise we will get an
    // assert failure at(index) below.
120
    increment_length();
121 122 123 124
    HeapRegion* hr = at(index);
    list->add_as_tail(hr);

    next_bottom = hr->end();
125
  }
126 127 128 129
  assert(next_bottom == new_end, "post-condition");
  return MemRegion(old_end, next_bottom);
}

130 131 132
uint HeapRegionSeq::free_suffix() {
  uint res = 0;
  uint index = length();
133 134 135 136
  while (index > 0) {
    index -= 1;
    if (!at(index)->is_empty()) {
      break;
137
    }
138
    res += 1;
139
  }
140 141 142
  return res;
}

143
uint HeapRegionSeq::find_contiguous(uint num) {
144 145
  assert(num > 1, "use this only for sequences of length 2 or greater");
  assert(_next_search_index <= length(),
146
         err_msg("_next_search_index: %u should be valid and <= than %u",
147 148
                 _next_search_index, length()));

149 150
  uint start = _next_search_index;
  uint res = find_contiguous_from(start, num);
151 152 153 154 155 156
  if (res == G1_NULL_HRS_INDEX && start > 0) {
    // Try starting from the beginning. If _next_search_index was 0,
    // no point in doing this again.
    res = find_contiguous_from(0, num);
  }
  if (res != G1_NULL_HRS_INDEX) {
157
    assert(res < length(), err_msg("res: %u should be valid", res));
158 159
    _next_search_index = res + num;
    assert(_next_search_index <= length(),
160
           err_msg("_next_search_index: %u should be valid and <= than %u",
161
                   _next_search_index, length()));
162
  }
163 164 165 166 167
  return res;
}

void HeapRegionSeq::iterate(HeapRegionClosure* blk) const {
  iterate_from((HeapRegion*) NULL, blk);
168 169
}

170
void HeapRegionSeq::iterate_from(HeapRegion* hr, HeapRegionClosure* blk) const {
171
  uint hr_index = 0;
172
  if (hr != NULL) {
173
    hr_index = hr->hrs_index();
174 175
  }

176 177
  uint len = length();
  for (uint i = hr_index; i < len; i += 1) {
178 179
    bool res = blk->doHeapRegion(at(i));
    if (res) {
180 181 182 183
      blk->incomplete();
      return;
    }
  }
184
  for (uint i = 0; i < hr_index; i += 1) {
185 186
    bool res = blk->doHeapRegion(at(i));
    if (res) {
187 188 189 190 191 192
      blk->incomplete();
      return;
    }
  }
}

193
uint HeapRegionSeq::shrink_by(uint num_regions_to_remove) {
194 195
  // Reset this in case it's currently pointing into the regions that
  // we just removed.
196
  _next_search_index = 0;
197

198 199 200
  assert(length() > 0, "the region sequence should not be empty");
  assert(length() <= _allocated_length, "invariant");
  assert(_allocated_length > 0, "we should have at least one region committed");
201
  assert(num_regions_to_remove < length(), "We should never remove all regions");
202

203 204 205
  uint i = 0;
  for (; i < num_regions_to_remove; i++) {
    HeapRegion* cur = at(length() - 1);
206

207 208 209 210 211 212 213
    if (!cur->is_empty()) {
      // We have to give up if the region can not be moved
      break;
  }
    assert(!cur->isHumongous(), "Humongous regions should not be empty");

    decrement_length();
214
  }
215
  return i;
216 217
}

218 219
#ifndef PRODUCT
void HeapRegionSeq::verify_optional() {
220
  guarantee(length() <= _allocated_length,
221
            err_msg("invariant: _length: %u _allocated_length: %u",
222 223
                    length(), _allocated_length));
  guarantee(_allocated_length <= max_length(),
224
            err_msg("invariant: _allocated_length: %u _max_length: %u",
225 226
                    _allocated_length, max_length()));
  guarantee(_next_search_index <= length(),
227
            err_msg("invariant: _next_search_index: %u _length: %u",
228
                    _next_search_index, length()));
229

230
  HeapWord* prev_end = heap_bottom();
231
  for (uint i = 0; i < _allocated_length; i += 1) {
232
    HeapRegion* hr = _regions.get_by_index(i);
233
    guarantee(hr != NULL, err_msg("invariant: i: %u", i));
234
    guarantee(hr->bottom() == prev_end,
235
              err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT,
236 237
                      i, HR_FORMAT_PARAMS(hr), prev_end));
    guarantee(hr->hrs_index() == i,
238
              err_msg("invariant: i: %u hrs_index(): %u", i, hr->hrs_index()));
239
    if (i < length()) {
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
      // Asserts will fire if i is >= _length
      HeapWord* addr = hr->bottom();
      guarantee(addr_to_region(addr) == hr, "sanity");
      guarantee(addr_to_region_unsafe(addr) == hr, "sanity");
    } else {
      guarantee(hr->is_empty(), "sanity");
      guarantee(!hr->isHumongous(), "sanity");
      // using assert instead of guarantee here since containing_set()
      // is only available in non-product builds.
      assert(hr->containing_set() == NULL, "sanity");
    }
    if (hr->startsHumongous()) {
      prev_end = hr->orig_end();
    } else {
      prev_end = hr->end();
    }
  }
257 258
  for (uint i = _allocated_length; i < max_length(); i += 1) {
    guarantee(_regions.get_by_index(i) == NULL, err_msg("invariant i: %u", i));
259
  }
260
}
261
#endif // PRODUCT