--- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp Fri Oct 19 11:26:17 2012 -0700
+++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp Tue Sep 18 23:35:42 2012 -0700
@@ -25,9 +25,15 @@
#include "precompiled.hpp"
#include "gc_implementation/shared/allocationStats.hpp"
#include "memory/binaryTreeDictionary.hpp"
+#include "memory/freeList.hpp"
+#include "memory/freeBlockDictionary.hpp"
+#include "memory/metablock.hpp"
+#include "memory/metachunk.hpp"
#include "runtime/globals.hpp"
#include "utilities/ostream.hpp"
#ifndef SERIALGC
+#include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp"
+#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
#include "gc_implementation/shared/spaceDecorator.hpp"
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
#endif // SERIALGC
@@ -37,15 +43,18 @@
// This is currently used in the Concurrent Mark&Sweep implementation.
////////////////////////////////////////////////////////////////////////////////
-template <class Chunk>
-TreeChunk<Chunk>* TreeChunk<Chunk>::as_TreeChunk(Chunk* fc) {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t TreeChunk<Chunk_t, FreeList_t>::_min_tree_chunk_size = sizeof(TreeChunk<Chunk_t, FreeList_t>)/HeapWordSize;
+
+template <class Chunk_t, template <class> class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>* TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(Chunk_t* fc) {
// Do some assertion checking here.
- return (TreeChunk<Chunk>*) fc;
+ return (TreeChunk<Chunk_t, FreeList_t>*) fc;
}
-template <class Chunk>
-void TreeChunk<Chunk>::verify_tree_chunk_list() const {
- TreeChunk<Chunk>* nextTC = (TreeChunk<Chunk>*)next();
+template <class Chunk_t, template <class> class FreeList_t>
+void TreeChunk<Chunk_t, FreeList_t>::verify_tree_chunk_list() const {
+ TreeChunk<Chunk_t, FreeList_t>* nextTC = (TreeChunk<Chunk_t, FreeList_t>*)next();
if (prev() != NULL) { // interior list node shouldn'r have tree fields
guarantee(embedded_list()->parent() == NULL && embedded_list()->left() == NULL &&
embedded_list()->right() == NULL, "should be clear");
@@ -57,53 +66,113 @@
}
}
+template <class Chunk_t, template <class> class FreeList_t>
+TreeList<Chunk_t, FreeList_t>::TreeList() {}
-template <class Chunk>
-TreeList<Chunk>* TreeList<Chunk>::as_TreeList(TreeChunk<Chunk>* tc) {
+template <class Chunk_t, template <class> class FreeList_t>
+TreeList<Chunk_t, FreeList_t>*
+TreeList<Chunk_t, FreeList_t>::as_TreeList(TreeChunk<Chunk_t,FreeList_t>* tc) {
// This first free chunk in the list will be the tree list.
- assert(tc->size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "Chunk is too small for a TreeChunk");
- TreeList<Chunk>* tl = tc->embedded_list();
+ assert((tc->size() >= (TreeChunk<Chunk_t, FreeList_t>::min_size())),
+ "Chunk is too small for a TreeChunk");
+ TreeList<Chunk_t, FreeList_t>* tl = tc->embedded_list();
+ tl->initialize();
tc->set_list(tl);
-#ifdef ASSERT
- tl->set_protecting_lock(NULL);
-#endif
- tl->set_hint(0);
tl->set_size(tc->size());
tl->link_head(tc);
tl->link_tail(tc);
tl->set_count(1);
- tl->init_statistics(true /* split_birth */);
- tl->set_parent(NULL);
- tl->set_left(NULL);
- tl->set_right(NULL);
+
+ return tl;
+}
+
+
+template <class Chunk_t, template <class> class FreeList_t>
+TreeList<Chunk_t, FreeList_t>*
+get_chunk(size_t size, enum FreeBlockDictionary<Chunk_t>::Dither dither) {
+ FreeBlockDictionary<Chunk_t>::verify_par_locked();
+ Chunk_t* res = get_chunk_from_tree(size, dither);
+ assert(res == NULL || res->is_free(),
+ "Should be returning a free chunk");
+ assert(dither != FreeBlockDictionary<Chunk_t>::exactly ||
+ res->size() == size, "Not correct size");
+ return res;
+}
+
+template <class Chunk_t, template <class> class FreeList_t>
+TreeList<Chunk_t, FreeList_t>*
+TreeList<Chunk_t, FreeList_t>::as_TreeList(HeapWord* addr, size_t size) {
+ TreeChunk<Chunk_t, FreeList_t>* tc = (TreeChunk<Chunk_t, FreeList_t>*) addr;
+ assert((size >= TreeChunk<Chunk_t, FreeList_t>::min_size()),
+ "Chunk is too small for a TreeChunk");
+ // The space will have been mangled initially but
+ // is not remangled when a Chunk_t is returned to the free list
+ // (since it is used to maintain the chunk on the free list).
+ tc->assert_is_mangled();
+ tc->set_size(size);
+ tc->link_prev(NULL);
+ tc->link_next(NULL);
+ TreeList<Chunk_t, FreeList_t>* tl = TreeList<Chunk_t, FreeList_t>::as_TreeList(tc);
return tl;
}
-template <class Chunk>
-TreeList<Chunk>* TreeList<Chunk>::as_TreeList(HeapWord* addr, size_t size) {
- TreeChunk<Chunk>* tc = (TreeChunk<Chunk>*) addr;
- assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "Chunk is too small for a TreeChunk");
- // The space in the heap will have been mangled initially but
- // is not remangled when a free chunk is returned to the free list
- // (since it is used to maintain the chunk on the free list).
- assert((ZapUnusedHeapArea &&
- SpaceMangler::is_mangled((HeapWord*) tc->size_addr()) &&
- SpaceMangler::is_mangled((HeapWord*) tc->prev_addr()) &&
- SpaceMangler::is_mangled((HeapWord*) tc->next_addr())) ||
- (tc->size() == 0 && tc->prev() == NULL && tc->next() == NULL),
- "Space should be clear or mangled");
- tc->set_size(size);
- tc->link_prev(NULL);
- tc->link_next(NULL);
- TreeList<Chunk>* tl = TreeList<Chunk>::as_TreeList(tc);
- return tl;
+
+#ifndef SERIALGC
+// Specialize for AdaptiveFreeList which tries to avoid
+// splitting a chunk of a size that is under populated in favor of
+// an over populated size. The general get_better_list() just returns
+// the current list.
+template <>
+TreeList<FreeChunk, AdaptiveFreeList>*
+TreeList<FreeChunk, AdaptiveFreeList>::get_better_list(
+ BinaryTreeDictionary<FreeChunk, ::AdaptiveFreeList>* dictionary) {
+ // A candidate chunk has been found. If it is already under
+ // populated, get a chunk associated with the hint for this
+ // chunk.
+
+ TreeList<FreeChunk, ::AdaptiveFreeList>* curTL = this;
+ if (surplus() <= 0) {
+ /* Use the hint to find a size with a surplus, and reset the hint. */
+ TreeList<FreeChunk, ::AdaptiveFreeList>* hintTL = this;
+ while (hintTL->hint() != 0) {
+ assert(hintTL->hint() > hintTL->size(),
+ "hint points in the wrong direction");
+ hintTL = dictionary->find_list(hintTL->hint());
+ assert(curTL != hintTL, "Infinite loop");
+ if (hintTL == NULL ||
+ hintTL == curTL /* Should not happen but protect against it */ ) {
+ // No useful hint. Set the hint to NULL and go on.
+ curTL->set_hint(0);
+ break;
+ }
+ assert(hintTL->size() > curTL->size(), "hint is inconsistent");
+ if (hintTL->surplus() > 0) {
+ // The hint led to a list that has a surplus. Use it.
+ // Set the hint for the candidate to an overpopulated
+ // size.
+ curTL->set_hint(hintTL->size());
+ // Change the candidate.
+ curTL = hintTL;
+ break;
+ }
+ }
+ }
+ return curTL;
+}
+#endif // SERIALGC
+
+template <class Chunk_t, template <class> class FreeList_t>
+TreeList<Chunk_t, FreeList_t>*
+TreeList<Chunk_t, FreeList_t>::get_better_list(
+ BinaryTreeDictionary<Chunk_t, FreeList_t>* dictionary) {
+ return this;
}
-template <class Chunk>
-TreeList<Chunk>* TreeList<Chunk>::remove_chunk_replace_if_needed(TreeChunk<Chunk>* tc) {
+template <class Chunk_t, template <class> class FreeList_t>
+TreeList<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::remove_chunk_replace_if_needed(TreeChunk<Chunk_t, FreeList_t>* tc) {
- TreeList<Chunk>* retTL = this;
- Chunk* list = head();
+ TreeList<Chunk_t, FreeList_t>* retTL = this;
+ Chunk_t* list = head();
assert(!list || list != list->next(), "Chunk on list twice");
assert(tc != NULL, "Chunk being removed is NULL");
assert(parent() == NULL || this == parent()->left() ||
@@ -112,13 +181,13 @@
assert(head() == NULL || head()->prev() == NULL, "list invariant");
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
- Chunk* prevFC = tc->prev();
- TreeChunk<Chunk>* nextTC = TreeChunk<Chunk>::as_TreeChunk(tc->next());
+ Chunk_t* prevFC = tc->prev();
+ TreeChunk<Chunk_t, FreeList_t>* nextTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(tc->next());
assert(list != NULL, "should have at least the target chunk");
// Is this the first item on the list?
if (tc == list) {
- // The "getChunk..." functions for a TreeList<Chunk> will not return the
+ // The "getChunk..." functions for a TreeList<Chunk_t, FreeList_t> will not return the
// first chunk in the list unless it is the last chunk in the list
// because the first chunk is also acting as the tree node.
// When coalescing happens, however, the first chunk in the a tree
@@ -127,8 +196,8 @@
// allocated when the sweeper yields (giving up the free list lock)
// to allow mutator activity. If this chunk is the first in the
// list and is not the last in the list, do the work to copy the
- // TreeList<Chunk> from the first chunk to the next chunk and update all
- // the TreeList<Chunk> pointers in the chunks in the list.
+ // TreeList<Chunk_t, FreeList_t> from the first chunk to the next chunk and update all
+ // the TreeList<Chunk_t, FreeList_t> pointers in the chunks in the list.
if (nextTC == NULL) {
assert(prevFC == NULL, "Not last chunk in the list");
set_tail(NULL);
@@ -141,11 +210,11 @@
// This can be slow for a long list. Consider having
// an option that does not allow the first chunk on the
// list to be coalesced.
- for (TreeChunk<Chunk>* curTC = nextTC; curTC != NULL;
- curTC = TreeChunk<Chunk>::as_TreeChunk(curTC->next())) {
+ for (TreeChunk<Chunk_t, FreeList_t>* curTC = nextTC; curTC != NULL;
+ curTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(curTC->next())) {
curTC->set_list(retTL);
}
- // Fix the parent to point to the new TreeList<Chunk>.
+ // Fix the parent to point to the new TreeList<Chunk_t, FreeList_t>.
if (retTL->parent() != NULL) {
if (this == retTL->parent()->left()) {
retTL->parent()->set_left(retTL);
@@ -176,9 +245,9 @@
prevFC->link_after(nextTC);
}
- // Below this point the embeded TreeList<Chunk> being used for the
+ // Below this point the embeded TreeList<Chunk_t, FreeList_t> being used for the
// tree node may have changed. Don't use "this"
- // TreeList<Chunk>*.
+ // TreeList<Chunk_t, FreeList_t>*.
// chunk should still be a free chunk (bit set in _prev)
assert(!retTL->head() || retTL->size() == retTL->head()->size(),
"Wrong sized chunk in list");
@@ -188,7 +257,7 @@
tc->set_list(NULL);
bool prev_found = false;
bool next_found = false;
- for (Chunk* curFC = retTL->head();
+ for (Chunk_t* curFC = retTL->head();
curFC != NULL; curFC = curFC->next()) {
assert(curFC != tc, "Chunk is still in list");
if (curFC == prevFC) {
@@ -215,8 +284,8 @@
return retTL;
}
-template <class Chunk>
-void TreeList<Chunk>::return_chunk_at_tail(TreeChunk<Chunk>* chunk) {
+template <class Chunk_t, template <class> class FreeList_t>
+void TreeList<Chunk_t, FreeList_t>::return_chunk_at_tail(TreeChunk<Chunk_t, FreeList_t>* chunk) {
assert(chunk != NULL, "returning NULL chunk");
assert(chunk->list() == this, "list should be set for chunk");
assert(tail() != NULL, "The tree list is embedded in the first chunk");
@@ -225,12 +294,12 @@
assert(head() == NULL || head()->prev() == NULL, "list invariant");
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
- Chunk* fc = tail();
+ Chunk_t* fc = tail();
fc->link_after(chunk);
link_tail(chunk);
assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
- increment_count();
+ FreeList_t<Chunk_t>::increment_count();
debug_only(increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
assert(head() == NULL || head()->prev() == NULL, "list invariant");
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
@@ -238,10 +307,10 @@
// Add this chunk at the head of the list. "At the head of the list"
// is defined to be after the chunk pointer to by head(). This is
-// because the TreeList<Chunk> is embedded in the first TreeChunk<Chunk> in the
-// list. See the definition of TreeChunk<Chunk>.
-template <class Chunk>
-void TreeList<Chunk>::return_chunk_at_head(TreeChunk<Chunk>* chunk) {
+// because the TreeList<Chunk_t, FreeList_t> is embedded in the first TreeChunk<Chunk_t, FreeList_t> in the
+// list. See the definition of TreeChunk<Chunk_t, FreeList_t>.
+template <class Chunk_t, template <class> class FreeList_t>
+void TreeList<Chunk_t, FreeList_t>::return_chunk_at_head(TreeChunk<Chunk_t, FreeList_t>* chunk) {
assert(chunk->list() == this, "list should be set for chunk");
assert(head() != NULL, "The tree list is embedded in the first chunk");
assert(chunk != NULL, "returning NULL chunk");
@@ -249,7 +318,7 @@
assert(head() == NULL || head()->prev() == NULL, "list invariant");
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
- Chunk* fc = head()->next();
+ Chunk_t* fc = head()->next();
if (fc != NULL) {
chunk->link_after(fc);
} else {
@@ -258,28 +327,38 @@
}
head()->link_after(chunk);
assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
- increment_count();
+ FreeList_t<Chunk_t>::increment_count();
debug_only(increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
assert(head() == NULL || head()->prev() == NULL, "list invariant");
assert(tail() == NULL || tail()->next() == NULL, "list invariant");
}
-template <class Chunk>
-TreeChunk<Chunk>* TreeList<Chunk>::head_as_TreeChunk() {
- assert(head() == NULL || TreeChunk<Chunk>::as_TreeChunk(head())->list() == this,
- "Wrong type of chunk?");
- return TreeChunk<Chunk>::as_TreeChunk(head());
+template <class Chunk_t, template <class> class FreeList_t>
+void TreeChunk<Chunk_t, FreeList_t>::assert_is_mangled() const {
+ assert((ZapUnusedHeapArea &&
+ SpaceMangler::is_mangled((HeapWord*) Chunk_t::size_addr()) &&
+ SpaceMangler::is_mangled((HeapWord*) Chunk_t::prev_addr()) &&
+ SpaceMangler::is_mangled((HeapWord*) Chunk_t::next_addr())) ||
+ (size() == 0 && prev() == NULL && next() == NULL),
+ "Space should be clear or mangled");
}
-template <class Chunk>
-TreeChunk<Chunk>* TreeList<Chunk>::first_available() {
+template <class Chunk_t, template <class> class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::head_as_TreeChunk() {
+ assert(head() == NULL || (TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(head())->list() == this),
+ "Wrong type of chunk?");
+ return TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(head());
+}
+
+template <class Chunk_t, template <class> class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::first_available() {
assert(head() != NULL, "The head of the list cannot be NULL");
- Chunk* fc = head()->next();
- TreeChunk<Chunk>* retTC;
+ Chunk_t* fc = head()->next();
+ TreeChunk<Chunk_t, FreeList_t>* retTC;
if (fc == NULL) {
retTC = head_as_TreeChunk();
} else {
- retTC = TreeChunk<Chunk>::as_TreeChunk(fc);
+ retTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
}
assert(retTC->list() == this, "Wrong type of chunk.");
return retTC;
@@ -288,41 +367,32 @@
// Returns the block with the largest heap address amongst
// those in the list for this size; potentially slow and expensive,
// use with caution!
-template <class Chunk>
-TreeChunk<Chunk>* TreeList<Chunk>::largest_address() {
+template <class Chunk_t, template <class> class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::largest_address() {
assert(head() != NULL, "The head of the list cannot be NULL");
- Chunk* fc = head()->next();
- TreeChunk<Chunk>* retTC;
+ Chunk_t* fc = head()->next();
+ TreeChunk<Chunk_t, FreeList_t>* retTC;
if (fc == NULL) {
retTC = head_as_TreeChunk();
} else {
// walk down the list and return the one with the highest
// heap address among chunks of this size.
- Chunk* last = fc;
+ Chunk_t* last = fc;
while (fc->next() != NULL) {
if ((HeapWord*)last < (HeapWord*)fc) {
last = fc;
}
fc = fc->next();
}
- retTC = TreeChunk<Chunk>::as_TreeChunk(last);
+ retTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(last);
}
assert(retTC->list() == this, "Wrong type of chunk.");
return retTC;
}
-template <class Chunk>
-BinaryTreeDictionary<Chunk>::BinaryTreeDictionary(bool adaptive_freelists, bool splay) :
- _splay(splay), _adaptive_freelists(adaptive_freelists),
- _total_size(0), _total_free_blocks(0), _root(0) {}
-
-template <class Chunk>
-BinaryTreeDictionary<Chunk>::BinaryTreeDictionary(MemRegion mr,
- bool adaptive_freelists,
- bool splay):
- _adaptive_freelists(adaptive_freelists), _splay(splay)
-{
- assert(mr.word_size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
+template <class Chunk_t, template <class> class FreeList_t>
+BinaryTreeDictionary<Chunk_t, FreeList_t>::BinaryTreeDictionary(MemRegion mr) {
+ assert((mr.byte_size() > min_size()), "minimum chunk size");
reset(mr);
assert(root()->left() == NULL, "reset check failed");
@@ -333,52 +403,48 @@
assert(total_free_blocks() == 1, "reset check failed");
}
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::inc_total_size(size_t inc) {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::inc_total_size(size_t inc) {
_total_size = _total_size + inc;
}
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::dec_total_size(size_t dec) {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::dec_total_size(size_t dec) {
_total_size = _total_size - dec;
}
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::reset(MemRegion mr) {
- assert(mr.word_size() >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
- set_root(TreeList<Chunk>::as_TreeList(mr.start(), mr.word_size()));
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset(MemRegion mr) {
+ assert((mr.byte_size() > min_size()), "minimum chunk size");
+ set_root(TreeList<Chunk_t, FreeList_t>::as_TreeList(mr.start(), mr.word_size()));
set_total_size(mr.word_size());
set_total_free_blocks(1);
}
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::reset(HeapWord* addr, size_t byte_size) {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset(HeapWord* addr, size_t byte_size) {
MemRegion mr(addr, heap_word_size(byte_size));
reset(mr);
}
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::reset() {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset() {
set_root(NULL);
set_total_size(0);
set_total_free_blocks(0);
}
// Get a free block of size at least size from tree, or NULL.
-// If a splay step is requested, the removal algorithm (only) incorporates
-// a splay step as follows:
-// . the search proceeds down the tree looking for a possible
-// match. At the (closest) matching location, an appropriate splay step is applied
-// (zig, zig-zig or zig-zag). A chunk of the appropriate size is then returned
-// if available, and if it's the last chunk, the node is deleted. A deteleted
-// node is replaced in place by its tree successor.
-template <class Chunk>
-TreeChunk<Chunk>*
-BinaryTreeDictionary<Chunk>::get_chunk_from_tree(size_t size, enum FreeBlockDictionary<Chunk>::Dither dither, bool splay)
+template <class Chunk_t, template <class> class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>*
+BinaryTreeDictionary<Chunk_t, FreeList_t>::get_chunk_from_tree(
+ size_t size,
+ enum FreeBlockDictionary<Chunk_t>::Dither dither)
{
- TreeList<Chunk> *curTL, *prevTL;
- TreeChunk<Chunk>* retTC = NULL;
- assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "minimum chunk size");
+ TreeList<Chunk_t, FreeList_t> *curTL, *prevTL;
+ TreeChunk<Chunk_t, FreeList_t>* retTC = NULL;
+
+ assert((size >= min_size()), "minimum chunk size");
if (FLSVerifyDictionary) {
verify_tree();
}
@@ -398,7 +464,7 @@
}
if (curTL == NULL) { // couldn't find exact match
- if (dither == FreeBlockDictionary<Chunk>::exactly) return NULL;
+ if (dither == FreeBlockDictionary<Chunk_t>::exactly) return NULL;
// try and find the next larger size by walking back up the search path
for (curTL = prevTL; curTL != NULL;) {
@@ -410,46 +476,9 @@
}
if (curTL != NULL) {
assert(curTL->size() >= size, "size inconsistency");
- if (adaptive_freelists()) {
- // A candidate chunk has been found. If it is already under
- // populated, get a chunk associated with the hint for this
- // chunk.
- if (curTL->surplus() <= 0) {
- /* Use the hint to find a size with a surplus, and reset the hint. */
- TreeList<Chunk>* hintTL = curTL;
- while (hintTL->hint() != 0) {
- assert(hintTL->hint() == 0 || hintTL->hint() > hintTL->size(),
- "hint points in the wrong direction");
- hintTL = find_list(hintTL->hint());
- assert(curTL != hintTL, "Infinite loop");
- if (hintTL == NULL ||
- hintTL == curTL /* Should not happen but protect against it */ ) {
- // No useful hint. Set the hint to NULL and go on.
- curTL->set_hint(0);
- break;
- }
- assert(hintTL->size() > size, "hint is inconsistent");
- if (hintTL->surplus() > 0) {
- // The hint led to a list that has a surplus. Use it.
- // Set the hint for the candidate to an overpopulated
- // size.
- curTL->set_hint(hintTL->size());
- // Change the candidate.
- curTL = hintTL;
- break;
- }
- // The evm code reset the hint of the candidate as
- // at an interim point. Why? Seems like this leaves
- // the hint pointing to a list that didn't work.
- // curTL->set_hint(hintTL->size());
- }
- }
- }
- // don't waste time splaying if chunk's singleton
- if (splay && curTL->head()->next() != NULL) {
- semi_splay_step(curTL);
- }
+ curTL = curTL->get_better_list(this);
+
retTC = curTL->first_available();
assert((retTC != NULL) && (curTL->count() > 0),
"A list in the binary tree should not be NULL");
@@ -465,9 +494,9 @@
return retTC;
}
-template <class Chunk>
-TreeList<Chunk>* BinaryTreeDictionary<Chunk>::find_list(size_t size) const {
- TreeList<Chunk>* curTL;
+template <class Chunk_t, template <class> class FreeList_t>
+TreeList<Chunk_t, FreeList_t>* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_list(size_t size) const {
+ TreeList<Chunk_t, FreeList_t>* curTL;
for (curTL = root(); curTL != NULL;) {
if (curTL->size() == size) { // exact match
break;
@@ -484,10 +513,10 @@
}
-template <class Chunk>
-bool BinaryTreeDictionary<Chunk>::verify_chunk_in_free_list(Chunk* tc) const {
+template <class Chunk_t, template <class> class FreeList_t>
+bool BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_chunk_in_free_list(Chunk_t* tc) const {
size_t size = tc->size();
- TreeList<Chunk>* tl = find_list(size);
+ TreeList<Chunk_t, FreeList_t>* tl = find_list(size);
if (tl == NULL) {
return false;
} else {
@@ -495,9 +524,9 @@
}
}
-template <class Chunk>
-Chunk* BinaryTreeDictionary<Chunk>::find_largest_dict() const {
- TreeList<Chunk> *curTL = root();
+template <class Chunk_t, template <class> class FreeList_t>
+Chunk_t* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_largest_dict() const {
+ TreeList<Chunk_t, FreeList_t> *curTL = root();
if (curTL != NULL) {
while(curTL->right() != NULL) curTL = curTL->right();
return curTL->largest_address();
@@ -510,15 +539,15 @@
// chunk in a list on a tree node, just unlink it.
// If it is the last chunk in the list (the next link is NULL),
// remove the node and repair the tree.
-template <class Chunk>
-TreeChunk<Chunk>*
-BinaryTreeDictionary<Chunk>::remove_chunk_from_tree(TreeChunk<Chunk>* tc) {
+template <class Chunk_t, template <class> class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>*
+BinaryTreeDictionary<Chunk_t, FreeList_t>::remove_chunk_from_tree(TreeChunk<Chunk_t, FreeList_t>* tc) {
assert(tc != NULL, "Should not call with a NULL chunk");
assert(tc->is_free(), "Header is not marked correctly");
- TreeList<Chunk> *newTL, *parentTL;
- TreeChunk<Chunk>* retTC;
- TreeList<Chunk>* tl = tc->list();
+ TreeList<Chunk_t, FreeList_t> *newTL, *parentTL;
+ TreeChunk<Chunk_t, FreeList_t>* retTC;
+ TreeList<Chunk_t, FreeList_t>* tl = tc->list();
debug_only(
bool removing_only_chunk = false;
if (tl == _root) {
@@ -538,8 +567,8 @@
retTC = tc;
// Removing this chunk can have the side effect of changing the node
- // (TreeList<Chunk>*) in the tree. If the node is the root, update it.
- TreeList<Chunk>* replacementTL = tl->remove_chunk_replace_if_needed(tc);
+ // (TreeList<Chunk_t, FreeList_t>*) in the tree. If the node is the root, update it.
+ TreeList<Chunk_t, FreeList_t>* replacementTL = tl->remove_chunk_replace_if_needed(tc);
assert(tc->is_free(), "Chunk should still be free");
assert(replacementTL->parent() == NULL ||
replacementTL == replacementTL->parent()->left() ||
@@ -549,17 +578,18 @@
assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
set_root(replacementTL);
}
- debug_only(
+#ifdef ASSERT
if (tl != replacementTL) {
assert(replacementTL->head() != NULL,
"If the tree list was replaced, it should not be a NULL list");
- TreeList<Chunk>* rhl = replacementTL->head_as_TreeChunk()->list();
- TreeList<Chunk>* rtl = TreeChunk<Chunk>::as_TreeChunk(replacementTL->tail())->list();
+ TreeList<Chunk_t, FreeList_t>* rhl = replacementTL->head_as_TreeChunk()->list();
+ TreeList<Chunk_t, FreeList_t>* rtl =
+ TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(replacementTL->tail())->list();
assert(rhl == replacementTL, "Broken head");
assert(rtl == replacementTL, "Broken tail");
assert(replacementTL->size() == tc->size(), "Broken size");
}
- )
+#endif
// Does the tree need to be repaired?
if (replacementTL->count() == 0) {
@@ -574,7 +604,7 @@
} else if (replacementTL->right() == NULL) {
// right is NULL
newTL = replacementTL->left();
- debug_only(replacementTL->clearLeft();)
+ debug_only(replacementTL->clear_left();)
} else { // we have both children, so, by patriarchal convention,
// my replacement is least node in right sub-tree
complicated_splice = true;
@@ -623,7 +653,7 @@
newTL->set_right(replacementTL->right());
debug_only(
replacementTL->clear_right();
- replacementTL->clearLeft();
+ replacementTL->clear_left();
)
}
assert(replacementTL->right() == NULL &&
@@ -644,21 +674,21 @@
verify_tree();
}
assert(!removing_only_chunk || _root == NULL, "root should be NULL");
- return TreeChunk<Chunk>::as_TreeChunk(retTC);
+ return TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(retTC);
}
// Remove the leftmost node (lm) in the tree and return it.
// If lm has a right child, link it to the left node of
// the parent of lm.
-template <class Chunk>
-TreeList<Chunk>* BinaryTreeDictionary<Chunk>::remove_tree_minimum(TreeList<Chunk>* tl) {
+template <class Chunk_t, template <class> class FreeList_t>
+TreeList<Chunk_t, FreeList_t>* BinaryTreeDictionary<Chunk_t, FreeList_t>::remove_tree_minimum(TreeList<Chunk_t, FreeList_t>* tl) {
assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
// locate the subtree minimum by walking down left branches
- TreeList<Chunk>* curTL = tl;
+ TreeList<Chunk_t, FreeList_t>* curTL = tl;
for (; curTL->left() != NULL; curTL = curTL->left());
// obviously curTL now has at most one child, a right child
if (curTL != root()) { // Should this test just be removed?
- TreeList<Chunk>* parentTL = curTL->parent();
+ TreeList<Chunk_t, FreeList_t>* parentTL = curTL->parent();
if (parentTL->left() == curTL) { // curTL is a left child
parentTL->set_left(curTL->right());
} else {
@@ -685,31 +715,14 @@
return curTL;
}
-// Based on a simplification of the algorithm by Sleator and Tarjan (JACM 1985).
-// The simplifications are the following:
-// . we splay only when we delete (not when we insert)
-// . we apply a single spay step per deletion/access
-// By doing such partial splaying, we reduce the amount of restructuring,
-// while getting a reasonably efficient search tree (we think).
-// [Measurements will be needed to (in)validate this expectation.]
-
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::semi_splay_step(TreeList<Chunk>* tc) {
- // apply a semi-splay step at the given node:
- // . if root, norting needs to be done
- // . if child of root, splay once
- // . else zig-zig or sig-zag depending on path from grandparent
- if (root() == tc) return;
- warning("*** Splaying not yet implemented; "
- "tree operations may be inefficient ***");
-}
-
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::insert_chunk_in_tree(Chunk* fc) {
- TreeList<Chunk> *curTL, *prevTL;
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::insert_chunk_in_tree(Chunk_t* fc) {
+ TreeList<Chunk_t, FreeList_t> *curTL, *prevTL;
size_t size = fc->size();
- assert(size >= BinaryTreeDictionary<Chunk>::min_tree_chunk_size, "too small to be a TreeList<Chunk>");
+ assert((size >= min_size()),
+ err_msg(SIZE_FORMAT " is too small to be a TreeChunk<Chunk_t, FreeList_t> " SIZE_FORMAT,
+ size, min_size()));
if (FLSVerifyDictionary) {
verify_tree();
}
@@ -729,9 +742,9 @@
curTL = curTL->right();
}
}
- TreeChunk<Chunk>* tc = TreeChunk<Chunk>::as_TreeChunk(fc);
+ TreeChunk<Chunk_t, FreeList_t>* tc = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
// This chunk is being returned to the binary tree. Its embedded
- // TreeList<Chunk> should be unused at this point.
+ // TreeList<Chunk_t, FreeList_t> should be unused at this point.
tc->initialize();
if (curTL != NULL) { // exact match
tc->set_list(curTL);
@@ -739,8 +752,8 @@
} else { // need a new node in tree
tc->clear_next();
tc->link_prev(NULL);
- TreeList<Chunk>* newTL = TreeList<Chunk>::as_TreeList(tc);
- assert(((TreeChunk<Chunk>*)tc)->list() == newTL,
+ TreeList<Chunk_t, FreeList_t>* newTL = TreeList<Chunk_t, FreeList_t>::as_TreeList(tc);
+ assert(((TreeChunk<Chunk_t, FreeList_t>*)tc)->list() == newTL,
"List was not initialized correctly");
if (prevTL == NULL) { // we are the only tree node
assert(root() == NULL, "control point invariant");
@@ -768,30 +781,30 @@
}
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::max_chunk_size() const {
- FreeBlockDictionary<Chunk>::verify_par_locked();
- TreeList<Chunk>* tc = root();
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::max_chunk_size() const {
+ FreeBlockDictionary<Chunk_t>::verify_par_locked();
+ TreeList<Chunk_t, FreeList_t>* tc = root();
if (tc == NULL) return 0;
for (; tc->right() != NULL; tc = tc->right());
return tc->size();
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::total_list_length(TreeList<Chunk>* tl) const {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_list_length(TreeList<Chunk_t, FreeList_t>* tl) const {
size_t res;
res = tl->count();
#ifdef ASSERT
size_t cnt;
- Chunk* tc = tl->head();
+ Chunk_t* tc = tl->head();
for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
assert(res == cnt, "The count is not being maintained correctly");
#endif
return res;
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::total_size_in_tree(TreeList<Chunk>* tl) const {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_size_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
if (tl == NULL)
return 0;
return (tl->size() * total_list_length(tl)) +
@@ -799,8 +812,8 @@
total_size_in_tree(tl->right());
}
-template <class Chunk>
-double BinaryTreeDictionary<Chunk>::sum_of_squared_block_sizes(TreeList<Chunk>* const tl) const {
+template <class Chunk_t, template <class> class FreeList_t>
+double BinaryTreeDictionary<Chunk_t, FreeList_t>::sum_of_squared_block_sizes(TreeList<Chunk_t, FreeList_t>* const tl) const {
if (tl == NULL) {
return 0.0;
}
@@ -811,8 +824,8 @@
return curr;
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::total_free_blocks_in_tree(TreeList<Chunk>* tl) const {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_free_blocks_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
if (tl == NULL)
return 0;
return total_list_length(tl) +
@@ -820,28 +833,28 @@
total_free_blocks_in_tree(tl->right());
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::num_free_blocks() const {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::num_free_blocks() const {
assert(total_free_blocks_in_tree(root()) == total_free_blocks(),
"_total_free_blocks inconsistency");
return total_free_blocks();
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::tree_height_helper(TreeList<Chunk>* tl) const {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::tree_height_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
if (tl == NULL)
return 0;
return 1 + MAX2(tree_height_helper(tl->left()),
tree_height_helper(tl->right()));
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::treeHeight() const {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::tree_height() const {
return tree_height_helper(root());
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::total_nodes_helper(TreeList<Chunk>* tl) const {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_nodes_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
if (tl == NULL) {
return 0;
}
@@ -849,14 +862,18 @@
total_nodes_helper(tl->right());
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::total_nodes_in_tree(TreeList<Chunk>* tl) const {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_nodes_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
return total_nodes_helper(root());
}
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::dict_census_udpate(size_t size, bool split, bool birth){
- TreeList<Chunk>* nd = find_list(size);
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::dict_census_update(size_t size, bool split, bool birth){}
+
+#ifndef SERIALGC
+template <>
+void BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::dict_census_update(size_t size, bool split, bool birth){
+ TreeList<FreeChunk, AdaptiveFreeList>* nd = find_list(size);
if (nd) {
if (split) {
if (birth) {
@@ -882,16 +899,26 @@
// This is a birth associated with a LinAB. The chunk
// for the LinAB is not in the dictionary.
}
+#endif // SERIALGC
-template <class Chunk>
-bool BinaryTreeDictionary<Chunk>::coal_dict_over_populated(size_t size) {
+template <class Chunk_t, template <class> class FreeList_t>
+bool BinaryTreeDictionary<Chunk_t, FreeList_t>::coal_dict_over_populated(size_t size) {
+ // For the general type of freelists, encourage coalescing by
+ // returning true.
+ return true;
+}
+
+#ifndef SERIALGC
+template <>
+bool BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::coal_dict_over_populated(size_t size) {
if (FLSAlwaysCoalesceLarge) return true;
- TreeList<Chunk>* list_of_size = find_list(size);
+ TreeList<FreeChunk, AdaptiveFreeList>* list_of_size = find_list(size);
// None of requested size implies overpopulated.
return list_of_size == NULL || list_of_size->coal_desired() <= 0 ||
list_of_size->count() > list_of_size->coal_desired();
}
+#endif // SERIALGC
// Closures for walking the binary tree.
// do_list() walks the free list in a node applying the closure
@@ -899,19 +926,18 @@
// do_tree() walks the nodes in the binary tree applying do_list()
// to each list at each node.
-template <class Chunk>
+template <class Chunk_t, template <class> class FreeList_t>
class TreeCensusClosure : public StackObj {
protected:
- virtual void do_list(FreeList<Chunk>* fl) = 0;
+ virtual void do_list(FreeList_t<Chunk_t>* fl) = 0;
public:
- virtual void do_tree(TreeList<Chunk>* tl) = 0;
+ virtual void do_tree(TreeList<Chunk_t, FreeList_t>* tl) = 0;
};
-template <class Chunk>
-class AscendTreeCensusClosure : public TreeCensusClosure<Chunk> {
- using TreeCensusClosure<Chunk>::do_list;
+template <class Chunk_t, template <class> class FreeList_t>
+class AscendTreeCensusClosure : public TreeCensusClosure<Chunk_t, FreeList_t> {
public:
- void do_tree(TreeList<Chunk>* tl) {
+ void do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
if (tl != NULL) {
do_tree(tl->left());
do_list(tl);
@@ -920,11 +946,10 @@
}
};
-template <class Chunk>
-class DescendTreeCensusClosure : public TreeCensusClosure<Chunk> {
- using TreeCensusClosure<Chunk>::do_list;
+template <class Chunk_t, template <class> class FreeList_t>
+class DescendTreeCensusClosure : public TreeCensusClosure<Chunk_t, FreeList_t> {
public:
- void do_tree(TreeList<Chunk>* tl) {
+ void do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
if (tl != NULL) {
do_tree(tl->right());
do_list(tl);
@@ -935,8 +960,8 @@
// For each list in the tree, calculate the desired, desired
// coalesce, count before sweep, and surplus before sweep.
-template <class Chunk>
-class BeginSweepClosure : public AscendTreeCensusClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class BeginSweepClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
double _percentage;
float _inter_sweep_current;
float _inter_sweep_estimate;
@@ -951,32 +976,36 @@
_inter_sweep_estimate(inter_sweep_estimate),
_intra_sweep_estimate(intra_sweep_estimate) { }
- void do_list(FreeList<Chunk>* fl) {
+ void do_list(FreeList<Chunk_t>* fl) {}
+
+#ifndef SERIALGC
+ void do_list(AdaptiveFreeList<Chunk_t>* fl) {
double coalSurplusPercent = _percentage;
fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent));
fl->set_before_sweep(fl->count());
fl->set_bfr_surp(fl->surplus());
}
+#endif // SERIALGC
};
// Used to search the tree until a condition is met.
// Similar to TreeCensusClosure but searches the
// tree and returns promptly when found.
-template <class Chunk>
+template <class Chunk_t, template <class> class FreeList_t>
class TreeSearchClosure : public StackObj {
protected:
- virtual bool do_list(FreeList<Chunk>* fl) = 0;
+ virtual bool do_list(FreeList_t<Chunk_t>* fl) = 0;
public:
- virtual bool do_tree(TreeList<Chunk>* tl) = 0;
+ virtual bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) = 0;
};
#if 0 // Don't need this yet but here for symmetry.
-template <class Chunk>
-class AscendTreeSearchClosure : public TreeSearchClosure {
+template <class Chunk_t, template <class> class FreeList_t>
+class AscendTreeSearchClosure : public TreeSearchClosure<Chunk_t> {
public:
- bool do_tree(TreeList<Chunk>* tl) {
+ bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
if (tl != NULL) {
if (do_tree(tl->left())) return true;
if (do_list(tl)) return true;
@@ -987,11 +1016,10 @@
};
#endif
-template <class Chunk>
-class DescendTreeSearchClosure : public TreeSearchClosure<Chunk> {
- using TreeSearchClosure<Chunk>::do_list;
+template <class Chunk_t, template <class> class FreeList_t>
+class DescendTreeSearchClosure : public TreeSearchClosure<Chunk_t, FreeList_t> {
public:
- bool do_tree(TreeList<Chunk>* tl) {
+ bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
if (tl != NULL) {
if (do_tree(tl->right())) return true;
if (do_list(tl)) return true;
@@ -1003,17 +1031,17 @@
// Searches the tree for a chunk that ends at the
// specified address.
-template <class Chunk>
-class EndTreeSearchClosure : public DescendTreeSearchClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class EndTreeSearchClosure : public DescendTreeSearchClosure<Chunk_t, FreeList_t> {
HeapWord* _target;
- Chunk* _found;
+ Chunk_t* _found;
public:
EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
- bool do_list(FreeList<Chunk>* fl) {
- Chunk* item = fl->head();
+ bool do_list(FreeList_t<Chunk_t>* fl) {
+ Chunk_t* item = fl->head();
while (item != NULL) {
- if (item->end() == _target) {
+ if (item->end() == (uintptr_t*) _target) {
_found = item;
return true;
}
@@ -1021,22 +1049,22 @@
}
return false;
}
- Chunk* found() { return _found; }
+ Chunk_t* found() { return _found; }
};
-template <class Chunk>
-Chunk* BinaryTreeDictionary<Chunk>::find_chunk_ends_at(HeapWord* target) const {
- EndTreeSearchClosure<Chunk> etsc(target);
+template <class Chunk_t, template <class> class FreeList_t>
+Chunk_t* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_chunk_ends_at(HeapWord* target) const {
+ EndTreeSearchClosure<Chunk_t, FreeList_t> etsc(target);
bool found_target = etsc.do_tree(root());
assert(found_target || etsc.found() == NULL, "Consistency check");
assert(!found_target || etsc.found() != NULL, "Consistency check");
return etsc.found();
}
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::begin_sweep_dict_census(double coalSurplusPercent,
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::begin_sweep_dict_census(double coalSurplusPercent,
float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
- BeginSweepClosure<Chunk> bsc(coalSurplusPercent, inter_sweep_current,
+ BeginSweepClosure<Chunk_t, FreeList_t> bsc(coalSurplusPercent, inter_sweep_current,
inter_sweep_estimate,
intra_sweep_estimate);
bsc.do_tree(root());
@@ -1045,84 +1073,91 @@
// Closures and methods for calculating total bytes returned to the
// free lists in the tree.
#ifndef PRODUCT
-template <class Chunk>
-class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
public:
- void do_list(FreeList<Chunk>* fl) {
+ void do_list(FreeList_t<Chunk_t>* fl) {
fl->set_returned_bytes(0);
}
};
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::initialize_dict_returned_bytes() {
- InitializeDictReturnedBytesClosure<Chunk> idrb;
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::initialize_dict_returned_bytes() {
+ InitializeDictReturnedBytesClosure<Chunk_t, FreeList_t> idrb;
idrb.do_tree(root());
}
-template <class Chunk>
-class ReturnedBytesClosure : public AscendTreeCensusClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class ReturnedBytesClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
size_t _dict_returned_bytes;
public:
ReturnedBytesClosure() { _dict_returned_bytes = 0; }
- void do_list(FreeList<Chunk>* fl) {
+ void do_list(FreeList_t<Chunk_t>* fl) {
_dict_returned_bytes += fl->returned_bytes();
}
size_t dict_returned_bytes() { return _dict_returned_bytes; }
};
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::sum_dict_returned_bytes() {
- ReturnedBytesClosure<Chunk> rbc;
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::sum_dict_returned_bytes() {
+ ReturnedBytesClosure<Chunk_t, FreeList_t> rbc;
rbc.do_tree(root());
return rbc.dict_returned_bytes();
}
// Count the number of entries in the tree.
-template <class Chunk>
-class treeCountClosure : public DescendTreeCensusClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class treeCountClosure : public DescendTreeCensusClosure<Chunk_t, FreeList_t> {
public:
uint count;
treeCountClosure(uint c) { count = c; }
- void do_list(FreeList<Chunk>* fl) {
+ void do_list(FreeList_t<Chunk_t>* fl) {
count++;
}
};
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::total_count() {
- treeCountClosure<Chunk> ctc(0);
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_count() {
+ treeCountClosure<Chunk_t, FreeList_t> ctc(0);
ctc.do_tree(root());
return ctc.count;
}
#endif // PRODUCT
// Calculate surpluses for the lists in the tree.
-template <class Chunk>
-class setTreeSurplusClosure : public AscendTreeCensusClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class setTreeSurplusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
double percentage;
public:
setTreeSurplusClosure(double v) { percentage = v; }
- void do_list(FreeList<Chunk>* fl) {
+ void do_list(FreeList<Chunk_t>* fl) {}
+
+#ifndef SERIALGC
+ void do_list(AdaptiveFreeList<Chunk_t>* fl) {
double splitSurplusPercent = percentage;
fl->set_surplus(fl->count() -
(ssize_t)((double)fl->desired() * splitSurplusPercent));
}
+#endif // SERIALGC
};
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::set_tree_surplus(double splitSurplusPercent) {
- setTreeSurplusClosure<Chunk> sts(splitSurplusPercent);
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::set_tree_surplus(double splitSurplusPercent) {
+ setTreeSurplusClosure<Chunk_t, FreeList_t> sts(splitSurplusPercent);
sts.do_tree(root());
}
// Set hints for the lists in the tree.
-template <class Chunk>
-class setTreeHintsClosure : public DescendTreeCensusClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class setTreeHintsClosure : public DescendTreeCensusClosure<Chunk_t, FreeList_t> {
size_t hint;
public:
setTreeHintsClosure(size_t v) { hint = v; }
- void do_list(FreeList<Chunk>* fl) {
+ void do_list(FreeList<Chunk_t>* fl) {}
+
+#ifndef SERIALGC
+ void do_list(AdaptiveFreeList<Chunk_t>* fl) {
fl->set_hint(hint);
assert(fl->hint() == 0 || fl->hint() > fl->size(),
"Current hint is inconsistent");
@@ -1130,35 +1165,40 @@
hint = fl->size();
}
}
+#endif // SERIALGC
};
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::set_tree_hints(void) {
- setTreeHintsClosure<Chunk> sth(0);
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::set_tree_hints(void) {
+ setTreeHintsClosure<Chunk_t, FreeList_t> sth(0);
sth.do_tree(root());
}
// Save count before previous sweep and splits and coalesces.
-template <class Chunk>
-class clearTreeCensusClosure : public AscendTreeCensusClosure<Chunk> {
- void do_list(FreeList<Chunk>* fl) {
+template <class Chunk_t, template <class> class FreeList_t>
+class clearTreeCensusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
+ void do_list(FreeList<Chunk_t>* fl) {}
+
+#ifndef SERIALGC
+ void do_list(AdaptiveFreeList<Chunk_t>* fl) {
fl->set_prev_sweep(fl->count());
fl->set_coal_births(0);
fl->set_coal_deaths(0);
fl->set_split_births(0);
fl->set_split_deaths(0);
}
+#endif // SERIALGC
};
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::clear_tree_census(void) {
- clearTreeCensusClosure<Chunk> ctc;
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::clear_tree_census(void) {
+ clearTreeCensusClosure<Chunk_t, FreeList_t> ctc;
ctc.do_tree(root());
}
// Do reporting and post sweep clean up.
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::end_sweep_dict_census(double splitSurplusPercent) {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::end_sweep_dict_census(double splitSurplusPercent) {
// Does walking the tree 3 times hurt?
set_tree_surplus(splitSurplusPercent);
set_tree_hints();
@@ -1169,9 +1209,9 @@
}
// Print summary statistics
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::report_statistics() const {
- FreeBlockDictionary<Chunk>::verify_par_locked();
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::report_statistics() const {
+ FreeBlockDictionary<Chunk_t>::verify_par_locked();
gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n"
"------------------------------------\n");
size_t total_size = total_chunk_size(debug_only(NULL));
@@ -1182,36 +1222,47 @@
if (free_blocks > 0) {
gclog_or_tty->print("Av. Block Size: %d\n", total_size/free_blocks);
}
- gclog_or_tty->print("Tree Height: %d\n", treeHeight());
+ gclog_or_tty->print("Tree Height: %d\n", tree_height());
}
// Print census information - counts, births, deaths, etc.
// for each list in the tree. Also print some summary
// information.
-template <class Chunk>
-class PrintTreeCensusClosure : public AscendTreeCensusClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class PrintTreeCensusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
int _print_line;
size_t _total_free;
- FreeList<Chunk> _total;
+ FreeList_t<Chunk_t> _total;
public:
PrintTreeCensusClosure() {
_print_line = 0;
_total_free = 0;
}
- FreeList<Chunk>* total() { return &_total; }
+ FreeList_t<Chunk_t>* total() { return &_total; }
size_t total_free() { return _total_free; }
- void do_list(FreeList<Chunk>* fl) {
+ void do_list(FreeList<Chunk_t>* fl) {
if (++_print_line >= 40) {
- FreeList<Chunk>::print_labels_on(gclog_or_tty, "size");
+ FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, "size");
_print_line = 0;
}
fl->print_on(gclog_or_tty);
_total_free += fl->count() * fl->size() ;
total()->set_count( total()->count() + fl->count() );
- total()->set_bfr_surp( total()->bfr_surp() + fl->bfr_surp() );
+ }
+
+#ifndef SERIALGC
+ void do_list(AdaptiveFreeList<Chunk_t>* fl) {
+ if (++_print_line >= 40) {
+ FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, "size");
+ _print_line = 0;
+ }
+ fl->print_on(gclog_or_tty);
+ _total_free += fl->count() * fl->size() ;
+ total()->set_count( total()->count() + fl->count() );
+ total()->set_bfr_surp( total()->bfr_surp() + fl->bfr_surp() );
total()->set_surplus( total()->split_deaths() + fl->surplus() );
- total()->set_desired( total()->desired() + fl->desired() );
+ total()->set_desired( total()->desired() + fl->desired() );
total()->set_prev_sweep( total()->prev_sweep() + fl->prev_sweep() );
total()->set_before_sweep(total()->before_sweep() + fl->before_sweep());
total()->set_coal_births( total()->coal_births() + fl->coal_births() );
@@ -1219,18 +1270,32 @@
total()->set_split_births(total()->split_births() + fl->split_births());
total()->set_split_deaths(total()->split_deaths() + fl->split_deaths());
}
+#endif // SERIALGC
};
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::print_dict_census(void) const {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::print_dict_census(void) const {
gclog_or_tty->print("\nBinaryTree\n");
- FreeList<Chunk>::print_labels_on(gclog_or_tty, "size");
- PrintTreeCensusClosure<Chunk> ptc;
+ FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, "size");
+ PrintTreeCensusClosure<Chunk_t, FreeList_t> ptc;
ptc.do_tree(root());
- FreeList<Chunk>* total = ptc.total();
- FreeList<Chunk>::print_labels_on(gclog_or_tty, " ");
+ FreeList_t<Chunk_t>* total = ptc.total();
+ FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, " ");
+}
+
+#ifndef SERIALGC
+template <>
+void BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::print_dict_census(void) const {
+
+ gclog_or_tty->print("\nBinaryTree\n");
+ AdaptiveFreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
+ PrintTreeCensusClosure<FreeChunk, AdaptiveFreeList> ptc;
+ ptc.do_tree(root());
+
+ AdaptiveFreeList<FreeChunk>* total = ptc.total();
+ AdaptiveFreeList<FreeChunk>::print_labels_on(gclog_or_tty, " ");
total->print_on(gclog_or_tty, "TOTAL\t");
gclog_or_tty->print(
"total_free(words): " SIZE_FORMAT_W(16)
@@ -1242,9 +1307,10 @@
(double)(total->desired() - total->count())
/(total->desired() != 0 ? (double)total->desired() : 1.0));
}
+#endif // SERIALGC
-template <class Chunk>
-class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk> {
+template <class Chunk_t, template <class> class FreeList_t>
+class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
outputStream* _st;
int _print_line;
@@ -1253,14 +1319,14 @@
_st = st;
_print_line = 0;
}
- void do_list(FreeList<Chunk>* fl) {
+ void do_list(FreeList_t<Chunk_t>* fl) {
if (++_print_line >= 40) {
- FreeList<Chunk>::print_labels_on(_st, "size");
+ FreeList_t<Chunk_t>::print_labels_on(_st, "size");
_print_line = 0;
}
fl->print_on(gclog_or_tty);
size_t sz = fl->size();
- for (Chunk* fc = fl->head(); fc != NULL;
+ for (Chunk_t* fc = fl->head(); fc != NULL;
fc = fc->next()) {
_st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s",
fc, (HeapWord*)fc + sz,
@@ -1269,11 +1335,11 @@
}
};
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::print_free_lists(outputStream* st) const {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::print_free_lists(outputStream* st) const {
- FreeList<Chunk>::print_labels_on(st, "size");
- PrintFreeListsClosure<Chunk> pflc(st);
+ FreeList_t<Chunk_t>::print_labels_on(st, "size");
+ PrintFreeListsClosure<Chunk_t, FreeList_t> pflc(st);
pflc.do_tree(root());
}
@@ -1281,18 +1347,18 @@
// . _root has no parent
// . parent and child point to each other
// . each node's key correctly related to that of its child(ren)
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::verify_tree() const {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_tree() const {
guarantee(root() == NULL || total_free_blocks() == 0 ||
total_size() != 0, "_total_size should't be 0?");
guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
verify_tree_helper(root());
}
-template <class Chunk>
-size_t BinaryTreeDictionary<Chunk>::verify_prev_free_ptrs(TreeList<Chunk>* tl) {
+template <class Chunk_t, template <class> class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_prev_free_ptrs(TreeList<Chunk_t, FreeList_t>* tl) {
size_t ct = 0;
- for (Chunk* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
+ for (Chunk_t* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
ct++;
assert(curFC->prev() == NULL || curFC->prev()->is_free(),
"Chunk should be free");
@@ -1303,8 +1369,8 @@
// Note: this helper is recursive rather than iterative, so use with
// caution on very deep trees; and watch out for stack overflow errors;
// In general, to be used only for debugging.
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::verify_tree_helper(TreeList<Chunk>* tl) const {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_tree_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
if (tl == NULL)
return;
guarantee(tl->size() != 0, "A list must has a size");
@@ -1332,15 +1398,25 @@
verify_tree_helper(tl->right());
}
-template <class Chunk>
-void BinaryTreeDictionary<Chunk>::verify() const {
+template <class Chunk_t, template <class> class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify() const {
verify_tree();
guarantee(total_size() == total_size_in_tree(root()), "Total Size inconsistency");
}
+template class TreeList<Metablock, FreeList>;
+template class BinaryTreeDictionary<Metablock, FreeList>;
+template class TreeChunk<Metablock, FreeList>;
+
+template class TreeList<Metachunk, FreeList>;
+template class BinaryTreeDictionary<Metachunk, FreeList>;
+template class TreeChunk<Metachunk, FreeList>;
+
+
#ifndef SERIALGC
// Explicitly instantiate these types for FreeChunk.
-template class BinaryTreeDictionary<FreeChunk>;
-template class TreeChunk<FreeChunk>;
-template class TreeList<FreeChunk>;
+template class TreeList<FreeChunk, AdaptiveFreeList>;
+template class BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>;
+template class TreeChunk<FreeChunk, AdaptiveFreeList>;
+
#endif // SERIALGC