--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Fri May 09 08:34:22 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Fri May 09 19:47:41 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -194,23 +194,16 @@
}
bool RSHashTable::get_cards(RegionIdx_t region_ind, CardIdx_t* cards) {
- int ind = (int) (region_ind & capacity_mask());
- int cur_ind = _buckets[ind];
- SparsePRTEntry* cur;
- while (cur_ind != NullEntry &&
- (cur = entry(cur_ind))->r_ind() != region_ind) {
- cur_ind = cur->next_index();
+ SparsePRTEntry* entry = get_entry(region_ind);
+ if (entry == NULL) {
+ return false;
}
-
- if (cur_ind == NullEntry) return false;
// Otherwise...
- assert(cur->r_ind() == region_ind, "Postcondition of loop + test above.");
- assert(cur->num_valid_cards() > 0, "Inv");
- cur->copy_cards(cards);
+ entry->copy_cards(cards);
return true;
}
-SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) {
+SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) const {
int ind = (int) (region_ind & capacity_mask());
int cur_ind = _buckets[ind];
SparsePRTEntry* cur;
@@ -247,27 +240,8 @@
}
SparsePRTEntry*
-RSHashTable::entry_for_region_ind(RegionIdx_t region_ind) const {
- assert(occupied_entries() < capacity(), "Precondition");
- int ind = (int) (region_ind & capacity_mask());
- int cur_ind = _buckets[ind];
- SparsePRTEntry* cur;
- while (cur_ind != NullEntry &&
- (cur = entry(cur_ind))->r_ind() != region_ind) {
- cur_ind = cur->next_index();
- }
-
- if (cur_ind != NullEntry) {
- assert(cur->r_ind() == region_ind, "Loop postcondition + test");
- return cur;
- } else {
- return NULL;
- }
-}
-
-SparsePRTEntry*
RSHashTable::entry_for_region_ind_create(RegionIdx_t region_ind) {
- SparsePRTEntry* res = entry_for_region_ind(region_ind);
+ SparsePRTEntry* res = get_entry(region_ind);
if (res == NULL) {
int new_ind = alloc_entry();
assert(0 <= new_ind && (size_t)new_ind < capacity(), "There should be room.");
@@ -365,7 +339,7 @@
}
bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) const {
- SparsePRTEntry* e = entry_for_region_ind(region_index);
+ SparsePRTEntry* e = get_entry(region_index);
return (e != NULL && e->contains_card(card_index));
}
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Fri May 09 08:34:22 2014 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Fri May 09 19:47:41 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,12 +122,6 @@
// Requires that the caller hold a lock preventing parallel modifying
// operations, and that the the table be less than completely full. If
// an entry for "region_ind" is already in the table, finds it and
- // returns its address; otherwise returns "NULL."
- SparsePRTEntry* entry_for_region_ind(RegionIdx_t region_ind) const;
-
- // Requires that the caller hold a lock preventing parallel modifying
- // operations, and that the the table be less than completely full. If
- // an entry for "region_ind" is already in the table, finds it and
// returns its address; otherwise allocates, initializes, inserts and
// returns a new entry for "region_ind".
SparsePRTEntry* entry_for_region_ind_create(RegionIdx_t region_ind);
@@ -158,7 +152,7 @@
void add_entry(SparsePRTEntry* e);
- SparsePRTEntry* get_entry(RegionIdx_t region_id);
+ SparsePRTEntry* get_entry(RegionIdx_t region_id) const;
void clear();
--- a/hotspot/src/share/vm/memory/metaspace.cpp Fri May 09 08:34:22 2014 -0700
+++ b/hotspot/src/share/vm/memory/metaspace.cpp Fri May 09 19:47:41 2014 -0700
@@ -1431,10 +1431,9 @@
}
size_t capacity_until_gc = capacity_until_GC();
-
- if (capacity_until_gc <= committed_bytes) {
- return 0;
- }
+ assert(capacity_until_gc >= committed_bytes,
+ err_msg("capacity_until_gc: " SIZE_FORMAT " < committed_bytes: " SIZE_FORMAT,
+ capacity_until_gc, committed_bytes));
size_t left_until_GC = capacity_until_gc - committed_bytes;
size_t left_to_commit = MIN2(left_until_GC, left_until_max);
@@ -1447,7 +1446,15 @@
uint current_shrink_factor = _shrink_factor;
_shrink_factor = 0;
- const size_t used_after_gc = MetaspaceAux::capacity_bytes();
+ // Using committed_bytes() for used_after_gc is an overestimation, since the
+ // chunk free lists are included in committed_bytes() and the memory in an
+ // un-fragmented chunk free list is available for future allocations.
+ // However, if the chunk free lists becomes fragmented, then the memory may
+ // not be available for future allocations and the memory is therefore "in use".
+ // Including the chunk free lists in the definition of "in use" is therefore
+ // necessary. Not including the chunk free lists can cause capacity_until_GC to
+ // shrink below committed_bytes() and this has caused serious bugs in the past.
+ const size_t used_after_gc = MetaspaceAux::committed_bytes();
const size_t capacity_until_GC = MetaspaceGC::capacity_until_GC();
const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0;