binaryTreeDictionary.cpp 53.0 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 2001, 2012, 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 26
#include "precompiled.hpp"
#include "gc_implementation/shared/allocationStats.hpp"
27
#include "memory/binaryTreeDictionary.hpp"
28 29 30 31
#include "memory/freeList.hpp"
#include "memory/freeBlockDictionary.hpp"
#include "memory/metablock.hpp"
#include "memory/metachunk.hpp"
32 33
#include "runtime/globals.hpp"
#include "utilities/ostream.hpp"
34
#ifndef SERIALGC
35 36
#include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp"
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
37 38 39
#include "gc_implementation/shared/spaceDecorator.hpp"
#include "gc_implementation/concurrentMarkSweep/freeChunk.hpp"
#endif // SERIALGC
D
duke 已提交
40 41 42 43 44 45

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

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

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

69 70
template <class Chunk_t, template <class> class FreeList_t>
TreeList<Chunk_t, FreeList_t>::TreeList() {}
D
duke 已提交
71

72 73 74
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 已提交
75
  // This first free chunk in the list will be the tree list.
76 77 78 79
  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 已提交
80 81 82 83 84
  tc->set_list(tl);
  tl->set_size(tc->size());
  tl->link_head(tc);
  tl->link_tail(tc);
  tl->set_count(1);
85

D
duke 已提交
86 87
  return tl;
}
88

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

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


120 121 122 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 164 165 166 167 168 169 170 171 172 173 174 175
#ifndef SERIALGC
// Specialize for AdaptiveFreeList which tries to avoid
// splitting a chunk of a size that is under populated in favor of
// an over populated size.  The general get_better_list() just returns
// the current list.
template <>
TreeList<FreeChunk, AdaptiveFreeList>*
TreeList<FreeChunk, AdaptiveFreeList>::get_better_list(
  BinaryTreeDictionary<FreeChunk, ::AdaptiveFreeList>* dictionary) {
  // A candidate chunk has been found.  If it is already under
  // populated, get a chunk associated with the hint for this
  // chunk.

  TreeList<FreeChunk, ::AdaptiveFreeList>* curTL = this;
  if (surplus() <= 0) {
    /* Use the hint to find a size with a surplus, and reset the hint. */
    TreeList<FreeChunk, ::AdaptiveFreeList>* hintTL = this;
    while (hintTL->hint() != 0) {
      assert(hintTL->hint() > hintTL->size(),
        "hint points in the wrong direction");
      hintTL = dictionary->find_list(hintTL->hint());
      assert(curTL != hintTL, "Infinite loop");
      if (hintTL == NULL ||
          hintTL == curTL /* Should not happen but protect against it */ ) {
        // No useful hint.  Set the hint to NULL and go on.
        curTL->set_hint(0);
        break;
      }
      assert(hintTL->size() > curTL->size(), "hint is inconsistent");
      if (hintTL->surplus() > 0) {
        // The hint led to a list that has a surplus.  Use it.
        // Set the hint for the candidate to an overpopulated
        // size.
        curTL->set_hint(hintTL->size());
        // Change the candidate.
        curTL = hintTL;
        break;
      }
    }
  }
  return curTL;
}
#endif // SERIALGC

template <class Chunk_t, template <class> class FreeList_t>
TreeList<Chunk_t, FreeList_t>*
TreeList<Chunk_t, FreeList_t>::get_better_list(
  BinaryTreeDictionary<Chunk_t, FreeList_t>* dictionary) {
  return this;
}

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

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

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

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

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

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

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

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

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

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

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

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

393 394 395
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 已提交
396 397 398 399 400 401

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

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

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

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

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

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

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

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

467
    if (dither == FreeBlockDictionary<Chunk_t>::exactly) return NULL;
468

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

    curTL = curTL->get_better_list(this);

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

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

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


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

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

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

566
  bool complicated_splice = false;
D
duke 已提交
567 568 569

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

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

665 666 667 668
  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 已提交
669 670 671 672 673

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

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

718 719 720
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 已提交
721 722
  size_t size = fc->size();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

870 871 872 873 874 875 876
template <class Chunk_t, template <class> class FreeList_t>
void BinaryTreeDictionary<Chunk_t, FreeList_t>::dict_census_update(size_t size, bool split, bool birth){}

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

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

911 912 913
#ifndef SERIALGC
template <>
bool BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::coal_dict_over_populated(size_t size) {
914 915
  if (FLSAlwaysCoalesceLarge) return true;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1055 1056 1057
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 已提交
1058 1059 1060 1061 1062 1063
  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();
}

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

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

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

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

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

1106
  return rbc.dict_returned_bytes();
1107
}
D
duke 已提交
1108

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

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

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

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

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

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

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

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

// Save count before previous sweep and splits and coalesces.
1178 1179 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) {}

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

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

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

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

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

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

#ifndef SERIALGC
  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
    if (++_print_line >= 40) {
      FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, "size");
      _print_line = 0;
    }
    fl->print_on(gclog_or_tty);
    _total_free +=           fl->count()             * fl->size()        ;
    total()->set_count(      total()->count()        + fl->count()      );
    total()->set_bfr_surp(   total()->bfr_surp()     + fl->bfr_surp()    );
1264
    total()->set_surplus(    total()->split_deaths() + fl->surplus()    );
1265
    total()->set_desired(    total()->desired()      + fl->desired()    );
1266 1267 1268 1269 1270 1271
    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 已提交
1272
  }
1273
#endif  // SERIALGC
D
duke 已提交
1274 1275
};

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

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

1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
  FreeList_t<Chunk_t>* total = ptc.total();
  FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, " ");
}

#ifndef SERIALGC
template <>
void BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::print_dict_census(void) const {

  gclog_or_tty->print("\nBinaryTree\n");
  AdaptiveFreeList<FreeChunk>::print_labels_on(gclog_or_tty, "size");
  PrintTreeCensusClosure<FreeChunk, AdaptiveFreeList> ptc;
  ptc.do_tree(root());

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

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

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

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

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

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

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

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

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


1416 1417
#ifndef SERIALGC
// Explicitly instantiate these types for FreeChunk.
1418 1419 1420 1421
template class TreeList<FreeChunk, AdaptiveFreeList>;
template class BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>;
template class TreeChunk<FreeChunk, AdaptiveFreeList>;

1422
#endif // SERIALGC