src/share/vm/gc_implementation/g1/g1AllocRegion.cpp

Thu, 22 Sep 2011 10:57:37 -0700

author
johnc
date
Thu, 22 Sep 2011 10:57:37 -0700
changeset 3175
4dfb2df418f2
parent 3028
f44782f04dd4
child 3713
720b6a76dd9d
permissions
-rw-r--r--

6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp

tonyp@2715 1 /*
tonyp@2715 2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
tonyp@2715 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
tonyp@2715 4 *
tonyp@2715 5 * This code is free software; you can redistribute it and/or modify it
tonyp@2715 6 * under the terms of the GNU General Public License version 2 only, as
tonyp@2715 7 * published by the Free Software Foundation.
tonyp@2715 8 *
tonyp@2715 9 * This code is distributed in the hope that it will be useful, but WITHOUT
tonyp@2715 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
tonyp@2715 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
tonyp@2715 12 * version 2 for more details (a copy is included in the LICENSE file that
tonyp@2715 13 * accompanied this code).
tonyp@2715 14 *
tonyp@2715 15 * You should have received a copy of the GNU General Public License version
tonyp@2715 16 * 2 along with this work; if not, write to the Free Software Foundation,
tonyp@2715 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
tonyp@2715 18 *
tonyp@2715 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
tonyp@2715 20 * or visit www.oracle.com if you need additional information or have any
tonyp@2715 21 * questions.
tonyp@2715 22 *
tonyp@2715 23 */
tonyp@2715 24
tonyp@2715 25 #include "precompiled.hpp"
tonyp@2715 26 #include "gc_implementation/g1/g1AllocRegion.inline.hpp"
tonyp@2715 27 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
tonyp@2715 28
tonyp@2715 29 G1CollectedHeap* G1AllocRegion::_g1h = NULL;
tonyp@2715 30 HeapRegion* G1AllocRegion::_dummy_region = NULL;
tonyp@2715 31
tonyp@2715 32 void G1AllocRegion::setup(G1CollectedHeap* g1h, HeapRegion* dummy_region) {
tonyp@2715 33 assert(_dummy_region == NULL, "should be set once");
tonyp@2715 34 assert(dummy_region != NULL, "pre-condition");
tonyp@2715 35 assert(dummy_region->free() == 0, "pre-condition");
tonyp@2715 36
tonyp@2715 37 // Make sure that any allocation attempt on this region will fail
tonyp@2715 38 // and will not trigger any asserts.
tonyp@2715 39 assert(allocate(dummy_region, 1, false) == NULL, "should fail");
tonyp@2715 40 assert(par_allocate(dummy_region, 1, false) == NULL, "should fail");
tonyp@2715 41 assert(allocate(dummy_region, 1, true) == NULL, "should fail");
tonyp@2715 42 assert(par_allocate(dummy_region, 1, true) == NULL, "should fail");
tonyp@2715 43
tonyp@2715 44 _g1h = g1h;
tonyp@2715 45 _dummy_region = dummy_region;
tonyp@2715 46 }
tonyp@2715 47
tonyp@2715 48 void G1AllocRegion::fill_up_remaining_space(HeapRegion* alloc_region,
tonyp@2715 49 bool bot_updates) {
tonyp@2715 50 assert(alloc_region != NULL && alloc_region != _dummy_region,
tonyp@2715 51 "pre-condition");
tonyp@2715 52
tonyp@2715 53 // Other threads might still be trying to allocate using a CAS out
tonyp@2715 54 // of the region we are trying to retire, as they can do so without
tonyp@2715 55 // holding the lock. So, we first have to make sure that noone else
tonyp@2715 56 // can allocate out of it by doing a maximal allocation. Even if our
tonyp@2715 57 // CAS attempt fails a few times, we'll succeed sooner or later
tonyp@2715 58 // given that failed CAS attempts mean that the region is getting
tonyp@2715 59 // closed to being full.
tonyp@2715 60 size_t free_word_size = alloc_region->free() / HeapWordSize;
tonyp@2715 61
tonyp@2715 62 // This is the minimum free chunk we can turn into a dummy
tonyp@2715 63 // object. If the free space falls below this, then noone can
tonyp@2715 64 // allocate in this region anyway (all allocation requests will be
tonyp@2715 65 // of a size larger than this) so we won't have to perform the dummy
tonyp@2715 66 // allocation.
tonyp@2715 67 size_t min_word_size_to_fill = CollectedHeap::min_fill_size();
tonyp@2715 68
tonyp@2715 69 while (free_word_size >= min_word_size_to_fill) {
tonyp@2715 70 HeapWord* dummy = par_allocate(alloc_region, free_word_size, bot_updates);
tonyp@2715 71 if (dummy != NULL) {
tonyp@2715 72 // If the allocation was successful we should fill in the space.
tonyp@2715 73 CollectedHeap::fill_with_object(dummy, free_word_size);
tonyp@2715 74 alloc_region->set_pre_dummy_top(dummy);
tonyp@2715 75 break;
tonyp@2715 76 }
tonyp@2715 77
tonyp@2715 78 free_word_size = alloc_region->free() / HeapWordSize;
tonyp@2715 79 // It's also possible that someone else beats us to the
tonyp@2715 80 // allocation and they fill up the region. In that case, we can
tonyp@2715 81 // just get out of the loop.
tonyp@2715 82 }
tonyp@2715 83 assert(alloc_region->free() / HeapWordSize < min_word_size_to_fill,
tonyp@2715 84 "post-condition");
tonyp@2715 85 }
tonyp@2715 86
tonyp@2715 87 void G1AllocRegion::retire(bool fill_up) {
tonyp@2715 88 assert(_alloc_region != NULL, ar_ext_msg(this, "not initialized properly"));
tonyp@2715 89
tonyp@2715 90 trace("retiring");
tonyp@2715 91 HeapRegion* alloc_region = _alloc_region;
tonyp@2715 92 if (alloc_region != _dummy_region) {
tonyp@2715 93 // We never have to check whether the active region is empty or not,
tonyp@2715 94 // and potentially free it if it is, given that it's guaranteed that
tonyp@2715 95 // it will never be empty.
tonyp@2715 96 assert(!alloc_region->is_empty(),
tonyp@2715 97 ar_ext_msg(this, "the alloc region should never be empty"));
tonyp@2715 98
tonyp@2715 99 if (fill_up) {
tonyp@2715 100 fill_up_remaining_space(alloc_region, _bot_updates);
tonyp@2715 101 }
tonyp@2715 102
tonyp@2715 103 assert(alloc_region->used() >= _used_bytes_before,
tonyp@2715 104 ar_ext_msg(this, "invariant"));
tonyp@2715 105 size_t allocated_bytes = alloc_region->used() - _used_bytes_before;
tonyp@2715 106 retire_region(alloc_region, allocated_bytes);
tonyp@2715 107 _used_bytes_before = 0;
tonyp@2715 108 _alloc_region = _dummy_region;
tonyp@2715 109 }
tonyp@2715 110 trace("retired");
tonyp@2715 111 }
tonyp@2715 112
tonyp@2715 113 HeapWord* G1AllocRegion::new_alloc_region_and_allocate(size_t word_size,
tonyp@2715 114 bool force) {
tonyp@2715 115 assert(_alloc_region == _dummy_region, ar_ext_msg(this, "pre-condition"));
tonyp@2715 116 assert(_used_bytes_before == 0, ar_ext_msg(this, "pre-condition"));
tonyp@2715 117
tonyp@2715 118 trace("attempting region allocation");
tonyp@2715 119 HeapRegion* new_alloc_region = allocate_new_region(word_size, force);
tonyp@2715 120 if (new_alloc_region != NULL) {
tonyp@2715 121 new_alloc_region->reset_pre_dummy_top();
tonyp@2715 122 // Need to do this before the allocation
tonyp@2715 123 _used_bytes_before = new_alloc_region->used();
tonyp@2715 124 HeapWord* result = allocate(new_alloc_region, word_size, _bot_updates);
tonyp@2715 125 assert(result != NULL, ar_ext_msg(this, "the allocation should succeeded"));
tonyp@2715 126
tonyp@2715 127 OrderAccess::storestore();
tonyp@2715 128 // Note that we first perform the allocation and then we store the
tonyp@2715 129 // region in _alloc_region. This is the reason why an active region
tonyp@2715 130 // can never be empty.
tonyp@2715 131 _alloc_region = new_alloc_region;
tonyp@3028 132 _count += 1;
tonyp@2715 133 trace("region allocation successful");
tonyp@2715 134 return result;
tonyp@2715 135 } else {
tonyp@2715 136 trace("region allocation failed");
tonyp@2715 137 return NULL;
tonyp@2715 138 }
tonyp@2715 139 ShouldNotReachHere();
tonyp@2715 140 }
tonyp@2715 141
tonyp@2715 142 void G1AllocRegion::fill_in_ext_msg(ar_ext_msg* msg, const char* message) {
tonyp@3028 143 msg->append("[%s] %s c: "SIZE_FORMAT" b: %s r: "PTR_FORMAT" u: "SIZE_FORMAT,
tonyp@3028 144 _name, message, _count, BOOL_TO_STR(_bot_updates),
tonyp@2715 145 _alloc_region, _used_bytes_before);
tonyp@2715 146 }
tonyp@2715 147
tonyp@2715 148 void G1AllocRegion::init() {
tonyp@2715 149 trace("initializing");
tonyp@2715 150 assert(_alloc_region == NULL && _used_bytes_before == 0,
tonyp@2715 151 ar_ext_msg(this, "pre-condition"));
tonyp@3028 152 assert(_dummy_region != NULL, ar_ext_msg(this, "should have been set"));
tonyp@2715 153 _alloc_region = _dummy_region;
tonyp@3028 154 _count = 0;
tonyp@2715 155 trace("initialized");
tonyp@2715 156 }
tonyp@2715 157
tonyp@3028 158 void G1AllocRegion::set(HeapRegion* alloc_region) {
tonyp@3028 159 trace("setting");
tonyp@3028 160 // We explicitly check that the region is not empty to make sure we
tonyp@3028 161 // maintain the "the alloc region cannot be empty" invariant.
tonyp@3028 162 assert(alloc_region != NULL && !alloc_region->is_empty(),
tonyp@3028 163 ar_ext_msg(this, "pre-condition"));
tonyp@3028 164 assert(_alloc_region == _dummy_region &&
tonyp@3028 165 _used_bytes_before == 0 && _count == 0,
tonyp@3028 166 ar_ext_msg(this, "pre-condition"));
tonyp@3028 167
tonyp@3028 168 _used_bytes_before = alloc_region->used();
tonyp@3028 169 _alloc_region = alloc_region;
tonyp@3028 170 _count += 1;
tonyp@3028 171 trace("set");
tonyp@3028 172 }
tonyp@3028 173
tonyp@2715 174 HeapRegion* G1AllocRegion::release() {
tonyp@2715 175 trace("releasing");
tonyp@2715 176 HeapRegion* alloc_region = _alloc_region;
tonyp@2715 177 retire(false /* fill_up */);
tonyp@3028 178 assert(_alloc_region == _dummy_region,
tonyp@3028 179 ar_ext_msg(this, "post-condition of retire()"));
tonyp@2715 180 _alloc_region = NULL;
tonyp@2715 181 trace("released");
tonyp@2715 182 return (alloc_region == _dummy_region) ? NULL : alloc_region;
tonyp@2715 183 }
tonyp@2715 184
tonyp@2715 185 #if G1_ALLOC_REGION_TRACING
tonyp@2715 186 void G1AllocRegion::trace(const char* str, size_t word_size, HeapWord* result) {
tonyp@2715 187 // All the calls to trace that set either just the size or the size
tonyp@2715 188 // and the result are considered part of level 2 tracing and are
tonyp@2715 189 // skipped during level 1 tracing.
tonyp@2715 190 if ((word_size == 0 && result == NULL) || (G1_ALLOC_REGION_TRACING > 1)) {
tonyp@2715 191 const size_t buffer_length = 128;
tonyp@2715 192 char hr_buffer[buffer_length];
tonyp@2715 193 char rest_buffer[buffer_length];
tonyp@2715 194
tonyp@2715 195 HeapRegion* alloc_region = _alloc_region;
tonyp@2715 196 if (alloc_region == NULL) {
tonyp@2715 197 jio_snprintf(hr_buffer, buffer_length, "NULL");
tonyp@2715 198 } else if (alloc_region == _dummy_region) {
tonyp@2715 199 jio_snprintf(hr_buffer, buffer_length, "DUMMY");
tonyp@2715 200 } else {
tonyp@2715 201 jio_snprintf(hr_buffer, buffer_length,
tonyp@2715 202 HR_FORMAT, HR_FORMAT_PARAMS(alloc_region));
tonyp@2715 203 }
tonyp@2715 204
tonyp@2715 205 if (G1_ALLOC_REGION_TRACING > 1) {
tonyp@2715 206 if (result != NULL) {
tonyp@2715 207 jio_snprintf(rest_buffer, buffer_length, SIZE_FORMAT" "PTR_FORMAT,
tonyp@2715 208 word_size, result);
tonyp@2715 209 } else if (word_size != 0) {
tonyp@2715 210 jio_snprintf(rest_buffer, buffer_length, SIZE_FORMAT, word_size);
tonyp@2715 211 } else {
tonyp@2715 212 jio_snprintf(rest_buffer, buffer_length, "");
tonyp@2715 213 }
tonyp@2715 214 } else {
tonyp@2715 215 jio_snprintf(rest_buffer, buffer_length, "");
tonyp@2715 216 }
tonyp@2715 217
tonyp@3028 218 tty->print_cr("[%s] "SIZE_FORMAT" %s : %s %s",
tonyp@3028 219 _name, _count, hr_buffer, str, rest_buffer);
tonyp@2715 220 }
tonyp@2715 221 }
tonyp@2715 222 #endif // G1_ALLOC_REGION_TRACING
tonyp@2715 223
tonyp@2715 224 G1AllocRegion::G1AllocRegion(const char* name,
tonyp@2715 225 bool bot_updates)
tonyp@2715 226 : _name(name), _bot_updates(bot_updates),
tonyp@3028 227 _alloc_region(NULL), _count(0), _used_bytes_before(0) { }
tonyp@2715 228

mercurial