# HG changeset patch # Parent e8aaebb625973b71c265d758e4964eb8d7a22320 # User tschatzl diff -r e8aaebb62597 src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp --- a/src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp Tue Apr 21 15:35:24 2015 +0200 +++ b/src/share/vm/gc/g1/g1RegionToSpaceMapper.cpp Tue Apr 21 15:35:48 2015 +0200 @@ -26,6 +26,7 @@ #include "gc/g1/g1BiasedArray.hpp" #include "gc/g1/g1RegionToSpaceMapper.hpp" #include "memory/allocation.inline.hpp" +#include "memory/resourceArea.hpp" #include "runtime/virtualspace.hpp" #include "services/memTracker.hpp" #include "utilities/bitMap.inline.hpp" @@ -112,17 +113,51 @@ } virtual void commit_regions(uint start_idx, size_t num_regions) { + // The algorithm to commit tries to merge commits to multiple pages into as + // few as possible commit calls to the OS. + // For this to work, we make multiple passes over the memory range: first we + // record the pages that actually need to be committed (in the want_to_commit + // bitmap) from the OS, then walk over this bitmap to commit and determine which + // of those were zero-filled, to later determine the correct value of the + // zero_filled parameter in the calls to the listener for the particular region. + + ResourceMark rm; // We allocate temporary bitmaps in the resource area. + + BitMap want_to_commit(_refcounts.length()); + want_to_commit.clear(); + for (uint i = start_idx; i < start_idx + num_regions; i++) { assert(!_commit_map.at(i), err_msg("Trying to commit storage at region %u that is already committed", i)); size_t idx = region_idx_to_page_idx(i); uint old_refcount = _refcounts.get_by_index(idx); - bool zero_filled = false; if (old_refcount == 0) { - zero_filled = _storage.commit(idx, 1); + want_to_commit.set_bit(idx); } _refcounts.set_by_index(idx, old_refcount + 1); _commit_map.set_bit(i); - fire_on_commit(i, 1, zero_filled); + } + + BitMap just_committed_zero_filled_answer(_refcounts.length()); + just_committed_zero_filled_answer.clear(); + + // Iterate over the want_to_commit page table to do the commit call and gather + // whether the committed area is already zero filled. + BitMap::idx_t want_commit_start = want_to_commit.get_next_one_offset(0); + while (want_commit_start != want_to_commit.size()) { + BitMap::idx_t want_commit_end = want_to_commit.get_next_zero_offset(want_commit_start + 1); + size_t len_to_commit = want_commit_end - want_commit_start; + guarantee(len_to_commit > 0, "must be"); + + bool zero_filled = _storage.commit(want_commit_start, len_to_commit); + if (zero_filled) { + just_committed_zero_filled_answer.set_range(want_commit_start, want_commit_end); + } + want_commit_start = want_to_commit.get_next_one_offset(want_commit_end); + } + + // Call the listeners with the appropriate values. + for (uint i = start_idx; i < start_idx + num_regions; i++) { + fire_on_commit(i, 1, just_committed_zero_filled_answer.at(region_idx_to_page_idx(i))); } }