src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp

Fri, 10 Oct 2014 15:51:58 +0200

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7256
0fcaab91d485
child 7535
7ae4e26cb1e0
child 9697
cfe3264deba4
permissions
-rw-r--r--

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

ysr@777 1 /*
drchase@6680 2 * Copyright (c) 2001, 2014, 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_G1BLOCKOFFSETTABLE_INLINE_HPP
stefank@2314 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
stefank@2314 27
stefank@2314 28 #include "gc_implementation/g1/g1BlockOffsetTable.hpp"
mgerdin@6990 29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
mgerdin@6990 30 #include "gc_implementation/g1/heapRegion.inline.hpp"
stefank@2314 31 #include "memory/space.hpp"
stefank@2314 32
ysr@777 33 inline HeapWord* G1BlockOffsetTable::block_start(const void* addr) {
ysr@777 34 if (addr >= _bottom && addr < _end) {
ysr@777 35 return block_start_unsafe(addr);
ysr@777 36 } else {
ysr@777 37 return NULL;
ysr@777 38 }
ysr@777 39 }
ysr@777 40
ysr@777 41 inline HeapWord*
ysr@777 42 G1BlockOffsetTable::block_start_const(const void* addr) const {
ysr@777 43 if (addr >= _bottom && addr < _end) {
ysr@777 44 return block_start_unsafe_const(addr);
ysr@777 45 } else {
ysr@777 46 return NULL;
ysr@777 47 }
ysr@777 48 }
ysr@777 49
tschatzl@7051 50 #define check_index(index, msg) \
tschatzl@7051 51 assert((index) < (_reserved.word_size() >> LogN_words), \
tschatzl@7051 52 err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT, \
tschatzl@7051 53 msg, (index), (_reserved.word_size() >> LogN_words))); \
tschatzl@7051 54 assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)), \
tschatzl@7051 55 err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT \
tschatzl@7051 56 " (%u) is not in committed area.", \
tschatzl@7051 57 (index), \
tschatzl@7051 58 p2i(address_for_index_raw(index)), \
tschatzl@7051 59 G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index))));
tschatzl@7051 60
tschatzl@7051 61 u_char G1BlockOffsetSharedArray::offset_array(size_t index) const {
tschatzl@7051 62 check_index(index, "index out of range");
tschatzl@7051 63 return _offset_array[index];
tschatzl@7051 64 }
tschatzl@7051 65
tschatzl@7051 66 void G1BlockOffsetSharedArray::set_offset_array(size_t index, u_char offset) {
tschatzl@7051 67 check_index(index, "index out of range");
tschatzl@7051 68 set_offset_array_raw(index, offset);
tschatzl@7051 69 }
tschatzl@7051 70
tschatzl@7051 71 void G1BlockOffsetSharedArray::set_offset_array(size_t index, HeapWord* high, HeapWord* low) {
tschatzl@7051 72 check_index(index, "index out of range");
tschatzl@7051 73 assert(high >= low, "addresses out of order");
tschatzl@7051 74 size_t offset = pointer_delta(high, low);
tschatzl@7051 75 check_offset(offset, "offset too large");
tschatzl@7051 76 set_offset_array(index, (u_char)offset);
tschatzl@7051 77 }
tschatzl@7051 78
tschatzl@7051 79 void G1BlockOffsetSharedArray::set_offset_array(size_t left, size_t right, u_char offset) {
tschatzl@7051 80 check_index(right, "right index out of range");
tschatzl@7051 81 assert(left <= right, "indexes out of order");
tschatzl@7051 82 size_t num_cards = right - left + 1;
tschatzl@7051 83 if (UseMemSetInBOT) {
tschatzl@7051 84 memset(&_offset_array[left], offset, num_cards);
tschatzl@7051 85 } else {
tschatzl@7051 86 size_t i = left;
tschatzl@7051 87 const size_t end = i + num_cards;
tschatzl@7051 88 for (; i < end; i++) {
tschatzl@7051 89 _offset_array[i] = offset;
tschatzl@7051 90 }
tschatzl@7051 91 }
tschatzl@7051 92 }
tschatzl@7051 93
tschatzl@7051 94 // Variant of index_for that does not check the index for validity.
tschatzl@7051 95 inline size_t G1BlockOffsetSharedArray::index_for_raw(const void* p) const {
tschatzl@7051 96 return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> LogN;
tschatzl@7051 97 }
tschatzl@7051 98
ysr@777 99 inline size_t G1BlockOffsetSharedArray::index_for(const void* p) const {
ysr@777 100 char* pc = (char*)p;
ysr@777 101 assert(pc >= (char*)_reserved.start() &&
ysr@777 102 pc < (char*)_reserved.end(),
johnc@4300 103 err_msg("p (" PTR_FORMAT ") not in reserved [" PTR_FORMAT ", " PTR_FORMAT ")",
drchase@6680 104 p2i(p), p2i(_reserved.start()), p2i(_reserved.end())));
tschatzl@7051 105 size_t result = index_for_raw(p);
johnc@4300 106 check_index(result, "bad index from address");
ysr@777 107 return result;
ysr@777 108 }
ysr@777 109
ysr@777 110 inline HeapWord*
ysr@777 111 G1BlockOffsetSharedArray::address_for_index(size_t index) const {
johnc@4300 112 check_index(index, "index out of range");
tschatzl@7051 113 HeapWord* result = address_for_index_raw(index);
ysr@777 114 assert(result >= _reserved.start() && result < _reserved.end(),
coleenp@4037 115 err_msg("bad address from index result " PTR_FORMAT
coleenp@4037 116 " _reserved.start() " PTR_FORMAT " _reserved.end() "
coleenp@4037 117 PTR_FORMAT,
drchase@6680 118 p2i(result), p2i(_reserved.start()), p2i(_reserved.end())));
ysr@777 119 return result;
ysr@777 120 }
ysr@777 121
tschatzl@7051 122 #undef check_index
tschatzl@7051 123
mgerdin@6987 124 inline size_t
mgerdin@6987 125 G1BlockOffsetArray::block_size(const HeapWord* p) const {
mgerdin@6987 126 return gsp()->block_size(p);
mgerdin@6987 127 }
mgerdin@6987 128
ysr@777 129 inline HeapWord*
ysr@777 130 G1BlockOffsetArray::block_at_or_preceding(const void* addr,
ysr@777 131 bool has_max_index,
ysr@777 132 size_t max_index) const {
ysr@777 133 assert(_array->offset_array(0) == 0, "objects can't cross covered areas");
ysr@777 134 size_t index = _array->index_for(addr);
ysr@777 135 // We must make sure that the offset table entry we use is valid. If
ysr@777 136 // "addr" is past the end, start at the last known one and go forward.
ysr@777 137 if (has_max_index) {
ysr@777 138 index = MIN2(index, max_index);
ysr@777 139 }
ysr@777 140 HeapWord* q = _array->address_for_index(index);
ysr@777 141
ysr@777 142 uint offset = _array->offset_array(index); // Extend u_char to uint.
ysr@777 143 while (offset >= N_words) {
ysr@777 144 // The excess of the offset from N_words indicates a power of Base
ysr@777 145 // to go back by.
ysr@777 146 size_t n_cards_back = BlockOffsetArray::entry_to_cards_back(offset);
ysr@777 147 q -= (N_words * n_cards_back);
mgerdin@6987 148 assert(q >= gsp()->bottom(), "Went below bottom!");
ysr@777 149 index -= n_cards_back;
ysr@777 150 offset = _array->offset_array(index);
ysr@777 151 }
ysr@777 152 assert(offset < N_words, "offset too large");
ysr@777 153 q -= offset;
ysr@777 154 return q;
ysr@777 155 }
ysr@777 156
ysr@777 157 inline HeapWord*
ysr@777 158 G1BlockOffsetArray::
ysr@777 159 forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n,
ysr@777 160 const void* addr) const {
mgerdin@6987 161 if (addr >= gsp()->top()) return gsp()->top();
mgerdin@6987 162 while (n <= addr) {
mgerdin@6987 163 q = n;
mgerdin@6987 164 oop obj = oop(q);
mgerdin@6987 165 if (obj->klass_or_null() == NULL) return q;
stefank@6992 166 n += block_size(q);
ysr@777 167 }
ysr@777 168 assert(q <= n, "wrong order for q and addr");
ysr@777 169 assert(addr < n, "wrong order for addr and n");
ysr@777 170 return q;
ysr@777 171 }
ysr@777 172
ysr@777 173 inline HeapWord*
ysr@777 174 G1BlockOffsetArray::forward_to_block_containing_addr(HeapWord* q,
ysr@777 175 const void* addr) {
ysr@1280 176 if (oop(q)->klass_or_null() == NULL) return q;
mgerdin@6987 177 HeapWord* n = q + block_size(q);
ysr@777 178 // In the normal case, where the query "addr" is a card boundary, and the
ysr@777 179 // offset table chunks are the same size as cards, the block starting at
ysr@777 180 // "q" will contain addr, so the test below will fail, and we'll fall
ysr@777 181 // through quickly.
ysr@777 182 if (n <= addr) {
ysr@777 183 q = forward_to_block_containing_addr_slow(q, n, addr);
ysr@777 184 }
ysr@777 185 assert(q <= addr, "wrong order for current and arg");
ysr@777 186 return q;
ysr@777 187 }
ysr@777 188
stefank@2314 189 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP

mercurial