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

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

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7053
7b2fc3129653
child 7509
ae52ee069062
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

tschatzl@7051 1 /*
tschatzl@7051 2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
tschatzl@7051 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
tschatzl@7051 4 *
tschatzl@7051 5 * This code is free software; you can redistribute it and/or modify it
tschatzl@7051 6 * under the terms of the GNU General Public License version 2 only, as
tschatzl@7051 7 * published by the Free Software Foundation.
tschatzl@7051 8 *
tschatzl@7051 9 * This code is distributed in the hope that it will be useful, but WITHOUT
tschatzl@7051 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
tschatzl@7051 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
tschatzl@7051 12 * version 2 for more details (a copy is included in the LICENSE file that
tschatzl@7051 13 * accompanied this code).
tschatzl@7051 14 *
tschatzl@7051 15 * You should have received a copy of the GNU General Public License version
tschatzl@7051 16 * 2 along with this work; if not, write to the Free Software Foundation,
tschatzl@7051 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
tschatzl@7051 18 *
tschatzl@7051 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
tschatzl@7051 20 * or visit www.oracle.com if you need additional information or have any
tschatzl@7051 21 * questions.
tschatzl@7051 22 *
tschatzl@7051 23 */
tschatzl@7051 24
tschatzl@7051 25 #include "precompiled.hpp"
tschatzl@7051 26 #include "gc_implementation/g1/g1BiasedArray.hpp"
tschatzl@7051 27 #include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
tschatzl@7053 28 #include "memory/allocation.inline.hpp"
tschatzl@7051 29 #include "runtime/virtualspace.hpp"
tschatzl@7051 30 #include "services/memTracker.hpp"
tschatzl@7051 31 #include "utilities/bitMap.inline.hpp"
tschatzl@7051 32
tschatzl@7051 33 G1RegionToSpaceMapper::G1RegionToSpaceMapper(ReservedSpace rs,
tschatzl@7051 34 size_t commit_granularity,
tschatzl@7051 35 size_t region_granularity,
tschatzl@7051 36 MemoryType type) :
tschatzl@7051 37 _storage(),
tschatzl@7051 38 _commit_granularity(commit_granularity),
tschatzl@7051 39 _region_granularity(region_granularity),
tschatzl@7051 40 _listener(NULL),
tschatzl@7051 41 _commit_map() {
tschatzl@7051 42 guarantee(is_power_of_2(commit_granularity), "must be");
tschatzl@7051 43 guarantee(is_power_of_2(region_granularity), "must be");
tschatzl@7051 44 _storage.initialize_with_granularity(rs, commit_granularity);
tschatzl@7051 45
tschatzl@7051 46 MemTracker::record_virtual_memory_type((address)rs.base(), type);
tschatzl@7051 47 }
tschatzl@7051 48
tschatzl@7051 49 // G1RegionToSpaceMapper implementation where the region granularity is larger than
tschatzl@7051 50 // or the same as the commit granularity.
tschatzl@7051 51 // Basically, the space corresponding to one region region spans several OS pages.
tschatzl@7051 52 class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
tschatzl@7051 53 private:
tschatzl@7051 54 size_t _pages_per_region;
tschatzl@7051 55
tschatzl@7051 56 public:
tschatzl@7051 57 G1RegionsLargerThanCommitSizeMapper(ReservedSpace rs,
tschatzl@7051 58 size_t os_commit_granularity,
tschatzl@7051 59 size_t alloc_granularity,
tschatzl@7051 60 size_t commit_factor,
tschatzl@7051 61 MemoryType type) :
tschatzl@7051 62 G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type),
tschatzl@7051 63 _pages_per_region(alloc_granularity / (os_commit_granularity * commit_factor)) {
tschatzl@7051 64
tschatzl@7051 65 guarantee(alloc_granularity >= os_commit_granularity, "allocation granularity smaller than commit granularity");
tschatzl@7051 66 _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
tschatzl@7051 67 }
tschatzl@7051 68
tschatzl@7051 69 virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
tschatzl@7051 70 _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
tschatzl@7051 71 _commit_map.set_range(start_idx, start_idx + num_regions);
tschatzl@7257 72 fire_on_commit(start_idx, num_regions, true);
tschatzl@7051 73 }
tschatzl@7051 74
tschatzl@7051 75 virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
tschatzl@7051 76 _storage.uncommit(start_idx * _pages_per_region, num_regions * _pages_per_region);
tschatzl@7051 77 _commit_map.clear_range(start_idx, start_idx + num_regions);
tschatzl@7051 78 }
tschatzl@7051 79 };
tschatzl@7051 80
tschatzl@7051 81 // G1RegionToSpaceMapper implementation where the region granularity is smaller
tschatzl@7051 82 // than the commit granularity.
tschatzl@7051 83 // Basically, the contents of one OS page span several regions.
tschatzl@7051 84 class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
tschatzl@7051 85 private:
tschatzl@7051 86 class CommitRefcountArray : public G1BiasedMappedArray<uint> {
tschatzl@7051 87 protected:
tschatzl@7051 88 virtual uint default_value() const { return 0; }
tschatzl@7051 89 };
tschatzl@7051 90
tschatzl@7051 91 size_t _regions_per_page;
tschatzl@7051 92
tschatzl@7051 93 CommitRefcountArray _refcounts;
tschatzl@7051 94
tschatzl@7051 95 uintptr_t region_idx_to_page_idx(uint region) const {
tschatzl@7051 96 return region / _regions_per_page;
tschatzl@7051 97 }
tschatzl@7051 98
tschatzl@7051 99 public:
tschatzl@7051 100 G1RegionsSmallerThanCommitSizeMapper(ReservedSpace rs,
tschatzl@7051 101 size_t os_commit_granularity,
tschatzl@7051 102 size_t alloc_granularity,
tschatzl@7051 103 size_t commit_factor,
tschatzl@7051 104 MemoryType type) :
tschatzl@7051 105 G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type),
tschatzl@7051 106 _regions_per_page((os_commit_granularity * commit_factor) / alloc_granularity), _refcounts() {
tschatzl@7051 107
tschatzl@7051 108 guarantee((os_commit_granularity * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity");
tschatzl@7051 109 _refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + rs.size()), os_commit_granularity);
tschatzl@7051 110 _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
tschatzl@7051 111 }
tschatzl@7051 112
tschatzl@7051 113 virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
tschatzl@7051 114 for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) {
tschatzl@7051 115 assert(!_commit_map.at(i), err_msg("Trying to commit storage at region "INTPTR_FORMAT" that is already committed", i));
tschatzl@7051 116 uintptr_t idx = region_idx_to_page_idx(i);
tschatzl@7051 117 uint old_refcount = _refcounts.get_by_index(idx);
tschatzl@7257 118 bool zero_filled = false;
tschatzl@7051 119 if (old_refcount == 0) {
tschatzl@7051 120 _storage.commit(idx, 1);
tschatzl@7257 121 zero_filled = true;
tschatzl@7051 122 }
tschatzl@7051 123 _refcounts.set_by_index(idx, old_refcount + 1);
tschatzl@7051 124 _commit_map.set_bit(i);
tschatzl@7257 125 fire_on_commit(i, 1, zero_filled);
tschatzl@7051 126 }
tschatzl@7051 127 }
tschatzl@7051 128
tschatzl@7051 129 virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
tschatzl@7051 130 for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) {
tschatzl@7051 131 assert(_commit_map.at(i), err_msg("Trying to uncommit storage at region "INTPTR_FORMAT" that is not committed", i));
tschatzl@7051 132 uintptr_t idx = region_idx_to_page_idx(i);
tschatzl@7051 133 uint old_refcount = _refcounts.get_by_index(idx);
tschatzl@7051 134 assert(old_refcount > 0, "must be");
tschatzl@7051 135 if (old_refcount == 1) {
tschatzl@7051 136 _storage.uncommit(idx, 1);
tschatzl@7051 137 }
tschatzl@7051 138 _refcounts.set_by_index(idx, old_refcount - 1);
tschatzl@7051 139 _commit_map.clear_bit(i);
tschatzl@7051 140 }
tschatzl@7051 141 }
tschatzl@7051 142 };
tschatzl@7051 143
tschatzl@7257 144 void G1RegionToSpaceMapper::fire_on_commit(uint start_idx, size_t num_regions, bool zero_filled) {
tschatzl@7051 145 if (_listener != NULL) {
tschatzl@7257 146 _listener->on_commit(start_idx, num_regions, zero_filled);
tschatzl@7051 147 }
tschatzl@7051 148 }
tschatzl@7051 149
tschatzl@7051 150 G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_mapper(ReservedSpace rs,
tschatzl@7051 151 size_t os_commit_granularity,
tschatzl@7051 152 size_t region_granularity,
tschatzl@7051 153 size_t commit_factor,
tschatzl@7051 154 MemoryType type) {
tschatzl@7051 155
tschatzl@7051 156 if (region_granularity >= (os_commit_granularity * commit_factor)) {
tschatzl@7051 157 return new G1RegionsLargerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type);
tschatzl@7051 158 } else {
tschatzl@7051 159 return new G1RegionsSmallerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type);
tschatzl@7051 160 }
tschatzl@7051 161 }

mercurial