binaryTreeDictionary.cpp 53.3 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 32
#include "memory/freeList.hpp"
#include "memory/freeBlockDictionary.hpp"
#include "memory/metablock.hpp"
#include "memory/metachunk.hpp"
33 34
#include "runtime/globals.hpp"
#include "utilities/ostream.hpp"
35
#include "utilities/macros.hpp"
36
#include "gc_implementation/shared/spaceDecorator.hpp"
37
#if INCLUDE_ALL_GCS
38 39
#include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp"
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
40
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
41
#endif // INCLUDE_ALL_GCS
D
duke 已提交
42 43 44 45 46 47

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

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

57 58 59
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 已提交
60 61 62 63 64 65 66
  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");
67
    nextTC->verify_tree_chunk_list();
D
duke 已提交
68 69 70
  }
}

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

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

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

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


123
#if INCLUDE_ALL_GCS
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 164
// 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;
}
165
#endif // INCLUDE_ALL_GCS
166 167 168 169 170 171 172 173 174 175 176 177 178

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 已提交
179 180 181 182
  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");
183
  assert(tc->is_free(), "Header is not marked correctly");
D
duke 已提交
184 185 186
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");

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

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

251
  // Below this point the embeded TreeList<Chunk_t, FreeList_t> being used for the
D
duke 已提交
252
  // tree node may have changed. Don't use "this"
253
  // TreeList<Chunk_t, FreeList_t>*.
D
duke 已提交
254 255 256 257
  // 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(
258 259
    tc->link_prev(NULL);
    tc->link_next(NULL);
D
duke 已提交
260 261 262
    tc->set_list(NULL);
    bool prev_found = false;
    bool next_found = false;
263
    for (Chunk_t* curFC = retTL->head();
D
duke 已提交
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
         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();

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

290 291
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 已提交
292 293 294 295
  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 已提交
296
  assert(!this->verify_chunk_in_free_list(chunk), "Double entry");
D
duke 已提交
297 298 299
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");

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

  assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
305
  FreeList_t<Chunk_t>::increment_count();
C
coleenp 已提交
306
  debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
D
duke 已提交
307 308 309 310 311 312
  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
313 314 315 316
// 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 已提交
317 318 319
  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 已提交
320
  assert(!this->verify_chunk_in_free_list(chunk), "Double entry");
D
duke 已提交
321 322 323
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");

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

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

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

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

396 397 398
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 已提交
399 400 401 402 403 404

  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");
405 406
  assert(total_size() == root()->size(), "reset check failed");
  assert(total_free_blocks() == 1, "reset check failed");
D
duke 已提交
407 408
}

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

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

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

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

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

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

  assert((size >= min_size()), "minimum chunk size");
D
duke 已提交
451
  if (FLSVerifyDictionary) {
452
    verify_tree();
D
duke 已提交
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
  }
  // 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
469

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

D
duke 已提交
472 473 474 475 476 477 478 479 480 481
    // 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");
482 483 484

    curTL = curTL->get_better_list(this);

D
duke 已提交
485 486 487 488 489
    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");
490 491
    remove_chunk_from_tree(retTC);
    assert(retTC->is_free(), "Header is not marked correctly");
D
duke 已提交
492 493 494 495 496 497 498 499
  }

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

500 501 502
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 已提交
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
  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;
}


519 520
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 已提交
521
  size_t size = tc->size();
522
  TreeList<Chunk_t, FreeList_t>* tl = find_list(size);
D
duke 已提交
523 524 525
  if (tl == NULL) {
    return false;
  } else {
526
    return tl->verify_chunk_in_free_list(tc);
D
duke 已提交
527 528 529
  }
}

530 531 532
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 已提交
533 534
  if (curTL != NULL) {
    while(curTL->right() != NULL) curTL = curTL->right();
535
    return curTL->largest_address();
D
duke 已提交
536 537 538 539 540 541 542 543 544
  } 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.
545 546 547
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 已提交
548
  assert(tc != NULL, "Should not call with a NULL chunk");
549
  assert(tc->is_free(), "Header is not marked correctly");
D
duke 已提交
550

551 552 553
  TreeList<Chunk_t, FreeList_t> *newTL, *parentTL;
  TreeChunk<Chunk_t, FreeList_t>* retTC;
  TreeList<Chunk_t, FreeList_t>* tl = tc->list();
D
duke 已提交
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568
  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");

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

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

  // 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();
606
      debug_only(replacementTL->clear_right();)
D
duke 已提交
607 608 609
    } else if (replacementTL->right() == NULL) {
      // right is NULL
      newTL = replacementTL->left();
610
      debug_only(replacementTL->clear_left();)
D
duke 已提交
611 612
    } else {  // we have both children, so, by patriarchal convention,
              // my replacement is least node in right sub-tree
613 614
      complicated_splice = true;
      newTL = remove_tree_minimum(replacementTL->right());
D
duke 已提交
615 616 617 618 619 620 621
      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) {
622
      verify_tree();
D
duke 已提交
623 624 625 626 627 628 629
    }
    // 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) {
630
        newTL->clear_parent();
D
duke 已提交
631 632 633
      }
    } else if (parentTL->right() == replacementTL) {
      // replacementTL is a right child
634
      parentTL->set_right(newTL);
D
duke 已提交
635 636
    } else {                                // replacementTL is a left child
      assert(parentTL->left() == replacementTL, "should be left child");
637
      parentTL->set_left(newTL);
D
duke 已提交
638
    }
639 640
    debug_only(replacementTL->clear_parent();)
    if (complicated_splice) {  // we need newTL to get replacementTL's
D
duke 已提交
641 642 643 644 645 646
                              // 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,
647
      //       "else !complicated_splice");
D
duke 已提交
648 649 650 651 652 653
      // ... 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:
654 655 656
      assert(replacementTL->left() != NULL, "else !complicated_splice");
      newTL->set_left(replacementTL->left());
      newTL->set_right(replacementTL->right());
D
duke 已提交
657
      debug_only(
658
        replacementTL->clear_right();
659
        replacementTL->clear_left();
D
duke 已提交
660 661 662 663 664 665 666 667
      )
    }
    assert(replacementTL->right() == NULL &&
           replacementTL->left() == NULL &&
           replacementTL->parent() == NULL,
        "delete without encumbrances");
  }

668 669 670 671
  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 已提交
672 673 674 675 676

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

// 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.
686 687
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 已提交
688 689
  assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
  // locate the subtree minimum by walking down left branches
690
  TreeList<Chunk_t, FreeList_t>* curTL = tl;
D
duke 已提交
691 692 693
  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?
694
    TreeList<Chunk_t, FreeList_t>* parentTL = curTL->parent();
D
duke 已提交
695
    if (parentTL->left() == curTL) { // curTL is a left child
696
      parentTL->set_left(curTL->right());
D
duke 已提交
697 698 699 700
    } 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");
701
      parentTL->set_right(curTL->right());
D
duke 已提交
702 703 704 705 706 707 708 709 710
    }
  } 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(
711 712
    curTL->clear_parent();  // Test if this needs to be cleared
    curTL->clear_right();    // recall, above, left child is already null
D
duke 已提交
713 714 715
  )
  // we just excised a (non-root) node, we should still verify all tree invariants
  if (FLSVerifyDictionary) {
716
    verify_tree();
D
duke 已提交
717 718 719 720
  }
  return curTL;
}

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

726 727 728
  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 已提交
729
  if (FLSVerifyDictionary) {
730
    verify_tree();
D
duke 已提交
731 732
  }

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

  // 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();
    }
  }
748
  TreeChunk<Chunk_t, FreeList_t>* tc = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
749
  // This chunk is being returned to the binary tree.  Its embedded
750
  // TreeList<Chunk_t, FreeList_t> should be unused at this point.
D
duke 已提交
751 752 753
  tc->initialize();
  if (curTL != NULL) {          // exact match
    tc->set_list(curTL);
754
    curTL->return_chunk_at_tail(tc);
D
duke 已提交
755
  } else {                     // need a new node in tree
756 757
    tc->clear_next();
    tc->link_prev(NULL);
758 759
    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 已提交
760 761 762 763 764 765 766
      "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");
767
        prevTL->set_right(newTL);
D
duke 已提交
768 769
      } else {                       // am left child
        assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
770
        prevTL->set_left(newTL);
D
duke 已提交
771 772 773 774 775
      }
    }
  }
  assert(tc->list() != NULL, "Tree list should be set");

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

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

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

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

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

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

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

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

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

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

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

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

876
#if INCLUDE_ALL_GCS
877
template <>
878
void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){
879
  TreeList<FreeChunk, AdaptiveFreeList>* nd = find_list(size);
D
duke 已提交
880 881 882
  if (nd) {
    if (split) {
      if (birth) {
883
        nd->increment_split_births();
D
duke 已提交
884 885
        nd->increment_surplus();
      }  else {
886
        nd->increment_split_deaths();
D
duke 已提交
887 888 889 890
        nd->decrement_surplus();
      }
    } else {
      if (birth) {
891
        nd->increment_coal_births();
D
duke 已提交
892 893
        nd->increment_surplus();
      } else {
894
        nd->increment_coal_deaths();
D
duke 已提交
895 896 897 898 899 900 901 902 903 904
        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.
}
905
#endif // INCLUDE_ALL_GCS
906 907 908 909 910 911 912

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 已提交
913

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

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

// 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.

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

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

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

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

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

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

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

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

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

#if 0 //  Don't need this yet but here for symmetry.
1008 1009
template <class Chunk_t, template <class> class FreeList_t>
class AscendTreeSearchClosure : public TreeSearchClosure<Chunk_t> {
D
duke 已提交
1010
 public:
1011
  bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
D
duke 已提交
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
    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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Print summary statistics
1215 1216 1217
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 已提交
1218 1219
  gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n"
         "------------------------------------\n");
1220 1221 1222 1223 1224 1225 1226
  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 已提交
1227
  }
1228
  gclog_or_tty->print("Tree      Height: %d\n", tree_height());
D
duke 已提交
1229 1230 1231 1232 1233
}

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

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

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

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

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

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

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

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

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

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

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

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

D
duke 已提交
1349 1350 1351 1352
// 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)
1353 1354
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_tree() const {
1355 1356
  guarantee(root() == NULL || total_free_blocks() == 0 ||
    total_size() != 0, "_total_size should't be 0?");
D
duke 已提交
1357
  guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
1358
  verify_tree_helper(root());
D
duke 已提交
1359 1360
}

1361 1362
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 已提交
1363
  size_t ct = 0;
1364
  for (Chunk_t* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
D
duke 已提交
1365
    ct++;
1366
    assert(curFC->prev() == NULL || curFC->prev()->is_free(),
D
duke 已提交
1367 1368 1369 1370 1371 1372 1373 1374
      "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.
1375 1376
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 已提交
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
  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");
1388
  guarantee(tl->head() == NULL || tl->head()->is_free(), "!Free");
D
duke 已提交
1389 1390 1391 1392 1393 1394
  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");
1395
  size_t count = verify_prev_free_ptrs(tl);
D
duke 已提交
1396 1397
  guarantee(count == (size_t)tl->count(), "Node count is incorrect");
  if (tl->head() != NULL) {
1398
    tl->head_as_TreeChunk()->verify_tree_chunk_list();
D
duke 已提交
1399
  }
1400 1401
  verify_tree_helper(tl->left());
  verify_tree_helper(tl->right());
D
duke 已提交
1402 1403
}

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

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


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

1425
#endif // INCLUDE_ALL_GCS