binaryTreeDictionary.cpp 53.2 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25
#include "precompiled.hpp"
26
#include "utilities/macros.hpp"
27
#include "gc_implementation/shared/allocationStats.hpp"
28
#include "memory/binaryTreeDictionary.hpp"
29 30 31
#include "memory/freeList.hpp"
#include "memory/freeBlockDictionary.hpp"
#include "memory/metachunk.hpp"
32 33
#include "runtime/globals.hpp"
#include "utilities/ostream.hpp"
34
#include "utilities/macros.hpp"
35
#include "gc_implementation/shared/spaceDecorator.hpp"
36
#if INCLUDE_ALL_GCS
37 38
#include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp"
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
39
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
40
#endif // INCLUDE_ALL_GCS
D
duke 已提交
41 42 43 44 45 46

////////////////////////////////////////////////////////////////////////////////
// A binary tree based search structure for free blocks.
// This is currently used in the Concurrent Mark&Sweep implementation.
////////////////////////////////////////////////////////////////////////////////

47 48 49 50 51
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) {
D
duke 已提交
52
  // Do some assertion checking here.
53
  return (TreeChunk<Chunk_t, FreeList_t>*) fc;
D
duke 已提交
54 55
}

56 57 58
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();
D
duke 已提交
59 60 61 62 63 64 65
  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");
  }
  if (nextTC != NULL) {
    guarantee(as_TreeChunk(nextTC->prev()) == this, "broken chain");
    guarantee(nextTC->size() == size(), "wrong size");
66
    nextTC->verify_tree_chunk_list();
D
duke 已提交
67 68 69
  }
}

70
template <class Chunk_t, template <class> class FreeList_t>
71 72
TreeList<Chunk_t, FreeList_t>::TreeList() : _parent(NULL),
  _left(NULL), _right(NULL) {}
D
duke 已提交
73

74 75 76
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) {
D
duke 已提交
77
  // This first free chunk in the list will be the tree list.
78 79 80 81
  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();
D
duke 已提交
82 83 84 85 86
  tc->set_list(tl);
  tl->set_size(tc->size());
  tl->link_head(tc);
  tl->link_tail(tc);
  tl->set_count(1);
87
  assert(tl->parent() == NULL, "Should be clear");
D
duke 已提交
88 89
  return tl;
}
90

91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

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
112
  // (since it is used to maintain the chunk on the free list).
113
  tc->assert_is_mangled();
114 115 116
  tc->set_size(size);
  tc->link_prev(NULL);
  tc->link_next(NULL);
117
  TreeList<Chunk_t, FreeList_t>* tl = TreeList<Chunk_t, FreeList_t>::as_TreeList(tc);
D
duke 已提交
118 119 120 121
  return tl;
}


122
#if INCLUDE_ALL_GCS
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
// 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;
}
164
#endif // INCLUDE_ALL_GCS
165 166 167 168 169 170 171 172 173 174 175 176 177

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_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_t, FreeList_t>* retTL = this;
  Chunk_t* list = head();
D
duke 已提交
178 179 180 181
  assert(!list || list != list->next(), "Chunk on list twice");
  assert(tc != NULL, "Chunk being removed is NULL");
  assert(parent() == NULL || this == parent()->left() ||
    this == parent()->right(), "list is inconsistent");
182
  assert(tc->is_free(), "Header is not marked correctly");
D
duke 已提交
183 184 185
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");

186 187
  Chunk_t* prevFC = tc->prev();
  TreeChunk<Chunk_t, FreeList_t>* nextTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(tc->next());
D
duke 已提交
188 189 190 191
  assert(list != NULL, "should have at least the target chunk");

  // Is this the first item on the list?
  if (tc == list) {
192
    // The "getChunk..." functions for a TreeList<Chunk_t, FreeList_t> will not return the
D
duke 已提交
193 194 195 196 197 198 199 200
    // 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
    // list can be the start of a free range.  Free ranges are removed
    // from the free lists so that they are not available to be
    // 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
201 202
    // 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.
D
duke 已提交
203
    if (nextTC == NULL) {
204
      assert(prevFC == NULL, "Not last chunk in the list");
D
duke 已提交
205 206 207 208 209 210 211 212 213 214
      set_tail(NULL);
      set_head(NULL);
    } else {
      // copy embedded list.
      nextTC->set_embedded_list(tc->embedded_list());
      retTL = nextTC->embedded_list();
      // Fix the pointer to the list in each chunk in the list.
      // 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.
215 216
      for (TreeChunk<Chunk_t, FreeList_t>* curTC = nextTC; curTC != NULL;
          curTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(curTC->next())) {
D
duke 已提交
217 218
        curTC->set_list(retTL);
      }
219
      // Fix the parent to point to the new TreeList<Chunk_t, FreeList_t>.
D
duke 已提交
220 221
      if (retTL->parent() != NULL) {
        if (this == retTL->parent()->left()) {
222
          retTL->parent()->set_left(retTL);
D
duke 已提交
223 224
        } else {
          assert(this == retTL->parent()->right(), "Parent is incorrect");
225
          retTL->parent()->set_right(retTL);
D
duke 已提交
226 227 228 229 230 231
        }
      }
      // Fix the children's parent pointers to point to the
      // new list.
      assert(right() == retTL->right(), "Should have been copied");
      if (retTL->right() != NULL) {
232
        retTL->right()->set_parent(retTL);
D
duke 已提交
233 234 235
      }
      assert(left() == retTL->left(), "Should have been copied");
      if (retTL->left() != NULL) {
236
        retTL->left()->set_parent(retTL);
D
duke 已提交
237 238
      }
      retTL->link_head(nextTC);
239
      assert(nextTC->is_free(), "Should be a free chunk");
D
duke 已提交
240 241 242 243
    }
  } else {
    if (nextTC == NULL) {
      // Removing chunk at tail of list
244
      this->link_tail(prevFC);
D
duke 已提交
245 246
    }
    // Chunk is interior to the list
247
    prevFC->link_after(nextTC);
D
duke 已提交
248 249
  }

250
  // Below this point the embeded TreeList<Chunk_t, FreeList_t> being used for the
D
duke 已提交
251
  // tree node may have changed. Don't use "this"
252
  // TreeList<Chunk_t, FreeList_t>*.
D
duke 已提交
253 254 255 256
  // chunk should still be a free chunk (bit set in _prev)
  assert(!retTL->head() || retTL->size() == retTL->head()->size(),
    "Wrong sized chunk in list");
  debug_only(
257 258
    tc->link_prev(NULL);
    tc->link_next(NULL);
D
duke 已提交
259 260 261
    tc->set_list(NULL);
    bool prev_found = false;
    bool next_found = false;
262
    for (Chunk_t* curFC = retTL->head();
D
duke 已提交
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
         curFC != NULL; curFC = curFC->next()) {
      assert(curFC != tc, "Chunk is still in list");
      if (curFC == prevFC) {
        prev_found = true;
      }
      if (curFC == nextTC) {
        next_found = true;
      }
    }
    assert(prevFC == NULL || prev_found, "Chunk was lost from list");
    assert(nextTC == NULL || next_found, "Chunk was lost from list");
    assert(retTL->parent() == NULL ||
           retTL == retTL->parent()->left() ||
           retTL == retTL->parent()->right(),
           "list is inconsistent");
  )
  retTL->decrement_count();

281
  assert(tc->is_free(), "Should still be a free chunk");
D
duke 已提交
282 283 284 285 286 287
  assert(retTL->head() == NULL || retTL->head()->prev() == NULL,
    "list invariant");
  assert(retTL->tail() == NULL || retTL->tail()->next() == NULL,
    "list invariant");
  return retTL;
}
288

289 290
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) {
D
duke 已提交
291 292 293 294
  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");
  // which means that the list can never be empty.
C
coleenp 已提交
295
  assert(!this->verify_chunk_in_free_list(chunk), "Double entry");
D
duke 已提交
296 297 298
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");

299
  Chunk_t* fc = tail();
300
  fc->link_after(chunk);
301
  this->link_tail(chunk);
D
duke 已提交
302 303

  assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
304
  FreeList_t<Chunk_t>::increment_count();
C
coleenp 已提交
305
  debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
D
duke 已提交
306 307 308 309 310 311
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
}

// 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
312 313 314 315
// 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) {
D
duke 已提交
316 317 318
  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");
C
coleenp 已提交
319
  assert(!this->verify_chunk_in_free_list(chunk), "Double entry");
D
duke 已提交
320 321 322
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");

323
  Chunk_t* fc = head()->next();
D
duke 已提交
324
  if (fc != NULL) {
325
    chunk->link_after(fc);
D
duke 已提交
326 327
  } else {
    assert(tail() == NULL, "List is inconsistent");
328
    this->link_tail(chunk);
D
duke 已提交
329
  }
330
  head()->link_after(chunk);
D
duke 已提交
331
  assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
332
  FreeList_t<Chunk_t>::increment_count();
C
coleenp 已提交
333
  debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
D
duke 已提交
334 335 336 337
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
}

338 339 340 341 342 343 344 345 346 347 348 349 350
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_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),
D
duke 已提交
351
    "Wrong type of chunk?");
352
  return TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(head());
D
duke 已提交
353 354
}

355 356
template <class Chunk_t, template <class> class FreeList_t>
TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::first_available() {
357
  assert(head() != NULL, "The head of the list cannot be NULL");
358 359
  Chunk_t* fc = head()->next();
  TreeChunk<Chunk_t, FreeList_t>* retTC;
D
duke 已提交
360 361 362
  if (fc == NULL) {
    retTC = head_as_TreeChunk();
  } else {
363
    retTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
D
duke 已提交
364 365 366 367 368
  }
  assert(retTC->list() == this, "Wrong type of chunk.");
  return retTC;
}

369 370 371
// Returns the block with the largest heap address amongst
// those in the list for this size; potentially slow and expensive,
// use with caution!
372 373
template <class Chunk_t, template <class> class FreeList_t>
TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::largest_address() {
374
  assert(head() != NULL, "The head of the list cannot be NULL");
375 376
  Chunk_t* fc = head()->next();
  TreeChunk<Chunk_t, FreeList_t>* retTC;
377 378 379 380 381
  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.
382
    Chunk_t* last = fc;
383 384 385 386 387 388
    while (fc->next() != NULL) {
      if ((HeapWord*)last < (HeapWord*)fc) {
        last = fc;
      }
      fc = fc->next();
    }
389
    retTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(last);
390 391 392 393 394
  }
  assert(retTC->list() == this, "Wrong type of chunk.");
  return retTC;
}

395 396 397
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");
D
duke 已提交
398 399 400 401 402 403

  reset(mr);
  assert(root()->left() == NULL, "reset check failed");
  assert(root()->right() == NULL, "reset check failed");
  assert(root()->head()->next() == NULL, "reset check failed");
  assert(root()->head()->prev() == NULL, "reset check failed");
404 405
  assert(total_size() == root()->size(), "reset check failed");
  assert(total_free_blocks() == 1, "reset check failed");
D
duke 已提交
406 407
}

408 409
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::inc_total_size(size_t inc) {
410
  _total_size = _total_size + inc;
D
duke 已提交
411 412
}

413 414
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::dec_total_size(size_t dec) {
415
  _total_size = _total_size - dec;
D
duke 已提交
416 417
}

418 419 420 421
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()));
422 423
  set_total_size(mr.word_size());
  set_total_free_blocks(1);
D
duke 已提交
424 425
}

426 427
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset(HeapWord* addr, size_t byte_size) {
D
duke 已提交
428 429 430 431
  MemRegion mr(addr, heap_word_size(byte_size));
  reset(mr);
}

432 433
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset() {
D
duke 已提交
434
  set_root(NULL);
435 436
  set_total_size(0);
  set_total_free_blocks(0);
D
duke 已提交
437 438 439
}

// Get a free block of size at least size from tree, or NULL.
440 441 442 443 444
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)
D
duke 已提交
445
{
446 447 448 449
  TreeList<Chunk_t, FreeList_t> *curTL, *prevTL;
  TreeChunk<Chunk_t, FreeList_t>* retTC = NULL;

  assert((size >= min_size()), "minimum chunk size");
D
duke 已提交
450
  if (FLSVerifyDictionary) {
451
    verify_tree();
D
duke 已提交
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
  }
  // starting at the root, work downwards trying to find match.
  // Remember the last node of size too great or too small.
  for (prevTL = curTL = root(); curTL != NULL;) {
    if (curTL->size() == size) {        // exact match
      break;
    }
    prevTL = curTL;
    if (curTL->size() < size) {        // proceed to right sub-tree
      curTL = curTL->right();
    } else {                           // proceed to left sub-tree
      assert(curTL->size() > size, "size inconsistency");
      curTL = curTL->left();
    }
  }
  if (curTL == NULL) { // couldn't find exact match
468

469
    if (dither == FreeBlockDictionary<Chunk_t>::exactly) return NULL;
470

D
duke 已提交
471 472 473 474 475 476 477 478 479 480
    // try and find the next larger size by walking back up the search path
    for (curTL = prevTL; curTL != NULL;) {
      if (curTL->size() >= size) break;
      else curTL = curTL->parent();
    }
    assert(curTL == NULL || curTL->count() > 0,
      "An empty list should not be in the tree");
  }
  if (curTL != NULL) {
    assert(curTL->size() >= size, "size inconsistency");
481 482 483

    curTL = curTL->get_better_list(this);

D
duke 已提交
484 485 486 487 488
    retTC = curTL->first_available();
    assert((retTC != NULL) && (curTL->count() > 0),
      "A list in the binary tree should not be NULL");
    assert(retTC->size() >= size,
      "A chunk of the wrong size was found");
489 490
    remove_chunk_from_tree(retTC);
    assert(retTC->is_free(), "Header is not marked correctly");
D
duke 已提交
491 492 493 494 495 496 497 498
  }

  if (FLSVerifyDictionary) {
    verify();
  }
  return retTC;
}

499 500 501
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;
D
duke 已提交
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
  for (curTL = root(); curTL != NULL;) {
    if (curTL->size() == size) {        // exact match
      break;
    }

    if (curTL->size() < size) {        // proceed to right sub-tree
      curTL = curTL->right();
    } else {                           // proceed to left sub-tree
      assert(curTL->size() > size, "size inconsistency");
      curTL = curTL->left();
    }
  }
  return curTL;
}


518 519
template <class Chunk_t, template <class> class FreeList_t>
bool BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_chunk_in_free_list(Chunk_t* tc) const {
D
duke 已提交
520
  size_t size = tc->size();
521
  TreeList<Chunk_t, FreeList_t>* tl = find_list(size);
D
duke 已提交
522 523 524
  if (tl == NULL) {
    return false;
  } else {
525
    return tl->verify_chunk_in_free_list(tc);
D
duke 已提交
526 527 528
  }
}

529 530 531
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();
D
duke 已提交
532 533
  if (curTL != NULL) {
    while(curTL->right() != NULL) curTL = curTL->right();
534
    return curTL->largest_address();
D
duke 已提交
535 536 537 538 539 540 541 542 543
  } else {
    return NULL;
  }
}

// Remove the current chunk from the tree.  If it is not the last
// 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.
544 545 546
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) {
D
duke 已提交
547
  assert(tc != NULL, "Should not call with a NULL chunk");
548
  assert(tc->is_free(), "Header is not marked correctly");
D
duke 已提交
549

550 551 552
  TreeList<Chunk_t, FreeList_t> *newTL, *parentTL;
  TreeChunk<Chunk_t, FreeList_t>* retTC;
  TreeList<Chunk_t, FreeList_t>* tl = tc->list();
D
duke 已提交
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
  debug_only(
    bool removing_only_chunk = false;
    if (tl == _root) {
      if ((_root->left() == NULL) && (_root->right() == NULL)) {
        if (_root->count() == 1) {
          assert(_root->head() == tc, "Should only be this one chunk");
          removing_only_chunk = true;
        }
      }
    }
  )
  assert(tl != NULL, "List should be set");
  assert(tl->parent() == NULL || tl == tl->parent()->left() ||
         tl == tl->parent()->right(), "list is inconsistent");

568
  bool complicated_splice = false;
D
duke 已提交
569 570 571

  retTC = tc;
  // Removing this chunk can have the side effect of changing the node
572 573
  // (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);
574
  assert(tc->is_free(), "Chunk should still be free");
D
duke 已提交
575 576 577 578 579 580 581 582
  assert(replacementTL->parent() == NULL ||
         replacementTL == replacementTL->parent()->left() ||
         replacementTL == replacementTL->parent()->right(),
         "list is inconsistent");
  if (tl == root()) {
    assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
    set_root(replacementTL);
  }
583
#ifdef ASSERT
D
duke 已提交
584 585 586
    if (tl != replacementTL) {
      assert(replacementTL->head() != NULL,
        "If the tree list was replaced, it should not be a NULL list");
587 588 589
      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();
D
duke 已提交
590 591 592 593
      assert(rhl == replacementTL, "Broken head");
      assert(rtl == replacementTL, "Broken tail");
      assert(replacementTL->size() == tc->size(),  "Broken size");
    }
594
#endif
D
duke 已提交
595 596 597 598 599 600 601 602 603 604

  // Does the tree need to be repaired?
  if (replacementTL->count() == 0) {
    assert(replacementTL->head() == NULL &&
           replacementTL->tail() == NULL, "list count is incorrect");
    // Find the replacement node for the (soon to be empty) node being removed.
    // if we have a single (or no) child, splice child in our stead
    if (replacementTL->left() == NULL) {
      // left is NULL so pick right.  right may also be NULL.
      newTL = replacementTL->right();
605
      debug_only(replacementTL->clear_right();)
D
duke 已提交
606 607 608
    } else if (replacementTL->right() == NULL) {
      // right is NULL
      newTL = replacementTL->left();
609
      debug_only(replacementTL->clear_left();)
D
duke 已提交
610 611
    } else {  // we have both children, so, by patriarchal convention,
              // my replacement is least node in right sub-tree
612 613
      complicated_splice = true;
      newTL = remove_tree_minimum(replacementTL->right());
D
duke 已提交
614 615 616 617 618 619 620
      assert(newTL != NULL && newTL->left() == NULL &&
             newTL->right() == NULL, "sub-tree minimum exists");
    }
    // newTL is the replacement for the (soon to be empty) node.
    // newTL may be NULL.
    // should verify; we just cleanly excised our replacement
    if (FLSVerifyDictionary) {
621
      verify_tree();
D
duke 已提交
622 623 624 625 626 627 628
    }
    // first make newTL my parent's child
    if ((parentTL = replacementTL->parent()) == NULL) {
      // newTL should be root
      assert(tl == root(), "Incorrectly replacing root");
      set_root(newTL);
      if (newTL != NULL) {
629
        newTL->clear_parent();
D
duke 已提交
630 631 632
      }
    } else if (parentTL->right() == replacementTL) {
      // replacementTL is a right child
633
      parentTL->set_right(newTL);
D
duke 已提交
634 635
    } else {                                // replacementTL is a left child
      assert(parentTL->left() == replacementTL, "should be left child");
636
      parentTL->set_left(newTL);
D
duke 已提交
637
    }
638 639
    debug_only(replacementTL->clear_parent();)
    if (complicated_splice) {  // we need newTL to get replacementTL's
D
duke 已提交
640 641 642 643 644 645
                              // two children
      assert(newTL != NULL &&
             newTL->left() == NULL && newTL->right() == NULL,
            "newTL should not have encumbrances from the past");
      // we'd like to assert as below:
      // assert(replacementTL->left() != NULL && replacementTL->right() != NULL,
646
      //       "else !complicated_splice");
D
duke 已提交
647 648 649 650 651 652
      // ... however, the above assertion is too strong because we aren't
      // guaranteed that replacementTL->right() is still NULL.
      // Recall that we removed
      // the right sub-tree minimum from replacementTL.
      // That may well have been its right
      // child! So we'll just assert half of the above:
653 654 655
      assert(replacementTL->left() != NULL, "else !complicated_splice");
      newTL->set_left(replacementTL->left());
      newTL->set_right(replacementTL->right());
D
duke 已提交
656
      debug_only(
657
        replacementTL->clear_right();
658
        replacementTL->clear_left();
D
duke 已提交
659 660 661 662 663 664 665 666
      )
    }
    assert(replacementTL->right() == NULL &&
           replacementTL->left() == NULL &&
           replacementTL->parent() == NULL,
        "delete without encumbrances");
  }

667 668 669 670
  assert(total_size() >= retTC->size(), "Incorrect total size");
  dec_total_size(retTC->size());     // size book-keeping
  assert(total_free_blocks() > 0, "Incorrect total count");
  set_total_free_blocks(total_free_blocks() - 1);
D
duke 已提交
671 672 673 674 675

  assert(retTC != NULL, "null chunk?");
  assert(retTC->prev() == NULL && retTC->next() == NULL,
         "should return without encumbrances");
  if (FLSVerifyDictionary) {
676
    verify_tree();
D
duke 已提交
677 678
  }
  assert(!removing_only_chunk || _root == NULL, "root should be NULL");
679
  return TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(retTC);
D
duke 已提交
680 681 682 683 684
}

// 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.
685 686
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) {
D
duke 已提交
687 688
  assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
  // locate the subtree minimum by walking down left branches
689
  TreeList<Chunk_t, FreeList_t>* curTL = tl;
D
duke 已提交
690 691 692
  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?
693
    TreeList<Chunk_t, FreeList_t>* parentTL = curTL->parent();
D
duke 已提交
694
    if (parentTL->left() == curTL) { // curTL is a left child
695
      parentTL->set_left(curTL->right());
D
duke 已提交
696 697 698 699
    } else {
      // If the list tl has no left child, then curTL may be
      // the right child of parentTL.
      assert(parentTL->right() == curTL, "should be a right child");
700
      parentTL->set_right(curTL->right());
D
duke 已提交
701 702 703 704 705 706 707 708 709
    }
  } else {
    // The only use of this method would not pass the root of the
    // tree (as indicated by the assertion above that the tree list
    // has a parent) but the specification does not explicitly exclude the
    // passing of the root so accomodate it.
    set_root(NULL);
  }
  debug_only(
710 711
    curTL->clear_parent();  // Test if this needs to be cleared
    curTL->clear_right();    // recall, above, left child is already null
D
duke 已提交
712 713 714
  )
  // we just excised a (non-root) node, we should still verify all tree invariants
  if (FLSVerifyDictionary) {
715
    verify_tree();
D
duke 已提交
716 717 718 719
  }
  return curTL;
}

720 721 722
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;
D
duke 已提交
723 724
  size_t size = fc->size();

725 726 727
  assert((size >= min_size()),
    err_msg(SIZE_FORMAT " is too small to be a TreeChunk<Chunk_t, FreeList_t> " SIZE_FORMAT,
      size, min_size()));
D
duke 已提交
728
  if (FLSVerifyDictionary) {
729
    verify_tree();
D
duke 已提交
730 731
  }

732 733
  fc->clear_next();
  fc->link_prev(NULL);
D
duke 已提交
734 735 736 737 738 739 740 741 742 743 744 745 746

  // work down from the _root, looking for insertion point
  for (prevTL = curTL = root(); curTL != NULL;) {
    if (curTL->size() == size)  // exact match
      break;
    prevTL = curTL;
    if (curTL->size() > size) { // follow left branch
      curTL = curTL->left();
    } else {                    // follow right branch
      assert(curTL->size() < size, "size inconsistency");
      curTL = curTL->right();
    }
  }
747
  TreeChunk<Chunk_t, FreeList_t>* tc = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
748
  // This chunk is being returned to the binary tree.  Its embedded
749
  // TreeList<Chunk_t, FreeList_t> should be unused at this point.
D
duke 已提交
750 751 752
  tc->initialize();
  if (curTL != NULL) {          // exact match
    tc->set_list(curTL);
753
    curTL->return_chunk_at_tail(tc);
D
duke 已提交
754
  } else {                     // need a new node in tree
755 756
    tc->clear_next();
    tc->link_prev(NULL);
757 758
    TreeList<Chunk_t, FreeList_t>* newTL = TreeList<Chunk_t, FreeList_t>::as_TreeList(tc);
    assert(((TreeChunk<Chunk_t, FreeList_t>*)tc)->list() == newTL,
D
duke 已提交
759 760 761 762 763 764 765
      "List was not initialized correctly");
    if (prevTL == NULL) {      // we are the only tree node
      assert(root() == NULL, "control point invariant");
      set_root(newTL);
    } else {                   // insert under prevTL ...
      if (prevTL->size() < size) {   // am right child
        assert(prevTL->right() == NULL, "control point invariant");
766
        prevTL->set_right(newTL);
D
duke 已提交
767 768
      } else {                       // am left child
        assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
769
        prevTL->set_left(newTL);
D
duke 已提交
770 771 772 773 774
      }
    }
  }
  assert(tc->list() != NULL, "Tree list should be set");

775 776
  inc_total_size(size);
  // Method 'total_size_in_tree' walks through the every block in the
D
duke 已提交
777 778
  // tree, so it can cause significant performance loss if there are
  // many blocks in the tree
779 780
  assert(!FLSVerifyDictionary || total_size_in_tree(root()) == total_size(), "_total_size inconsistency");
  set_total_free_blocks(total_free_blocks() + 1);
D
duke 已提交
781
  if (FLSVerifyDictionary) {
782
    verify_tree();
D
duke 已提交
783 784 785
  }
}

786 787 788 789
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();
D
duke 已提交
790 791 792 793 794
  if (tc == NULL) return 0;
  for (; tc->right() != NULL; tc = tc->right());
  return tc->size();
}

795 796
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 {
D
duke 已提交
797 798 799 800
  size_t res;
  res = tl->count();
#ifdef ASSERT
  size_t cnt;
801
  Chunk_t* tc = tl->head();
D
duke 已提交
802 803 804 805 806 807
  for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
  assert(res == cnt, "The count is not being maintained correctly");
#endif
  return res;
}

808 809
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 {
D
duke 已提交
810 811
  if (tl == NULL)
    return 0;
812 813 814
  return (tl->size() * total_list_length(tl)) +
         total_size_in_tree(tl->left())    +
         total_size_in_tree(tl->right());
D
duke 已提交
815 816
}

817 818
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 {
D
duke 已提交
819 820 821 822
  if (tl == NULL) {
    return 0.0;
  }
  double size = (double)(tl->size());
823
  double curr = size * size * total_list_length(tl);
D
duke 已提交
824 825 826 827 828
  curr += sum_of_squared_block_sizes(tl->left());
  curr += sum_of_squared_block_sizes(tl->right());
  return curr;
}

829 830
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 {
D
duke 已提交
831 832
  if (tl == NULL)
    return 0;
833 834 835
  return total_list_length(tl) +
         total_free_blocks_in_tree(tl->left()) +
         total_free_blocks_in_tree(tl->right());
D
duke 已提交
836 837
}

838 839
template <class Chunk_t, template <class> class FreeList_t>
size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::num_free_blocks() const {
840 841 842
  assert(total_free_blocks_in_tree(root()) == total_free_blocks(),
         "_total_free_blocks inconsistency");
  return total_free_blocks();
D
duke 已提交
843 844
}

845 846
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 {
D
duke 已提交
847 848
  if (tl == NULL)
    return 0;
849 850
  return 1 + MAX2(tree_height_helper(tl->left()),
                  tree_height_helper(tl->right()));
D
duke 已提交
851 852
}

853 854
template <class Chunk_t, template <class> class FreeList_t>
size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::tree_height() const {
855
  return tree_height_helper(root());
D
duke 已提交
856 857
}

858 859
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 {
D
duke 已提交
860 861 862
  if (tl == NULL) {
    return 0;
  }
863 864
  return 1 + total_nodes_helper(tl->left()) +
    total_nodes_helper(tl->right());
D
duke 已提交
865 866
}

867 868
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 {
869
  return total_nodes_helper(root());
D
duke 已提交
870 871
}

872 873 874
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){}

875
#if INCLUDE_ALL_GCS
876
template <>
877
void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){
878
  TreeList<FreeChunk, AdaptiveFreeList>* nd = find_list(size);
D
duke 已提交
879 880 881
  if (nd) {
    if (split) {
      if (birth) {
882
        nd->increment_split_births();
D
duke 已提交
883 884
        nd->increment_surplus();
      }  else {
885
        nd->increment_split_deaths();
D
duke 已提交
886 887 888 889
        nd->decrement_surplus();
      }
    } else {
      if (birth) {
890
        nd->increment_coal_births();
D
duke 已提交
891 892
        nd->increment_surplus();
      } else {
893
        nd->increment_coal_deaths();
D
duke 已提交
894 895 896 897 898 899 900 901 902 903
        nd->decrement_surplus();
      }
    }
  }
  // A list for this size may not be found (nd == 0) if
  //   This is a death where the appropriate list is now
  //     empty and has been removed from the list.
  //   This is a birth associated with a LinAB.  The chunk
  //     for the LinAB is not in the dictionary.
}
904
#endif // INCLUDE_ALL_GCS
905 906 907 908 909 910 911

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;
}
D
duke 已提交
912

913
#if INCLUDE_ALL_GCS
914
template <>
915
bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) {
916 917
  if (FLSAlwaysCoalesceLarge) return true;

918
  TreeList<FreeChunk, AdaptiveFreeList>* list_of_size = find_list(size);
D
duke 已提交
919
  // None of requested size implies overpopulated.
920 921
  return list_of_size == NULL || list_of_size->coal_desired() <= 0 ||
         list_of_size->count() > list_of_size->coal_desired();
D
duke 已提交
922
}
923
#endif // INCLUDE_ALL_GCS
D
duke 已提交
924 925 926 927 928 929 930

// Closures for walking the binary tree.
//   do_list() walks the free list in a node applying the closure
//     to each free chunk in the list
//   do_tree() walks the nodes in the binary tree applying do_list()
//     to each list at each node.

931
template <class Chunk_t, template <class> class FreeList_t>
D
duke 已提交
932 933
class TreeCensusClosure : public StackObj {
 protected:
934
  virtual void do_list(FreeList_t<Chunk_t>* fl) = 0;
D
duke 已提交
935
 public:
936
  virtual void do_tree(TreeList<Chunk_t, FreeList_t>* tl) = 0;
D
duke 已提交
937 938
};

939 940
template <class Chunk_t, template <class> class FreeList_t>
class AscendTreeCensusClosure : public TreeCensusClosure<Chunk_t, FreeList_t> {
D
duke 已提交
941
 public:
942
  void do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
D
duke 已提交
943 944
    if (tl != NULL) {
      do_tree(tl->left());
945
      this->do_list(tl);
D
duke 已提交
946 947 948 949 950
      do_tree(tl->right());
    }
  }
};

951 952
template <class Chunk_t, template <class> class FreeList_t>
class DescendTreeCensusClosure : public TreeCensusClosure<Chunk_t, FreeList_t> {
D
duke 已提交
953
 public:
954
  void do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
D
duke 已提交
955 956
    if (tl != NULL) {
      do_tree(tl->right());
957
      this->do_list(tl);
D
duke 已提交
958 959 960 961 962 963 964
      do_tree(tl->left());
    }
  }
};

// For each list in the tree, calculate the desired, desired
// coalesce, count before sweep, and surplus before sweep.
965 966
template <class Chunk_t, template <class> class FreeList_t>
class BeginSweepClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
D
duke 已提交
967 968 969
  double _percentage;
  float _inter_sweep_current;
  float _inter_sweep_estimate;
970
  float _intra_sweep_estimate;
D
duke 已提交
971 972 973

 public:
  BeginSweepClosure(double p, float inter_sweep_current,
974 975
                              float inter_sweep_estimate,
                              float intra_sweep_estimate) :
D
duke 已提交
976 977
   _percentage(p),
   _inter_sweep_current(inter_sweep_current),
978 979
   _inter_sweep_estimate(inter_sweep_estimate),
   _intra_sweep_estimate(intra_sweep_estimate) { }
D
duke 已提交
980

981 982
  void do_list(FreeList<Chunk_t>* fl) {}

983
#if INCLUDE_ALL_GCS
984
  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
D
duke 已提交
985
    double coalSurplusPercent = _percentage;
986
    fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
987 988 989
    fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent));
    fl->set_before_sweep(fl->count());
    fl->set_bfr_surp(fl->surplus());
D
duke 已提交
990
  }
991
#endif // INCLUDE_ALL_GCS
D
duke 已提交
992 993 994 995 996 997
};

// Used to search the tree until a condition is met.
// Similar to TreeCensusClosure but searches the
// tree and returns promptly when found.

998
template <class Chunk_t, template <class> class FreeList_t>
D
duke 已提交
999 1000
class TreeSearchClosure : public StackObj {
 protected:
1001
  virtual bool do_list(FreeList_t<Chunk_t>* fl) = 0;
D
duke 已提交
1002
 public:
1003
  virtual bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) = 0;
D
duke 已提交
1004 1005 1006
};

#if 0 //  Don't need this yet but here for symmetry.
1007 1008
template <class Chunk_t, template <class> class FreeList_t>
class AscendTreeSearchClosure : public TreeSearchClosure<Chunk_t> {
D
duke 已提交
1009
 public:
1010
  bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
D
duke 已提交
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
    if (tl != NULL) {
      if (do_tree(tl->left())) return true;
      if (do_list(tl)) return true;
      if (do_tree(tl->right())) return true;
    }
    return false;
  }
};
#endif

1021 1022
template <class Chunk_t, template <class> class FreeList_t>
class DescendTreeSearchClosure : public TreeSearchClosure<Chunk_t, FreeList_t> {
D
duke 已提交
1023
 public:
1024
  bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
D
duke 已提交
1025 1026
    if (tl != NULL) {
      if (do_tree(tl->right())) return true;
1027
      if (this->do_list(tl)) return true;
D
duke 已提交
1028 1029 1030 1031 1032 1033 1034 1035
      if (do_tree(tl->left())) return true;
    }
    return false;
  }
};

// Searches the tree for a chunk that ends at the
// specified address.
1036 1037
template <class Chunk_t, template <class> class FreeList_t>
class EndTreeSearchClosure : public DescendTreeSearchClosure<Chunk_t, FreeList_t> {
D
duke 已提交
1038
  HeapWord* _target;
1039
  Chunk_t* _found;
D
duke 已提交
1040 1041 1042

 public:
  EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
1043 1044
  bool do_list(FreeList_t<Chunk_t>* fl) {
    Chunk_t* item = fl->head();
D
duke 已提交
1045
    while (item != NULL) {
1046
      if (item->end() == (uintptr_t*) _target) {
D
duke 已提交
1047 1048 1049 1050 1051 1052 1053
        _found = item;
        return true;
      }
      item = item->next();
    }
    return false;
  }
1054
  Chunk_t* found() { return _found; }
D
duke 已提交
1055 1056
};

1057 1058 1059
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);
D
duke 已提交
1060 1061 1062 1063 1064 1065
  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();
}

1066 1067
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::begin_sweep_dict_census(double coalSurplusPercent,
1068
  float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
1069
  BeginSweepClosure<Chunk_t, FreeList_t> bsc(coalSurplusPercent, inter_sweep_current,
1070 1071
                                            inter_sweep_estimate,
                                            intra_sweep_estimate);
D
duke 已提交
1072 1073 1074 1075 1076
  bsc.do_tree(root());
}

// Closures and methods for calculating total bytes returned to the
// free lists in the tree.
1077
#ifndef PRODUCT
1078 1079
template <class Chunk_t, template <class> class FreeList_t>
class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
D
duke 已提交
1080
   public:
1081
  void do_list(FreeList_t<Chunk_t>* fl) {
1082
    fl->set_returned_bytes(0);
D
duke 已提交
1083
  }
1084
};
D
duke 已提交
1085

1086 1087 1088
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;
1089 1090
  idrb.do_tree(root());
}
D
duke 已提交
1091

1092 1093
template <class Chunk_t, template <class> class FreeList_t>
class ReturnedBytesClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
1094
  size_t _dict_returned_bytes;
1095
 public:
1096
  ReturnedBytesClosure() { _dict_returned_bytes = 0; }
1097
  void do_list(FreeList_t<Chunk_t>* fl) {
1098
    _dict_returned_bytes += fl->returned_bytes();
D
duke 已提交
1099
  }
1100
  size_t dict_returned_bytes() { return _dict_returned_bytes; }
1101
};
D
duke 已提交
1102

1103 1104 1105
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;
1106 1107
  rbc.do_tree(root());

1108
  return rbc.dict_returned_bytes();
1109
}
D
duke 已提交
1110

1111
// Count the number of entries in the tree.
1112 1113
template <class Chunk_t, template <class> class FreeList_t>
class treeCountClosure : public DescendTreeCensusClosure<Chunk_t, FreeList_t> {
1114 1115 1116
 public:
  uint count;
  treeCountClosure(uint c) { count = c; }
1117
  void do_list(FreeList_t<Chunk_t>* fl) {
1118
    count++;
D
duke 已提交
1119
  }
1120 1121
};

1122 1123 1124
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);
1125 1126 1127 1128
  ctc.do_tree(root());
  return ctc.count;
}
#endif // PRODUCT
D
duke 已提交
1129 1130

// Calculate surpluses for the lists in the tree.
1131 1132
template <class Chunk_t, template <class> class FreeList_t>
class setTreeSurplusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
D
duke 已提交
1133 1134 1135
  double percentage;
 public:
  setTreeSurplusClosure(double v) { percentage = v; }
1136 1137
  void do_list(FreeList<Chunk_t>* fl) {}

1138
#if INCLUDE_ALL_GCS
1139
  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
D
duke 已提交
1140 1141 1142 1143
    double splitSurplusPercent = percentage;
    fl->set_surplus(fl->count() -
                   (ssize_t)((double)fl->desired() * splitSurplusPercent));
  }
1144
#endif // INCLUDE_ALL_GCS
D
duke 已提交
1145 1146
};

1147 1148 1149
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);
D
duke 已提交
1150 1151 1152 1153
  sts.do_tree(root());
}

// Set hints for the lists in the tree.
1154 1155
template <class Chunk_t, template <class> class FreeList_t>
class setTreeHintsClosure : public DescendTreeCensusClosure<Chunk_t, FreeList_t> {
D
duke 已提交
1156 1157 1158
  size_t hint;
 public:
  setTreeHintsClosure(size_t v) { hint = v; }
1159 1160
  void do_list(FreeList<Chunk_t>* fl) {}

1161
#if INCLUDE_ALL_GCS
1162
  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
D
duke 已提交
1163 1164 1165 1166 1167 1168 1169
    fl->set_hint(hint);
    assert(fl->hint() == 0 || fl->hint() > fl->size(),
      "Current hint is inconsistent");
    if (fl->surplus() > 0) {
      hint = fl->size();
    }
  }
1170
#endif // INCLUDE_ALL_GCS
D
duke 已提交
1171 1172
};

1173 1174 1175
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);
D
duke 已提交
1176 1177 1178 1179
  sth.do_tree(root());
}

// Save count before previous sweep and splits and coalesces.
1180 1181 1182 1183
template <class Chunk_t, template <class> class FreeList_t>
class clearTreeCensusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
  void do_list(FreeList<Chunk_t>* fl) {}

1184
#if INCLUDE_ALL_GCS
1185
  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
1186 1187 1188 1189 1190
    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);
D
duke 已提交
1191
  }
1192
#endif // INCLUDE_ALL_GCS
D
duke 已提交
1193 1194
};

1195 1196 1197
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;
D
duke 已提交
1198 1199 1200 1201
  ctc.do_tree(root());
}

// Do reporting and post sweep clean up.
1202 1203
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::end_sweep_dict_census(double splitSurplusPercent) {
D
duke 已提交
1204
  // Does walking the tree 3 times hurt?
1205 1206
  set_tree_surplus(splitSurplusPercent);
  set_tree_hints();
D
duke 已提交
1207
  if (PrintGC && Verbose) {
1208
    report_statistics();
D
duke 已提交
1209
  }
1210
  clear_tree_census();
D
duke 已提交
1211 1212 1213
}

// Print summary statistics
1214 1215 1216
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::report_statistics() const {
  FreeBlockDictionary<Chunk_t>::verify_par_locked();
D
duke 已提交
1217 1218
  gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n"
         "------------------------------------\n");
1219 1220 1221 1222 1223 1224 1225
  size_t total_size = total_chunk_size(debug_only(NULL));
  size_t    free_blocks = num_free_blocks();
  gclog_or_tty->print("Total Free Space: %d\n", total_size);
  gclog_or_tty->print("Max   Chunk Size: %d\n", max_chunk_size());
  gclog_or_tty->print("Number of Blocks: %d\n", free_blocks);
  if (free_blocks > 0) {
    gclog_or_tty->print("Av.  Block  Size: %d\n", total_size/free_blocks);
D
duke 已提交
1226
  }
1227
  gclog_or_tty->print("Tree      Height: %d\n", tree_height());
D
duke 已提交
1228 1229 1230 1231 1232
}

// Print census information - counts, births, deaths, etc.
// for each list in the tree.  Also print some summary
// information.
1233 1234
template <class Chunk_t, template <class> class FreeList_t>
class PrintTreeCensusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
1235
  int _print_line;
1236
  size_t _total_free;
1237
  FreeList_t<Chunk_t> _total;
D
duke 已提交
1238 1239

 public:
1240
  PrintTreeCensusClosure() {
1241
    _print_line = 0;
1242
    _total_free = 0;
D
duke 已提交
1243
  }
1244
  FreeList_t<Chunk_t>* total() { return &_total; }
1245
  size_t total_free() { return _total_free; }
1246
  void do_list(FreeList<Chunk_t>* fl) {
1247
    if (++_print_line >= 40) {
1248
      FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, "size");
1249 1250 1251
      _print_line = 0;
    }
    fl->print_on(gclog_or_tty);
1252
    _total_free +=            fl->count()            * fl->size()        ;
1253
    total()->set_count(      total()->count()       + fl->count()      );
1254 1255
  }

1256
#if INCLUDE_ALL_GCS
1257 1258 1259 1260 1261 1262 1263 1264 1265
  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()    );
1266
    total()->set_surplus(    total()->split_deaths() + fl->surplus()    );
1267
    total()->set_desired(    total()->desired()      + fl->desired()    );
1268 1269 1270 1271 1272 1273
    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() );
    total()->set_coal_deaths( total()->coal_deaths()  + fl->coal_deaths() );
    total()->set_split_births(total()->split_births() + fl->split_births());
    total()->set_split_deaths(total()->split_deaths() + fl->split_deaths());
D
duke 已提交
1274
  }
1275
#endif // INCLUDE_ALL_GCS
D
duke 已提交
1276 1277
};

1278 1279
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::print_dict_census(void) const {
D
duke 已提交
1280 1281

  gclog_or_tty->print("\nBinaryTree\n");
1282 1283
  FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, "size");
  PrintTreeCensusClosure<Chunk_t, FreeList_t> ptc;
D
duke 已提交
1284 1285
  ptc.do_tree(root());

1286 1287 1288 1289
  FreeList_t<Chunk_t>* total = ptc.total();
  FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, " ");
}

1290
#if INCLUDE_ALL_GCS
1291
template <>
1292
void AFLBinaryTreeDictionary::print_dict_census(void) const {
1293 1294 1295 1296 1297 1298 1299 1300

  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, " ");
1301
  total->print_on(gclog_or_tty, "TOTAL\t");
D
duke 已提交
1302
  gclog_or_tty->print(
1303
              "total_free(words): " SIZE_FORMAT_W(16)
1304
              " growth: %8.5f  deficit: %8.5f\n",
1305 1306 1307 1308
              ptc.total_free(),
              (double)(total->split_births() + total->coal_births()
                     - total->split_deaths() - total->coal_deaths())
              /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0),
1309 1310
             (double)(total->desired() - total->count())
             /(total->desired() != 0 ? (double)total->desired() : 1.0));
D
duke 已提交
1311
}
1312
#endif // INCLUDE_ALL_GCS
D
duke 已提交
1313

1314 1315
template <class Chunk_t, template <class> class FreeList_t>
class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
1316 1317 1318 1319 1320 1321 1322 1323
  outputStream* _st;
  int _print_line;

 public:
  PrintFreeListsClosure(outputStream* st) {
    _st = st;
    _print_line = 0;
  }
1324
  void do_list(FreeList_t<Chunk_t>* fl) {
1325
    if (++_print_line >= 40) {
1326
      FreeList_t<Chunk_t>::print_labels_on(_st, "size");
1327 1328 1329 1330
      _print_line = 0;
    }
    fl->print_on(gclog_or_tty);
    size_t sz = fl->size();
1331
    for (Chunk_t* fc = fl->head(); fc != NULL;
1332 1333 1334 1335 1336 1337 1338 1339
         fc = fc->next()) {
      _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
                    fc, (HeapWord*)fc + sz,
                    fc->cantCoalesce() ? "\t CC" : "");
    }
  }
};

1340 1341
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::print_free_lists(outputStream* st) const {
1342

1343 1344
  FreeList_t<Chunk_t>::print_labels_on(st, "size");
  PrintFreeListsClosure<Chunk_t, FreeList_t> pflc(st);
1345 1346 1347
  pflc.do_tree(root());
}

D
duke 已提交
1348 1349 1350 1351
// Verify the following tree invariants:
// . _root has no parent
// . parent and child point to each other
// . each node's key correctly related to that of its child(ren)
1352 1353
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_tree() const {
1354 1355
  guarantee(root() == NULL || total_free_blocks() == 0 ||
    total_size() != 0, "_total_size should't be 0?");
D
duke 已提交
1356
  guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
1357
  verify_tree_helper(root());
D
duke 已提交
1358 1359
}

1360 1361
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) {
D
duke 已提交
1362
  size_t ct = 0;
1363
  for (Chunk_t* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
D
duke 已提交
1364
    ct++;
1365
    assert(curFC->prev() == NULL || curFC->prev()->is_free(),
D
duke 已提交
1366 1367 1368 1369 1370 1371 1372 1373
      "Chunk should be free");
  }
  return ct;
}

// 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.
1374 1375
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 {
D
duke 已提交
1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
  if (tl == NULL)
    return;
  guarantee(tl->size() != 0, "A list must has a size");
  guarantee(tl->left()  == NULL || tl->left()->parent()  == tl,
         "parent<-/->left");
  guarantee(tl->right() == NULL || tl->right()->parent() == tl,
         "parent<-/->right");;
  guarantee(tl->left() == NULL  || tl->left()->size()    <  tl->size(),
         "parent !> left");
  guarantee(tl->right() == NULL || tl->right()->size()   >  tl->size(),
         "parent !< left");
1387
  guarantee(tl->head() == NULL || tl->head()->is_free(), "!Free");
D
duke 已提交
1388 1389 1390 1391 1392 1393
  guarantee(tl->head() == NULL || tl->head_as_TreeChunk()->list() == tl,
    "list inconsistency");
  guarantee(tl->count() > 0 || (tl->head() == NULL && tl->tail() == NULL),
    "list count is inconsistent");
  guarantee(tl->count() > 1 || tl->head() == tl->tail(),
    "list is incorrectly constructed");
1394
  size_t count = verify_prev_free_ptrs(tl);
D
duke 已提交
1395 1396
  guarantee(count == (size_t)tl->count(), "Node count is incorrect");
  if (tl->head() != NULL) {
1397
    tl->head_as_TreeChunk()->verify_tree_chunk_list();
D
duke 已提交
1398
  }
1399 1400
  verify_tree_helper(tl->left());
  verify_tree_helper(tl->right());
D
duke 已提交
1401 1402
}

1403 1404
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify() const {
1405 1406
  verify_tree();
  guarantee(total_size() == total_size_in_tree(root()), "Total Size inconsistency");
D
duke 已提交
1407
}
1408

1409 1410 1411 1412 1413 1414 1415 1416 1417
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>;


1418
#if INCLUDE_ALL_GCS
1419
// Explicitly instantiate these types for FreeChunk.
1420 1421 1422 1423
template class TreeList<FreeChunk, AdaptiveFreeList>;
template class BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>;
template class TreeChunk<FreeChunk, AdaptiveFreeList>;

1424
#endif // INCLUDE_ALL_GCS