annotate src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp @ 1145:e018e6884bd8

6631166: CMS: better heuristics when combatting fragmentation Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking. Reviewed-by: jmasa
author ysr
date Wed, 23 Dec 2009 09:23:54 -0800
parents 850fdf70db2b
children cff162798819
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
196
d1605aabd0a1 6719955: Update copyright year
xdono
parents: 12
diff changeset
2 * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_binaryTreeDictionary.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 ////////////////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
29 // A binary tree based search structure for free blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
30 // This is currently used in the Concurrent Mark&Sweep implementation.
a61af66fc99e Initial load
duke
parents:
diff changeset
31 ////////////////////////////////////////////////////////////////////////////////
a61af66fc99e Initial load
duke
parents:
diff changeset
32
a61af66fc99e Initial load
duke
parents:
diff changeset
33 TreeChunk* TreeChunk::as_TreeChunk(FreeChunk* fc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // Do some assertion checking here.
a61af66fc99e Initial load
duke
parents:
diff changeset
35 return (TreeChunk*) fc;
a61af66fc99e Initial load
duke
parents:
diff changeset
36 }
a61af66fc99e Initial load
duke
parents:
diff changeset
37
a61af66fc99e Initial load
duke
parents:
diff changeset
38 void TreeChunk::verifyTreeChunkList() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
39 TreeChunk* nextTC = (TreeChunk*)next();
a61af66fc99e Initial load
duke
parents:
diff changeset
40 if (prev() != NULL) { // interior list node shouldn'r have tree fields
a61af66fc99e Initial load
duke
parents:
diff changeset
41 guarantee(embedded_list()->parent() == NULL && embedded_list()->left() == NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
42 embedded_list()->right() == NULL, "should be clear");
a61af66fc99e Initial load
duke
parents:
diff changeset
43 }
a61af66fc99e Initial load
duke
parents:
diff changeset
44 if (nextTC != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
45 guarantee(as_TreeChunk(nextTC->prev()) == this, "broken chain");
a61af66fc99e Initial load
duke
parents:
diff changeset
46 guarantee(nextTC->size() == size(), "wrong size");
a61af66fc99e Initial load
duke
parents:
diff changeset
47 nextTC->verifyTreeChunkList();
a61af66fc99e Initial load
duke
parents:
diff changeset
48 }
a61af66fc99e Initial load
duke
parents:
diff changeset
49 }
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 TreeList* TreeList::as_TreeList(TreeChunk* tc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // This first free chunk in the list will be the tree list.
a61af66fc99e Initial load
duke
parents:
diff changeset
54 assert(tc->size() >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
55 TreeList* tl = tc->embedded_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
56 tc->set_list(tl);
a61af66fc99e Initial load
duke
parents:
diff changeset
57 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
58 tl->set_protecting_lock(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
59 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
60 tl->set_hint(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
61 tl->set_size(tc->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
62 tl->link_head(tc);
a61af66fc99e Initial load
duke
parents:
diff changeset
63 tl->link_tail(tc);
a61af66fc99e Initial load
duke
parents:
diff changeset
64 tl->set_count(1);
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
65 tl->init_statistics(true /* split_birth */);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
66 tl->setParent(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
67 tl->setLeft(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
68 tl->setRight(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
69 return tl;
a61af66fc99e Initial load
duke
parents:
diff changeset
70 }
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
71
0
a61af66fc99e Initial load
duke
parents:
diff changeset
72 TreeList* TreeList::as_TreeList(HeapWord* addr, size_t size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
73 TreeChunk* tc = (TreeChunk*) addr;
a61af66fc99e Initial load
duke
parents:
diff changeset
74 assert(size >= sizeof(TreeChunk), "Chunk is too small for a TreeChunk");
263
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
75 // The space in the heap will have been mangled initially but
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
76 // is not remangled when a free chunk is returned to the free list
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
77 // (since it is used to maintain the chunk on the free list).
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
78 assert((ZapUnusedHeapArea &&
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
79 SpaceMangler::is_mangled((HeapWord*) tc->size_addr()) &&
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
80 SpaceMangler::is_mangled((HeapWord*) tc->prev_addr()) &&
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
81 SpaceMangler::is_mangled((HeapWord*) tc->next_addr())) ||
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
82 (tc->size() == 0 && tc->prev() == NULL && tc->next() == NULL),
12eea04c8b06 6672698: mangle_unused_area() should not remangle the entire heap at each collection.
jmasa
parents: 12
diff changeset
83 "Space should be clear or mangled");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
84 tc->setSize(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
85 tc->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
86 tc->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
87 TreeList* tl = TreeList::as_TreeList(tc);
a61af66fc99e Initial load
duke
parents:
diff changeset
88 return tl;
a61af66fc99e Initial load
duke
parents:
diff changeset
89 }
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91 TreeList* TreeList::removeChunkReplaceIfNeeded(TreeChunk* tc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
92
a61af66fc99e Initial load
duke
parents:
diff changeset
93 TreeList* retTL = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
94 FreeChunk* list = head();
a61af66fc99e Initial load
duke
parents:
diff changeset
95 assert(!list || list != list->next(), "Chunk on list twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
96 assert(tc != NULL, "Chunk being removed is NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
97 assert(parent() == NULL || this == parent()->left() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
98 this == parent()->right(), "list is inconsistent");
a61af66fc99e Initial load
duke
parents:
diff changeset
99 assert(tc->isFree(), "Header is not marked correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
100 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
101 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
102
a61af66fc99e Initial load
duke
parents:
diff changeset
103 FreeChunk* prevFC = tc->prev();
a61af66fc99e Initial load
duke
parents:
diff changeset
104 TreeChunk* nextTC = TreeChunk::as_TreeChunk(tc->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
105 assert(list != NULL, "should have at least the target chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
106
a61af66fc99e Initial load
duke
parents:
diff changeset
107 // Is this the first item on the list?
a61af66fc99e Initial load
duke
parents:
diff changeset
108 if (tc == list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
109 // The "getChunk..." functions for a TreeList will not return the
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // first chunk in the list unless it is the last chunk in the list
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // because the first chunk is also acting as the tree node.
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // When coalescing happens, however, the first chunk in the a tree
a61af66fc99e Initial load
duke
parents:
diff changeset
113 // list can be the start of a free range. Free ranges are removed
a61af66fc99e Initial load
duke
parents:
diff changeset
114 // from the free lists so that they are not available to be
a61af66fc99e Initial load
duke
parents:
diff changeset
115 // allocated when the sweeper yields (giving up the free list lock)
a61af66fc99e Initial load
duke
parents:
diff changeset
116 // to allow mutator activity. If this chunk is the first in the
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // list and is not the last in the list, do the work to copy the
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // TreeList from the first chunk to the next chunk and update all
a61af66fc99e Initial load
duke
parents:
diff changeset
119 // the TreeList pointers in the chunks in the list.
a61af66fc99e Initial load
duke
parents:
diff changeset
120 if (nextTC == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
121 assert(prevFC == NULL, "Not last chunk in the list")
a61af66fc99e Initial load
duke
parents:
diff changeset
122 set_tail(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
123 set_head(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
124 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 // copy embedded list.
a61af66fc99e Initial load
duke
parents:
diff changeset
126 nextTC->set_embedded_list(tc->embedded_list());
a61af66fc99e Initial load
duke
parents:
diff changeset
127 retTL = nextTC->embedded_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
128 // Fix the pointer to the list in each chunk in the list.
a61af66fc99e Initial load
duke
parents:
diff changeset
129 // This can be slow for a long list. Consider having
a61af66fc99e Initial load
duke
parents:
diff changeset
130 // an option that does not allow the first chunk on the
a61af66fc99e Initial load
duke
parents:
diff changeset
131 // list to be coalesced.
a61af66fc99e Initial load
duke
parents:
diff changeset
132 for (TreeChunk* curTC = nextTC; curTC != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
133 curTC = TreeChunk::as_TreeChunk(curTC->next())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
134 curTC->set_list(retTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
136 // Fix the parent to point to the new TreeList.
a61af66fc99e Initial load
duke
parents:
diff changeset
137 if (retTL->parent() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
138 if (this == retTL->parent()->left()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
139 retTL->parent()->setLeft(retTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
140 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
141 assert(this == retTL->parent()->right(), "Parent is incorrect");
a61af66fc99e Initial load
duke
parents:
diff changeset
142 retTL->parent()->setRight(retTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
144 }
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // Fix the children's parent pointers to point to the
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // new list.
a61af66fc99e Initial load
duke
parents:
diff changeset
147 assert(right() == retTL->right(), "Should have been copied");
a61af66fc99e Initial load
duke
parents:
diff changeset
148 if (retTL->right() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
149 retTL->right()->setParent(retTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
150 }
a61af66fc99e Initial load
duke
parents:
diff changeset
151 assert(left() == retTL->left(), "Should have been copied");
a61af66fc99e Initial load
duke
parents:
diff changeset
152 if (retTL->left() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
153 retTL->left()->setParent(retTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
155 retTL->link_head(nextTC);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 assert(nextTC->isFree(), "Should be a free chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
158 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 if (nextTC == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // Removing chunk at tail of list
a61af66fc99e Initial load
duke
parents:
diff changeset
161 link_tail(prevFC);
a61af66fc99e Initial load
duke
parents:
diff changeset
162 }
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // Chunk is interior to the list
a61af66fc99e Initial load
duke
parents:
diff changeset
164 prevFC->linkAfter(nextTC);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
166
a61af66fc99e Initial load
duke
parents:
diff changeset
167 // Below this point the embeded TreeList being used for the
a61af66fc99e Initial load
duke
parents:
diff changeset
168 // tree node may have changed. Don't use "this"
a61af66fc99e Initial load
duke
parents:
diff changeset
169 // TreeList*.
a61af66fc99e Initial load
duke
parents:
diff changeset
170 // chunk should still be a free chunk (bit set in _prev)
a61af66fc99e Initial load
duke
parents:
diff changeset
171 assert(!retTL->head() || retTL->size() == retTL->head()->size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
172 "Wrong sized chunk in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
173 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
174 tc->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
175 tc->linkNext(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
176 tc->set_list(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
177 bool prev_found = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
178 bool next_found = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 for (FreeChunk* curFC = retTL->head();
a61af66fc99e Initial load
duke
parents:
diff changeset
180 curFC != NULL; curFC = curFC->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
181 assert(curFC != tc, "Chunk is still in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
182 if (curFC == prevFC) {
a61af66fc99e Initial load
duke
parents:
diff changeset
183 prev_found = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
184 }
a61af66fc99e Initial load
duke
parents:
diff changeset
185 if (curFC == nextTC) {
a61af66fc99e Initial load
duke
parents:
diff changeset
186 next_found = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
189 assert(prevFC == NULL || prev_found, "Chunk was lost from list");
a61af66fc99e Initial load
duke
parents:
diff changeset
190 assert(nextTC == NULL || next_found, "Chunk was lost from list");
a61af66fc99e Initial load
duke
parents:
diff changeset
191 assert(retTL->parent() == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
192 retTL == retTL->parent()->left() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
193 retTL == retTL->parent()->right(),
a61af66fc99e Initial load
duke
parents:
diff changeset
194 "list is inconsistent");
a61af66fc99e Initial load
duke
parents:
diff changeset
195 )
a61af66fc99e Initial load
duke
parents:
diff changeset
196 retTL->decrement_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
197
a61af66fc99e Initial load
duke
parents:
diff changeset
198 assert(tc->isFree(), "Should still be a free chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
199 assert(retTL->head() == NULL || retTL->head()->prev() == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
200 "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
201 assert(retTL->tail() == NULL || retTL->tail()->next() == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
202 "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
203 return retTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
204 }
a61af66fc99e Initial load
duke
parents:
diff changeset
205 void TreeList::returnChunkAtTail(TreeChunk* chunk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 assert(chunk != NULL, "returning NULL chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
207 assert(chunk->list() == this, "list should be set for chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
208 assert(tail() != NULL, "The tree list is embedded in the first chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // which means that the list can never be empty.
a61af66fc99e Initial load
duke
parents:
diff changeset
210 assert(!verifyChunkInFreeLists(chunk), "Double entry");
a61af66fc99e Initial load
duke
parents:
diff changeset
211 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
212 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
213
a61af66fc99e Initial load
duke
parents:
diff changeset
214 FreeChunk* fc = tail();
a61af66fc99e Initial load
duke
parents:
diff changeset
215 fc->linkAfter(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
216 link_tail(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
217
a61af66fc99e Initial load
duke
parents:
diff changeset
218 assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
219 increment_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
220 debug_only(increment_returnedBytes_by(chunk->size()*sizeof(HeapWord));)
a61af66fc99e Initial load
duke
parents:
diff changeset
221 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
222 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
223 }
a61af66fc99e Initial load
duke
parents:
diff changeset
224
a61af66fc99e Initial load
duke
parents:
diff changeset
225 // Add this chunk at the head of the list. "At the head of the list"
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // is defined to be after the chunk pointer to by head(). This is
a61af66fc99e Initial load
duke
parents:
diff changeset
227 // because the TreeList is embedded in the first TreeChunk in the
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // list. See the definition of TreeChunk.
a61af66fc99e Initial load
duke
parents:
diff changeset
229 void TreeList::returnChunkAtHead(TreeChunk* chunk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
230 assert(chunk->list() == this, "list should be set for chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
231 assert(head() != NULL, "The tree list is embedded in the first chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
232 assert(chunk != NULL, "returning NULL chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
233 assert(!verifyChunkInFreeLists(chunk), "Double entry");
a61af66fc99e Initial load
duke
parents:
diff changeset
234 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
235 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
236
a61af66fc99e Initial load
duke
parents:
diff changeset
237 FreeChunk* fc = head()->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
238 if (fc != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
239 chunk->linkAfter(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
240 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
241 assert(tail() == NULL, "List is inconsistent");
a61af66fc99e Initial load
duke
parents:
diff changeset
242 link_tail(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
244 head()->linkAfter(chunk);
a61af66fc99e Initial load
duke
parents:
diff changeset
245 assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
246 increment_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
247 debug_only(increment_returnedBytes_by(chunk->size()*sizeof(HeapWord));)
a61af66fc99e Initial load
duke
parents:
diff changeset
248 assert(head() == NULL || head()->prev() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
249 assert(tail() == NULL || tail()->next() == NULL, "list invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251
a61af66fc99e Initial load
duke
parents:
diff changeset
252 TreeChunk* TreeList::head_as_TreeChunk() {
a61af66fc99e Initial load
duke
parents:
diff changeset
253 assert(head() == NULL || TreeChunk::as_TreeChunk(head())->list() == this,
a61af66fc99e Initial load
duke
parents:
diff changeset
254 "Wrong type of chunk?");
a61af66fc99e Initial load
duke
parents:
diff changeset
255 return TreeChunk::as_TreeChunk(head());
a61af66fc99e Initial load
duke
parents:
diff changeset
256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
257
a61af66fc99e Initial load
duke
parents:
diff changeset
258 TreeChunk* TreeList::first_available() {
a61af66fc99e Initial load
duke
parents:
diff changeset
259 guarantee(head() != NULL, "The head of the list cannot be NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
260 FreeChunk* fc = head()->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
261 TreeChunk* retTC;
a61af66fc99e Initial load
duke
parents:
diff changeset
262 if (fc == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
263 retTC = head_as_TreeChunk();
a61af66fc99e Initial load
duke
parents:
diff changeset
264 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
265 retTC = TreeChunk::as_TreeChunk(fc);
a61af66fc99e Initial load
duke
parents:
diff changeset
266 }
a61af66fc99e Initial load
duke
parents:
diff changeset
267 assert(retTC->list() == this, "Wrong type of chunk.");
a61af66fc99e Initial load
duke
parents:
diff changeset
268 return retTC;
a61af66fc99e Initial load
duke
parents:
diff changeset
269 }
a61af66fc99e Initial load
duke
parents:
diff changeset
270
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
271 // Returns the block with the largest heap address amongst
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
272 // those in the list for this size; potentially slow and expensive,
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
273 // use with caution!
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
274 TreeChunk* TreeList::largest_address() {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
275 guarantee(head() != NULL, "The head of the list cannot be NULL");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
276 FreeChunk* fc = head()->next();
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
277 TreeChunk* retTC;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
278 if (fc == NULL) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
279 retTC = head_as_TreeChunk();
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
280 } else {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
281 // walk down the list and return the one with the highest
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
282 // heap address among chunks of this size.
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
283 FreeChunk* last = fc;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
284 while (fc->next() != NULL) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
285 if ((HeapWord*)last < (HeapWord*)fc) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
286 last = fc;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
287 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
288 fc = fc->next();
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
289 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
290 retTC = TreeChunk::as_TreeChunk(last);
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
291 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
292 assert(retTC->list() == this, "Wrong type of chunk.");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
293 return retTC;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
294 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
295
0
a61af66fc99e Initial load
duke
parents:
diff changeset
296 BinaryTreeDictionary::BinaryTreeDictionary(MemRegion mr, bool splay):
a61af66fc99e Initial load
duke
parents:
diff changeset
297 _splay(splay)
a61af66fc99e Initial load
duke
parents:
diff changeset
298 {
a61af66fc99e Initial load
duke
parents:
diff changeset
299 assert(mr.byte_size() > MIN_TREE_CHUNK_SIZE, "minimum chunk size");
a61af66fc99e Initial load
duke
parents:
diff changeset
300
a61af66fc99e Initial load
duke
parents:
diff changeset
301 reset(mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
302 assert(root()->left() == NULL, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
303 assert(root()->right() == NULL, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
304 assert(root()->head()->next() == NULL, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
305 assert(root()->head()->prev() == NULL, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
306 assert(totalSize() == root()->size(), "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
307 assert(totalFreeBlocks() == 1, "reset check failed");
a61af66fc99e Initial load
duke
parents:
diff changeset
308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
309
a61af66fc99e Initial load
duke
parents:
diff changeset
310 void BinaryTreeDictionary::inc_totalSize(size_t inc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
311 _totalSize = _totalSize + inc;
a61af66fc99e Initial load
duke
parents:
diff changeset
312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
313
a61af66fc99e Initial load
duke
parents:
diff changeset
314 void BinaryTreeDictionary::dec_totalSize(size_t dec) {
a61af66fc99e Initial load
duke
parents:
diff changeset
315 _totalSize = _totalSize - dec;
a61af66fc99e Initial load
duke
parents:
diff changeset
316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
317
a61af66fc99e Initial load
duke
parents:
diff changeset
318 void BinaryTreeDictionary::reset(MemRegion mr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
319 assert(mr.byte_size() > MIN_TREE_CHUNK_SIZE, "minimum chunk size");
a61af66fc99e Initial load
duke
parents:
diff changeset
320 set_root(TreeList::as_TreeList(mr.start(), mr.word_size()));
a61af66fc99e Initial load
duke
parents:
diff changeset
321 set_totalSize(mr.word_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
322 set_totalFreeBlocks(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
323 }
a61af66fc99e Initial load
duke
parents:
diff changeset
324
a61af66fc99e Initial load
duke
parents:
diff changeset
325 void BinaryTreeDictionary::reset(HeapWord* addr, size_t byte_size) {
a61af66fc99e Initial load
duke
parents:
diff changeset
326 MemRegion mr(addr, heap_word_size(byte_size));
a61af66fc99e Initial load
duke
parents:
diff changeset
327 reset(mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
328 }
a61af66fc99e Initial load
duke
parents:
diff changeset
329
a61af66fc99e Initial load
duke
parents:
diff changeset
330 void BinaryTreeDictionary::reset() {
a61af66fc99e Initial load
duke
parents:
diff changeset
331 set_root(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
332 set_totalSize(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 set_totalFreeBlocks(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
334 }
a61af66fc99e Initial load
duke
parents:
diff changeset
335
a61af66fc99e Initial load
duke
parents:
diff changeset
336 // Get a free block of size at least size from tree, or NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
337 // If a splay step is requested, the removal algorithm (only) incorporates
a61af66fc99e Initial load
duke
parents:
diff changeset
338 // a splay step as follows:
a61af66fc99e Initial load
duke
parents:
diff changeset
339 // . the search proceeds down the tree looking for a possible
a61af66fc99e Initial load
duke
parents:
diff changeset
340 // match. At the (closest) matching location, an appropriate splay step is applied
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // (zig, zig-zig or zig-zag). A chunk of the appropriate size is then returned
a61af66fc99e Initial load
duke
parents:
diff changeset
342 // if available, and if it's the last chunk, the node is deleted. A deteleted
a61af66fc99e Initial load
duke
parents:
diff changeset
343 // node is replaced in place by its tree successor.
a61af66fc99e Initial load
duke
parents:
diff changeset
344 TreeChunk*
a61af66fc99e Initial load
duke
parents:
diff changeset
345 BinaryTreeDictionary::getChunkFromTree(size_t size, Dither dither, bool splay)
a61af66fc99e Initial load
duke
parents:
diff changeset
346 {
a61af66fc99e Initial load
duke
parents:
diff changeset
347 TreeList *curTL, *prevTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
348 TreeChunk* retTC = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
349 assert(size >= MIN_TREE_CHUNK_SIZE, "minimum chunk size");
a61af66fc99e Initial load
duke
parents:
diff changeset
350 if (FLSVerifyDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
351 verifyTree();
a61af66fc99e Initial load
duke
parents:
diff changeset
352 }
a61af66fc99e Initial load
duke
parents:
diff changeset
353 // starting at the root, work downwards trying to find match.
a61af66fc99e Initial load
duke
parents:
diff changeset
354 // Remember the last node of size too great or too small.
a61af66fc99e Initial load
duke
parents:
diff changeset
355 for (prevTL = curTL = root(); curTL != NULL;) {
a61af66fc99e Initial load
duke
parents:
diff changeset
356 if (curTL->size() == size) { // exact match
a61af66fc99e Initial load
duke
parents:
diff changeset
357 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
358 }
a61af66fc99e Initial load
duke
parents:
diff changeset
359 prevTL = curTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
360 if (curTL->size() < size) { // proceed to right sub-tree
a61af66fc99e Initial load
duke
parents:
diff changeset
361 curTL = curTL->right();
a61af66fc99e Initial load
duke
parents:
diff changeset
362 } else { // proceed to left sub-tree
a61af66fc99e Initial load
duke
parents:
diff changeset
363 assert(curTL->size() > size, "size inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
364 curTL = curTL->left();
a61af66fc99e Initial load
duke
parents:
diff changeset
365 }
a61af66fc99e Initial load
duke
parents:
diff changeset
366 }
a61af66fc99e Initial load
duke
parents:
diff changeset
367 if (curTL == NULL) { // couldn't find exact match
a61af66fc99e Initial load
duke
parents:
diff changeset
368 // try and find the next larger size by walking back up the search path
a61af66fc99e Initial load
duke
parents:
diff changeset
369 for (curTL = prevTL; curTL != NULL;) {
a61af66fc99e Initial load
duke
parents:
diff changeset
370 if (curTL->size() >= size) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
371 else curTL = curTL->parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
372 }
a61af66fc99e Initial load
duke
parents:
diff changeset
373 assert(curTL == NULL || curTL->count() > 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
374 "An empty list should not be in the tree");
a61af66fc99e Initial load
duke
parents:
diff changeset
375 }
a61af66fc99e Initial load
duke
parents:
diff changeset
376 if (curTL != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
377 assert(curTL->size() >= size, "size inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
378 if (UseCMSAdaptiveFreeLists) {
a61af66fc99e Initial load
duke
parents:
diff changeset
379
a61af66fc99e Initial load
duke
parents:
diff changeset
380 // A candidate chunk has been found. If it is already under
a61af66fc99e Initial load
duke
parents:
diff changeset
381 // populated, get a chunk associated with the hint for this
a61af66fc99e Initial load
duke
parents:
diff changeset
382 // chunk.
a61af66fc99e Initial load
duke
parents:
diff changeset
383 if (curTL->surplus() <= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
384 /* Use the hint to find a size with a surplus, and reset the hint. */
a61af66fc99e Initial load
duke
parents:
diff changeset
385 TreeList* hintTL = curTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
386 while (hintTL->hint() != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
387 assert(hintTL->hint() == 0 || hintTL->hint() > hintTL->size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
388 "hint points in the wrong direction");
a61af66fc99e Initial load
duke
parents:
diff changeset
389 hintTL = findList(hintTL->hint());
a61af66fc99e Initial load
duke
parents:
diff changeset
390 assert(curTL != hintTL, "Infinite loop");
a61af66fc99e Initial load
duke
parents:
diff changeset
391 if (hintTL == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
392 hintTL == curTL /* Should not happen but protect against it */ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
393 // No useful hint. Set the hint to NULL and go on.
a61af66fc99e Initial load
duke
parents:
diff changeset
394 curTL->set_hint(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
395 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
396 }
a61af66fc99e Initial load
duke
parents:
diff changeset
397 assert(hintTL->size() > size, "hint is inconsistent");
a61af66fc99e Initial load
duke
parents:
diff changeset
398 if (hintTL->surplus() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // The hint led to a list that has a surplus. Use it.
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // Set the hint for the candidate to an overpopulated
a61af66fc99e Initial load
duke
parents:
diff changeset
401 // size.
a61af66fc99e Initial load
duke
parents:
diff changeset
402 curTL->set_hint(hintTL->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
403 // Change the candidate.
a61af66fc99e Initial load
duke
parents:
diff changeset
404 curTL = hintTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
405 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
406 }
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // The evm code reset the hint of the candidate as
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
408 // at an interim point. Why? Seems like this leaves
0
a61af66fc99e Initial load
duke
parents:
diff changeset
409 // the hint pointing to a list that didn't work.
a61af66fc99e Initial load
duke
parents:
diff changeset
410 // curTL->set_hint(hintTL->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
411 }
a61af66fc99e Initial load
duke
parents:
diff changeset
412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
413 }
a61af66fc99e Initial load
duke
parents:
diff changeset
414 // don't waste time splaying if chunk's singleton
a61af66fc99e Initial load
duke
parents:
diff changeset
415 if (splay && curTL->head()->next() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
416 semiSplayStep(curTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
418 retTC = curTL->first_available();
a61af66fc99e Initial load
duke
parents:
diff changeset
419 assert((retTC != NULL) && (curTL->count() > 0),
a61af66fc99e Initial load
duke
parents:
diff changeset
420 "A list in the binary tree should not be NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
421 assert(retTC->size() >= size,
a61af66fc99e Initial load
duke
parents:
diff changeset
422 "A chunk of the wrong size was found");
a61af66fc99e Initial load
duke
parents:
diff changeset
423 removeChunkFromTree(retTC);
a61af66fc99e Initial load
duke
parents:
diff changeset
424 assert(retTC->isFree(), "Header is not marked correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
425 }
a61af66fc99e Initial load
duke
parents:
diff changeset
426
a61af66fc99e Initial load
duke
parents:
diff changeset
427 if (FLSVerifyDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
428 verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
430 return retTC;
a61af66fc99e Initial load
duke
parents:
diff changeset
431 }
a61af66fc99e Initial load
duke
parents:
diff changeset
432
a61af66fc99e Initial load
duke
parents:
diff changeset
433 TreeList* BinaryTreeDictionary::findList(size_t size) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
434 TreeList* curTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
435 for (curTL = root(); curTL != NULL;) {
a61af66fc99e Initial load
duke
parents:
diff changeset
436 if (curTL->size() == size) { // exact match
a61af66fc99e Initial load
duke
parents:
diff changeset
437 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
439
a61af66fc99e Initial load
duke
parents:
diff changeset
440 if (curTL->size() < size) { // proceed to right sub-tree
a61af66fc99e Initial load
duke
parents:
diff changeset
441 curTL = curTL->right();
a61af66fc99e Initial load
duke
parents:
diff changeset
442 } else { // proceed to left sub-tree
a61af66fc99e Initial load
duke
parents:
diff changeset
443 assert(curTL->size() > size, "size inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
444 curTL = curTL->left();
a61af66fc99e Initial load
duke
parents:
diff changeset
445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
447 return curTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
449
a61af66fc99e Initial load
duke
parents:
diff changeset
450
a61af66fc99e Initial load
duke
parents:
diff changeset
451 bool BinaryTreeDictionary::verifyChunkInFreeLists(FreeChunk* tc) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
452 size_t size = tc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
453 TreeList* tl = findList(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
454 if (tl == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
455 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
456 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
457 return tl->verifyChunkInFreeLists(tc);
a61af66fc99e Initial load
duke
parents:
diff changeset
458 }
a61af66fc99e Initial load
duke
parents:
diff changeset
459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
460
a61af66fc99e Initial load
duke
parents:
diff changeset
461 FreeChunk* BinaryTreeDictionary::findLargestDict() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
462 TreeList *curTL = root();
a61af66fc99e Initial load
duke
parents:
diff changeset
463 if (curTL != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
464 while(curTL->right() != NULL) curTL = curTL->right();
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
465 return curTL->largest_address();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
466 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
467 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
468 }
a61af66fc99e Initial load
duke
parents:
diff changeset
469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
470
a61af66fc99e Initial load
duke
parents:
diff changeset
471 // Remove the current chunk from the tree. If it is not the last
a61af66fc99e Initial load
duke
parents:
diff changeset
472 // chunk in a list on a tree node, just unlink it.
a61af66fc99e Initial load
duke
parents:
diff changeset
473 // If it is the last chunk in the list (the next link is NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
474 // remove the node and repair the tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
475 TreeChunk*
a61af66fc99e Initial load
duke
parents:
diff changeset
476 BinaryTreeDictionary::removeChunkFromTree(TreeChunk* tc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
477 assert(tc != NULL, "Should not call with a NULL chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
478 assert(tc->isFree(), "Header is not marked correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
479
a61af66fc99e Initial load
duke
parents:
diff changeset
480 TreeList *newTL, *parentTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
481 TreeChunk* retTC;
a61af66fc99e Initial load
duke
parents:
diff changeset
482 TreeList* tl = tc->list();
a61af66fc99e Initial load
duke
parents:
diff changeset
483 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
484 bool removing_only_chunk = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
485 if (tl == _root) {
a61af66fc99e Initial load
duke
parents:
diff changeset
486 if ((_root->left() == NULL) && (_root->right() == NULL)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
487 if (_root->count() == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
488 assert(_root->head() == tc, "Should only be this one chunk");
a61af66fc99e Initial load
duke
parents:
diff changeset
489 removing_only_chunk = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
491 }
a61af66fc99e Initial load
duke
parents:
diff changeset
492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
493 )
a61af66fc99e Initial load
duke
parents:
diff changeset
494 assert(tl != NULL, "List should be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
495 assert(tl->parent() == NULL || tl == tl->parent()->left() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
496 tl == tl->parent()->right(), "list is inconsistent");
a61af66fc99e Initial load
duke
parents:
diff changeset
497
a61af66fc99e Initial load
duke
parents:
diff changeset
498 bool complicatedSplice = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
499
a61af66fc99e Initial load
duke
parents:
diff changeset
500 retTC = tc;
a61af66fc99e Initial load
duke
parents:
diff changeset
501 // Removing this chunk can have the side effect of changing the node
a61af66fc99e Initial load
duke
parents:
diff changeset
502 // (TreeList*) in the tree. If the node is the root, update it.
a61af66fc99e Initial load
duke
parents:
diff changeset
503 TreeList* replacementTL = tl->removeChunkReplaceIfNeeded(tc);
a61af66fc99e Initial load
duke
parents:
diff changeset
504 assert(tc->isFree(), "Chunk should still be free");
a61af66fc99e Initial load
duke
parents:
diff changeset
505 assert(replacementTL->parent() == NULL ||
a61af66fc99e Initial load
duke
parents:
diff changeset
506 replacementTL == replacementTL->parent()->left() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
507 replacementTL == replacementTL->parent()->right(),
a61af66fc99e Initial load
duke
parents:
diff changeset
508 "list is inconsistent");
a61af66fc99e Initial load
duke
parents:
diff changeset
509 if (tl == root()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
510 assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
a61af66fc99e Initial load
duke
parents:
diff changeset
511 set_root(replacementTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
512 }
a61af66fc99e Initial load
duke
parents:
diff changeset
513 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
514 if (tl != replacementTL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
515 assert(replacementTL->head() != NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
516 "If the tree list was replaced, it should not be a NULL list");
a61af66fc99e Initial load
duke
parents:
diff changeset
517 TreeList* rhl = replacementTL->head_as_TreeChunk()->list();
a61af66fc99e Initial load
duke
parents:
diff changeset
518 TreeList* rtl = TreeChunk::as_TreeChunk(replacementTL->tail())->list();
a61af66fc99e Initial load
duke
parents:
diff changeset
519 assert(rhl == replacementTL, "Broken head");
a61af66fc99e Initial load
duke
parents:
diff changeset
520 assert(rtl == replacementTL, "Broken tail");
a61af66fc99e Initial load
duke
parents:
diff changeset
521 assert(replacementTL->size() == tc->size(), "Broken size");
a61af66fc99e Initial load
duke
parents:
diff changeset
522 }
a61af66fc99e Initial load
duke
parents:
diff changeset
523 )
a61af66fc99e Initial load
duke
parents:
diff changeset
524
a61af66fc99e Initial load
duke
parents:
diff changeset
525 // Does the tree need to be repaired?
a61af66fc99e Initial load
duke
parents:
diff changeset
526 if (replacementTL->count() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
527 assert(replacementTL->head() == NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
528 replacementTL->tail() == NULL, "list count is incorrect");
a61af66fc99e Initial load
duke
parents:
diff changeset
529 // Find the replacement node for the (soon to be empty) node being removed.
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // if we have a single (or no) child, splice child in our stead
a61af66fc99e Initial load
duke
parents:
diff changeset
531 if (replacementTL->left() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
532 // left is NULL so pick right. right may also be NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
533 newTL = replacementTL->right();
a61af66fc99e Initial load
duke
parents:
diff changeset
534 debug_only(replacementTL->clearRight();)
a61af66fc99e Initial load
duke
parents:
diff changeset
535 } else if (replacementTL->right() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
536 // right is NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
537 newTL = replacementTL->left();
a61af66fc99e Initial load
duke
parents:
diff changeset
538 debug_only(replacementTL->clearLeft();)
a61af66fc99e Initial load
duke
parents:
diff changeset
539 } else { // we have both children, so, by patriarchal convention,
a61af66fc99e Initial load
duke
parents:
diff changeset
540 // my replacement is least node in right sub-tree
a61af66fc99e Initial load
duke
parents:
diff changeset
541 complicatedSplice = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
542 newTL = removeTreeMinimum(replacementTL->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
543 assert(newTL != NULL && newTL->left() == NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
544 newTL->right() == NULL, "sub-tree minimum exists");
a61af66fc99e Initial load
duke
parents:
diff changeset
545 }
a61af66fc99e Initial load
duke
parents:
diff changeset
546 // newTL is the replacement for the (soon to be empty) node.
a61af66fc99e Initial load
duke
parents:
diff changeset
547 // newTL may be NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
548 // should verify; we just cleanly excised our replacement
a61af66fc99e Initial load
duke
parents:
diff changeset
549 if (FLSVerifyDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
550 verifyTree();
a61af66fc99e Initial load
duke
parents:
diff changeset
551 }
a61af66fc99e Initial load
duke
parents:
diff changeset
552 // first make newTL my parent's child
a61af66fc99e Initial load
duke
parents:
diff changeset
553 if ((parentTL = replacementTL->parent()) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
554 // newTL should be root
a61af66fc99e Initial load
duke
parents:
diff changeset
555 assert(tl == root(), "Incorrectly replacing root");
a61af66fc99e Initial load
duke
parents:
diff changeset
556 set_root(newTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
557 if (newTL != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
558 newTL->clearParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
559 }
a61af66fc99e Initial load
duke
parents:
diff changeset
560 } else if (parentTL->right() == replacementTL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
561 // replacementTL is a right child
a61af66fc99e Initial load
duke
parents:
diff changeset
562 parentTL->setRight(newTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
563 } else { // replacementTL is a left child
a61af66fc99e Initial load
duke
parents:
diff changeset
564 assert(parentTL->left() == replacementTL, "should be left child");
a61af66fc99e Initial load
duke
parents:
diff changeset
565 parentTL->setLeft(newTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
566 }
a61af66fc99e Initial load
duke
parents:
diff changeset
567 debug_only(replacementTL->clearParent();)
a61af66fc99e Initial load
duke
parents:
diff changeset
568 if (complicatedSplice) { // we need newTL to get replacementTL's
a61af66fc99e Initial load
duke
parents:
diff changeset
569 // two children
a61af66fc99e Initial load
duke
parents:
diff changeset
570 assert(newTL != NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
571 newTL->left() == NULL && newTL->right() == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
572 "newTL should not have encumbrances from the past");
a61af66fc99e Initial load
duke
parents:
diff changeset
573 // we'd like to assert as below:
a61af66fc99e Initial load
duke
parents:
diff changeset
574 // assert(replacementTL->left() != NULL && replacementTL->right() != NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
575 // "else !complicatedSplice");
a61af66fc99e Initial load
duke
parents:
diff changeset
576 // ... however, the above assertion is too strong because we aren't
a61af66fc99e Initial load
duke
parents:
diff changeset
577 // guaranteed that replacementTL->right() is still NULL.
a61af66fc99e Initial load
duke
parents:
diff changeset
578 // Recall that we removed
a61af66fc99e Initial load
duke
parents:
diff changeset
579 // the right sub-tree minimum from replacementTL.
a61af66fc99e Initial load
duke
parents:
diff changeset
580 // That may well have been its right
a61af66fc99e Initial load
duke
parents:
diff changeset
581 // child! So we'll just assert half of the above:
a61af66fc99e Initial load
duke
parents:
diff changeset
582 assert(replacementTL->left() != NULL, "else !complicatedSplice");
a61af66fc99e Initial load
duke
parents:
diff changeset
583 newTL->setLeft(replacementTL->left());
a61af66fc99e Initial load
duke
parents:
diff changeset
584 newTL->setRight(replacementTL->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
585 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
586 replacementTL->clearRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
587 replacementTL->clearLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
588 )
a61af66fc99e Initial load
duke
parents:
diff changeset
589 }
a61af66fc99e Initial load
duke
parents:
diff changeset
590 assert(replacementTL->right() == NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
591 replacementTL->left() == NULL &&
a61af66fc99e Initial load
duke
parents:
diff changeset
592 replacementTL->parent() == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
593 "delete without encumbrances");
a61af66fc99e Initial load
duke
parents:
diff changeset
594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
595
a61af66fc99e Initial load
duke
parents:
diff changeset
596 assert(totalSize() >= retTC->size(), "Incorrect total size");
a61af66fc99e Initial load
duke
parents:
diff changeset
597 dec_totalSize(retTC->size()); // size book-keeping
a61af66fc99e Initial load
duke
parents:
diff changeset
598 assert(totalFreeBlocks() > 0, "Incorrect total count");
a61af66fc99e Initial load
duke
parents:
diff changeset
599 set_totalFreeBlocks(totalFreeBlocks() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
600
a61af66fc99e Initial load
duke
parents:
diff changeset
601 assert(retTC != NULL, "null chunk?");
a61af66fc99e Initial load
duke
parents:
diff changeset
602 assert(retTC->prev() == NULL && retTC->next() == NULL,
a61af66fc99e Initial load
duke
parents:
diff changeset
603 "should return without encumbrances");
a61af66fc99e Initial load
duke
parents:
diff changeset
604 if (FLSVerifyDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
605 verifyTree();
a61af66fc99e Initial load
duke
parents:
diff changeset
606 }
a61af66fc99e Initial load
duke
parents:
diff changeset
607 assert(!removing_only_chunk || _root == NULL, "root should be NULL");
a61af66fc99e Initial load
duke
parents:
diff changeset
608 return TreeChunk::as_TreeChunk(retTC);
a61af66fc99e Initial load
duke
parents:
diff changeset
609 }
a61af66fc99e Initial load
duke
parents:
diff changeset
610
a61af66fc99e Initial load
duke
parents:
diff changeset
611 // Remove the leftmost node (lm) in the tree and return it.
a61af66fc99e Initial load
duke
parents:
diff changeset
612 // If lm has a right child, link it to the left node of
a61af66fc99e Initial load
duke
parents:
diff changeset
613 // the parent of lm.
a61af66fc99e Initial load
duke
parents:
diff changeset
614 TreeList* BinaryTreeDictionary::removeTreeMinimum(TreeList* tl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
615 assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
a61af66fc99e Initial load
duke
parents:
diff changeset
616 // locate the subtree minimum by walking down left branches
a61af66fc99e Initial load
duke
parents:
diff changeset
617 TreeList* curTL = tl;
a61af66fc99e Initial load
duke
parents:
diff changeset
618 for (; curTL->left() != NULL; curTL = curTL->left());
a61af66fc99e Initial load
duke
parents:
diff changeset
619 // obviously curTL now has at most one child, a right child
a61af66fc99e Initial load
duke
parents:
diff changeset
620 if (curTL != root()) { // Should this test just be removed?
a61af66fc99e Initial load
duke
parents:
diff changeset
621 TreeList* parentTL = curTL->parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
622 if (parentTL->left() == curTL) { // curTL is a left child
a61af66fc99e Initial load
duke
parents:
diff changeset
623 parentTL->setLeft(curTL->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
624 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
625 // If the list tl has no left child, then curTL may be
a61af66fc99e Initial load
duke
parents:
diff changeset
626 // the right child of parentTL.
a61af66fc99e Initial load
duke
parents:
diff changeset
627 assert(parentTL->right() == curTL, "should be a right child");
a61af66fc99e Initial load
duke
parents:
diff changeset
628 parentTL->setRight(curTL->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
629 }
a61af66fc99e Initial load
duke
parents:
diff changeset
630 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
631 // The only use of this method would not pass the root of the
a61af66fc99e Initial load
duke
parents:
diff changeset
632 // tree (as indicated by the assertion above that the tree list
a61af66fc99e Initial load
duke
parents:
diff changeset
633 // has a parent) but the specification does not explicitly exclude the
a61af66fc99e Initial load
duke
parents:
diff changeset
634 // passing of the root so accomodate it.
a61af66fc99e Initial load
duke
parents:
diff changeset
635 set_root(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
636 }
a61af66fc99e Initial load
duke
parents:
diff changeset
637 debug_only(
a61af66fc99e Initial load
duke
parents:
diff changeset
638 curTL->clearParent(); // Test if this needs to be cleared
a61af66fc99e Initial load
duke
parents:
diff changeset
639 curTL->clearRight(); // recall, above, left child is already null
a61af66fc99e Initial load
duke
parents:
diff changeset
640 )
a61af66fc99e Initial load
duke
parents:
diff changeset
641 // we just excised a (non-root) node, we should still verify all tree invariants
a61af66fc99e Initial load
duke
parents:
diff changeset
642 if (FLSVerifyDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
643 verifyTree();
a61af66fc99e Initial load
duke
parents:
diff changeset
644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
645 return curTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
647
a61af66fc99e Initial load
duke
parents:
diff changeset
648 // Based on a simplification of the algorithm by Sleator and Tarjan (JACM 1985).
a61af66fc99e Initial load
duke
parents:
diff changeset
649 // The simplifications are the following:
a61af66fc99e Initial load
duke
parents:
diff changeset
650 // . we splay only when we delete (not when we insert)
a61af66fc99e Initial load
duke
parents:
diff changeset
651 // . we apply a single spay step per deletion/access
a61af66fc99e Initial load
duke
parents:
diff changeset
652 // By doing such partial splaying, we reduce the amount of restructuring,
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // while getting a reasonably efficient search tree (we think).
a61af66fc99e Initial load
duke
parents:
diff changeset
654 // [Measurements will be needed to (in)validate this expectation.]
a61af66fc99e Initial load
duke
parents:
diff changeset
655
a61af66fc99e Initial load
duke
parents:
diff changeset
656 void BinaryTreeDictionary::semiSplayStep(TreeList* tc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
657 // apply a semi-splay step at the given node:
a61af66fc99e Initial load
duke
parents:
diff changeset
658 // . if root, norting needs to be done
a61af66fc99e Initial load
duke
parents:
diff changeset
659 // . if child of root, splay once
a61af66fc99e Initial load
duke
parents:
diff changeset
660 // . else zig-zig or sig-zag depending on path from grandparent
a61af66fc99e Initial load
duke
parents:
diff changeset
661 if (root() == tc) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
662 warning("*** Splaying not yet implemented; "
a61af66fc99e Initial load
duke
parents:
diff changeset
663 "tree operations may be inefficient ***");
a61af66fc99e Initial load
duke
parents:
diff changeset
664 }
a61af66fc99e Initial load
duke
parents:
diff changeset
665
a61af66fc99e Initial load
duke
parents:
diff changeset
666 void BinaryTreeDictionary::insertChunkInTree(FreeChunk* fc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
667 TreeList *curTL, *prevTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
668 size_t size = fc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
669
a61af66fc99e Initial load
duke
parents:
diff changeset
670 assert(size >= MIN_TREE_CHUNK_SIZE, "too small to be a TreeList");
a61af66fc99e Initial load
duke
parents:
diff changeset
671 if (FLSVerifyDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
672 verifyTree();
a61af66fc99e Initial load
duke
parents:
diff changeset
673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
674 // XXX: do i need to clear the FreeChunk fields, let me do it just in case
a61af66fc99e Initial load
duke
parents:
diff changeset
675 // Revisit this later
a61af66fc99e Initial load
duke
parents:
diff changeset
676
a61af66fc99e Initial load
duke
parents:
diff changeset
677 fc->clearNext();
a61af66fc99e Initial load
duke
parents:
diff changeset
678 fc->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
679
a61af66fc99e Initial load
duke
parents:
diff changeset
680 // work down from the _root, looking for insertion point
a61af66fc99e Initial load
duke
parents:
diff changeset
681 for (prevTL = curTL = root(); curTL != NULL;) {
a61af66fc99e Initial load
duke
parents:
diff changeset
682 if (curTL->size() == size) // exact match
a61af66fc99e Initial load
duke
parents:
diff changeset
683 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
684 prevTL = curTL;
a61af66fc99e Initial load
duke
parents:
diff changeset
685 if (curTL->size() > size) { // follow left branch
a61af66fc99e Initial load
duke
parents:
diff changeset
686 curTL = curTL->left();
a61af66fc99e Initial load
duke
parents:
diff changeset
687 } else { // follow right branch
a61af66fc99e Initial load
duke
parents:
diff changeset
688 assert(curTL->size() < size, "size inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
689 curTL = curTL->right();
a61af66fc99e Initial load
duke
parents:
diff changeset
690 }
a61af66fc99e Initial load
duke
parents:
diff changeset
691 }
a61af66fc99e Initial load
duke
parents:
diff changeset
692 TreeChunk* tc = TreeChunk::as_TreeChunk(fc);
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
693 // This chunk is being returned to the binary tree. Its embedded
0
a61af66fc99e Initial load
duke
parents:
diff changeset
694 // TreeList should be unused at this point.
a61af66fc99e Initial load
duke
parents:
diff changeset
695 tc->initialize();
a61af66fc99e Initial load
duke
parents:
diff changeset
696 if (curTL != NULL) { // exact match
a61af66fc99e Initial load
duke
parents:
diff changeset
697 tc->set_list(curTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
698 curTL->returnChunkAtTail(tc);
a61af66fc99e Initial load
duke
parents:
diff changeset
699 } else { // need a new node in tree
a61af66fc99e Initial load
duke
parents:
diff changeset
700 tc->clearNext();
a61af66fc99e Initial load
duke
parents:
diff changeset
701 tc->linkPrev(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
702 TreeList* newTL = TreeList::as_TreeList(tc);
a61af66fc99e Initial load
duke
parents:
diff changeset
703 assert(((TreeChunk*)tc)->list() == newTL,
a61af66fc99e Initial load
duke
parents:
diff changeset
704 "List was not initialized correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
705 if (prevTL == NULL) { // we are the only tree node
a61af66fc99e Initial load
duke
parents:
diff changeset
706 assert(root() == NULL, "control point invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
707 set_root(newTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
708 } else { // insert under prevTL ...
a61af66fc99e Initial load
duke
parents:
diff changeset
709 if (prevTL->size() < size) { // am right child
a61af66fc99e Initial load
duke
parents:
diff changeset
710 assert(prevTL->right() == NULL, "control point invariant");
a61af66fc99e Initial load
duke
parents:
diff changeset
711 prevTL->setRight(newTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
712 } else { // am left child
a61af66fc99e Initial load
duke
parents:
diff changeset
713 assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
a61af66fc99e Initial load
duke
parents:
diff changeset
714 prevTL->setLeft(newTL);
a61af66fc99e Initial load
duke
parents:
diff changeset
715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
716 }
a61af66fc99e Initial load
duke
parents:
diff changeset
717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
718 assert(tc->list() != NULL, "Tree list should be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
719
a61af66fc99e Initial load
duke
parents:
diff changeset
720 inc_totalSize(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
721 // Method 'totalSizeInTree' walks through the every block in the
a61af66fc99e Initial load
duke
parents:
diff changeset
722 // tree, so it can cause significant performance loss if there are
a61af66fc99e Initial load
duke
parents:
diff changeset
723 // many blocks in the tree
a61af66fc99e Initial load
duke
parents:
diff changeset
724 assert(!FLSVerifyDictionary || totalSizeInTree(root()) == totalSize(), "_totalSize inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
725 set_totalFreeBlocks(totalFreeBlocks() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
726 if (FLSVerifyDictionary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
727 verifyTree();
a61af66fc99e Initial load
duke
parents:
diff changeset
728 }
a61af66fc99e Initial load
duke
parents:
diff changeset
729 }
a61af66fc99e Initial load
duke
parents:
diff changeset
730
a61af66fc99e Initial load
duke
parents:
diff changeset
731 size_t BinaryTreeDictionary::maxChunkSize() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
732 verify_par_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
733 TreeList* tc = root();
a61af66fc99e Initial load
duke
parents:
diff changeset
734 if (tc == NULL) return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
735 for (; tc->right() != NULL; tc = tc->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
736 return tc->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
737 }
a61af66fc99e Initial load
duke
parents:
diff changeset
738
a61af66fc99e Initial load
duke
parents:
diff changeset
739 size_t BinaryTreeDictionary::totalListLength(TreeList* tl) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
740 size_t res;
a61af66fc99e Initial load
duke
parents:
diff changeset
741 res = tl->count();
a61af66fc99e Initial load
duke
parents:
diff changeset
742 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
743 size_t cnt;
a61af66fc99e Initial load
duke
parents:
diff changeset
744 FreeChunk* tc = tl->head();
a61af66fc99e Initial load
duke
parents:
diff changeset
745 for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
a61af66fc99e Initial load
duke
parents:
diff changeset
746 assert(res == cnt, "The count is not being maintained correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
747 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
748 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
749 }
a61af66fc99e Initial load
duke
parents:
diff changeset
750
a61af66fc99e Initial load
duke
parents:
diff changeset
751 size_t BinaryTreeDictionary::totalSizeInTree(TreeList* tl) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
752 if (tl == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
753 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
754 return (tl->size() * totalListLength(tl)) +
a61af66fc99e Initial load
duke
parents:
diff changeset
755 totalSizeInTree(tl->left()) +
a61af66fc99e Initial load
duke
parents:
diff changeset
756 totalSizeInTree(tl->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
757 }
a61af66fc99e Initial load
duke
parents:
diff changeset
758
a61af66fc99e Initial load
duke
parents:
diff changeset
759 double BinaryTreeDictionary::sum_of_squared_block_sizes(TreeList* const tl) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
760 if (tl == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
761 return 0.0;
a61af66fc99e Initial load
duke
parents:
diff changeset
762 }
a61af66fc99e Initial load
duke
parents:
diff changeset
763 double size = (double)(tl->size());
a61af66fc99e Initial load
duke
parents:
diff changeset
764 double curr = size * size * totalListLength(tl);
a61af66fc99e Initial load
duke
parents:
diff changeset
765 curr += sum_of_squared_block_sizes(tl->left());
a61af66fc99e Initial load
duke
parents:
diff changeset
766 curr += sum_of_squared_block_sizes(tl->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
767 return curr;
a61af66fc99e Initial load
duke
parents:
diff changeset
768 }
a61af66fc99e Initial load
duke
parents:
diff changeset
769
a61af66fc99e Initial load
duke
parents:
diff changeset
770 size_t BinaryTreeDictionary::totalFreeBlocksInTree(TreeList* tl) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
771 if (tl == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
772 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
773 return totalListLength(tl) +
a61af66fc99e Initial load
duke
parents:
diff changeset
774 totalFreeBlocksInTree(tl->left()) +
a61af66fc99e Initial load
duke
parents:
diff changeset
775 totalFreeBlocksInTree(tl->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
776 }
a61af66fc99e Initial load
duke
parents:
diff changeset
777
a61af66fc99e Initial load
duke
parents:
diff changeset
778 size_t BinaryTreeDictionary::numFreeBlocks() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
779 assert(totalFreeBlocksInTree(root()) == totalFreeBlocks(),
a61af66fc99e Initial load
duke
parents:
diff changeset
780 "_totalFreeBlocks inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
781 return totalFreeBlocks();
a61af66fc99e Initial load
duke
parents:
diff changeset
782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
783
a61af66fc99e Initial load
duke
parents:
diff changeset
784 size_t BinaryTreeDictionary::treeHeightHelper(TreeList* tl) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
785 if (tl == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
786 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
787 return 1 + MAX2(treeHeightHelper(tl->left()),
a61af66fc99e Initial load
duke
parents:
diff changeset
788 treeHeightHelper(tl->right()));
a61af66fc99e Initial load
duke
parents:
diff changeset
789 }
a61af66fc99e Initial load
duke
parents:
diff changeset
790
a61af66fc99e Initial load
duke
parents:
diff changeset
791 size_t BinaryTreeDictionary::treeHeight() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
792 return treeHeightHelper(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
793 }
a61af66fc99e Initial load
duke
parents:
diff changeset
794
a61af66fc99e Initial load
duke
parents:
diff changeset
795 size_t BinaryTreeDictionary::totalNodesHelper(TreeList* tl) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
796 if (tl == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
797 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
798 }
a61af66fc99e Initial load
duke
parents:
diff changeset
799 return 1 + totalNodesHelper(tl->left()) +
a61af66fc99e Initial load
duke
parents:
diff changeset
800 totalNodesHelper(tl->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
801 }
a61af66fc99e Initial load
duke
parents:
diff changeset
802
a61af66fc99e Initial load
duke
parents:
diff changeset
803 size_t BinaryTreeDictionary::totalNodesInTree(TreeList* tl) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
804 return totalNodesHelper(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
805 }
a61af66fc99e Initial load
duke
parents:
diff changeset
806
a61af66fc99e Initial load
duke
parents:
diff changeset
807 void BinaryTreeDictionary::dictCensusUpdate(size_t size, bool split, bool birth){
a61af66fc99e Initial load
duke
parents:
diff changeset
808 TreeList* nd = findList(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
809 if (nd) {
a61af66fc99e Initial load
duke
parents:
diff changeset
810 if (split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
811 if (birth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
812 nd->increment_splitBirths();
a61af66fc99e Initial load
duke
parents:
diff changeset
813 nd->increment_surplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
814 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
815 nd->increment_splitDeaths();
a61af66fc99e Initial load
duke
parents:
diff changeset
816 nd->decrement_surplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
818 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
819 if (birth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
820 nd->increment_coalBirths();
a61af66fc99e Initial load
duke
parents:
diff changeset
821 nd->increment_surplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
822 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
823 nd->increment_coalDeaths();
a61af66fc99e Initial load
duke
parents:
diff changeset
824 nd->decrement_surplus();
a61af66fc99e Initial load
duke
parents:
diff changeset
825 }
a61af66fc99e Initial load
duke
parents:
diff changeset
826 }
a61af66fc99e Initial load
duke
parents:
diff changeset
827 }
a61af66fc99e Initial load
duke
parents:
diff changeset
828 // A list for this size may not be found (nd == 0) if
a61af66fc99e Initial load
duke
parents:
diff changeset
829 // This is a death where the appropriate list is now
a61af66fc99e Initial load
duke
parents:
diff changeset
830 // empty and has been removed from the list.
a61af66fc99e Initial load
duke
parents:
diff changeset
831 // This is a birth associated with a LinAB. The chunk
a61af66fc99e Initial load
duke
parents:
diff changeset
832 // for the LinAB is not in the dictionary.
a61af66fc99e Initial load
duke
parents:
diff changeset
833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
834
a61af66fc99e Initial load
duke
parents:
diff changeset
835 bool BinaryTreeDictionary::coalDictOverPopulated(size_t size) {
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
836 if (FLSAlwaysCoalesceLarge) return true;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
837
0
a61af66fc99e Initial load
duke
parents:
diff changeset
838 TreeList* list_of_size = findList(size);
a61af66fc99e Initial load
duke
parents:
diff changeset
839 // None of requested size implies overpopulated.
a61af66fc99e Initial load
duke
parents:
diff changeset
840 return list_of_size == NULL || list_of_size->coalDesired() <= 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
841 list_of_size->count() > list_of_size->coalDesired();
a61af66fc99e Initial load
duke
parents:
diff changeset
842 }
a61af66fc99e Initial load
duke
parents:
diff changeset
843
a61af66fc99e Initial load
duke
parents:
diff changeset
844 // Closures for walking the binary tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
845 // do_list() walks the free list in a node applying the closure
a61af66fc99e Initial load
duke
parents:
diff changeset
846 // to each free chunk in the list
a61af66fc99e Initial load
duke
parents:
diff changeset
847 // do_tree() walks the nodes in the binary tree applying do_list()
a61af66fc99e Initial load
duke
parents:
diff changeset
848 // to each list at each node.
a61af66fc99e Initial load
duke
parents:
diff changeset
849
a61af66fc99e Initial load
duke
parents:
diff changeset
850 class TreeCensusClosure : public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
851 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
852 virtual void do_list(FreeList* fl) = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
853 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
854 virtual void do_tree(TreeList* tl) = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
855 };
a61af66fc99e Initial load
duke
parents:
diff changeset
856
a61af66fc99e Initial load
duke
parents:
diff changeset
857 class AscendTreeCensusClosure : public TreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
858 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
859 void do_tree(TreeList* tl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
860 if (tl != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
861 do_tree(tl->left());
a61af66fc99e Initial load
duke
parents:
diff changeset
862 do_list(tl);
a61af66fc99e Initial load
duke
parents:
diff changeset
863 do_tree(tl->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
864 }
a61af66fc99e Initial load
duke
parents:
diff changeset
865 }
a61af66fc99e Initial load
duke
parents:
diff changeset
866 };
a61af66fc99e Initial load
duke
parents:
diff changeset
867
a61af66fc99e Initial load
duke
parents:
diff changeset
868 class DescendTreeCensusClosure : public TreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
869 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
870 void do_tree(TreeList* tl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
871 if (tl != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
872 do_tree(tl->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
873 do_list(tl);
a61af66fc99e Initial load
duke
parents:
diff changeset
874 do_tree(tl->left());
a61af66fc99e Initial load
duke
parents:
diff changeset
875 }
a61af66fc99e Initial load
duke
parents:
diff changeset
876 }
a61af66fc99e Initial load
duke
parents:
diff changeset
877 };
a61af66fc99e Initial load
duke
parents:
diff changeset
878
a61af66fc99e Initial load
duke
parents:
diff changeset
879 // For each list in the tree, calculate the desired, desired
a61af66fc99e Initial load
duke
parents:
diff changeset
880 // coalesce, count before sweep, and surplus before sweep.
a61af66fc99e Initial load
duke
parents:
diff changeset
881 class BeginSweepClosure : public AscendTreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
882 double _percentage;
a61af66fc99e Initial load
duke
parents:
diff changeset
883 float _inter_sweep_current;
a61af66fc99e Initial load
duke
parents:
diff changeset
884 float _inter_sweep_estimate;
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
885 float _intra_sweep_estimate;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
886
a61af66fc99e Initial load
duke
parents:
diff changeset
887 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
888 BeginSweepClosure(double p, float inter_sweep_current,
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
889 float inter_sweep_estimate,
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
890 float intra_sweep_estimate) :
0
a61af66fc99e Initial load
duke
parents:
diff changeset
891 _percentage(p),
a61af66fc99e Initial load
duke
parents:
diff changeset
892 _inter_sweep_current(inter_sweep_current),
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
893 _inter_sweep_estimate(inter_sweep_estimate),
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
894 _intra_sweep_estimate(intra_sweep_estimate) { }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
895
a61af66fc99e Initial load
duke
parents:
diff changeset
896 void do_list(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
897 double coalSurplusPercent = _percentage;
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
898 fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
899 fl->set_coalDesired((ssize_t)((double)fl->desired() * coalSurplusPercent));
a61af66fc99e Initial load
duke
parents:
diff changeset
900 fl->set_beforeSweep(fl->count());
a61af66fc99e Initial load
duke
parents:
diff changeset
901 fl->set_bfrSurp(fl->surplus());
a61af66fc99e Initial load
duke
parents:
diff changeset
902 }
a61af66fc99e Initial load
duke
parents:
diff changeset
903 };
a61af66fc99e Initial load
duke
parents:
diff changeset
904
a61af66fc99e Initial load
duke
parents:
diff changeset
905 // Used to search the tree until a condition is met.
a61af66fc99e Initial load
duke
parents:
diff changeset
906 // Similar to TreeCensusClosure but searches the
a61af66fc99e Initial load
duke
parents:
diff changeset
907 // tree and returns promptly when found.
a61af66fc99e Initial load
duke
parents:
diff changeset
908
a61af66fc99e Initial load
duke
parents:
diff changeset
909 class TreeSearchClosure : public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
910 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
911 virtual bool do_list(FreeList* fl) = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
912 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
913 virtual bool do_tree(TreeList* tl) = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
914 };
a61af66fc99e Initial load
duke
parents:
diff changeset
915
a61af66fc99e Initial load
duke
parents:
diff changeset
916 #if 0 // Don't need this yet but here for symmetry.
a61af66fc99e Initial load
duke
parents:
diff changeset
917 class AscendTreeSearchClosure : public TreeSearchClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
918 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
919 bool do_tree(TreeList* tl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
920 if (tl != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
921 if (do_tree(tl->left())) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
922 if (do_list(tl)) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
923 if (do_tree(tl->right())) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
924 }
a61af66fc99e Initial load
duke
parents:
diff changeset
925 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
926 }
a61af66fc99e Initial load
duke
parents:
diff changeset
927 };
a61af66fc99e Initial load
duke
parents:
diff changeset
928 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
929
a61af66fc99e Initial load
duke
parents:
diff changeset
930 class DescendTreeSearchClosure : public TreeSearchClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
931 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
932 bool do_tree(TreeList* tl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
933 if (tl != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
934 if (do_tree(tl->right())) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
935 if (do_list(tl)) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
936 if (do_tree(tl->left())) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
938 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
939 }
a61af66fc99e Initial load
duke
parents:
diff changeset
940 };
a61af66fc99e Initial load
duke
parents:
diff changeset
941
a61af66fc99e Initial load
duke
parents:
diff changeset
942 // Searches the tree for a chunk that ends at the
a61af66fc99e Initial load
duke
parents:
diff changeset
943 // specified address.
a61af66fc99e Initial load
duke
parents:
diff changeset
944 class EndTreeSearchClosure : public DescendTreeSearchClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
945 HeapWord* _target;
a61af66fc99e Initial load
duke
parents:
diff changeset
946 FreeChunk* _found;
a61af66fc99e Initial load
duke
parents:
diff changeset
947
a61af66fc99e Initial load
duke
parents:
diff changeset
948 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
949 EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
950 bool do_list(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
951 FreeChunk* item = fl->head();
a61af66fc99e Initial load
duke
parents:
diff changeset
952 while (item != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
953 if (item->end() == _target) {
a61af66fc99e Initial load
duke
parents:
diff changeset
954 _found = item;
a61af66fc99e Initial load
duke
parents:
diff changeset
955 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
956 }
a61af66fc99e Initial load
duke
parents:
diff changeset
957 item = item->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
958 }
a61af66fc99e Initial load
duke
parents:
diff changeset
959 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
960 }
a61af66fc99e Initial load
duke
parents:
diff changeset
961 FreeChunk* found() { return _found; }
a61af66fc99e Initial load
duke
parents:
diff changeset
962 };
a61af66fc99e Initial load
duke
parents:
diff changeset
963
a61af66fc99e Initial load
duke
parents:
diff changeset
964 FreeChunk* BinaryTreeDictionary::find_chunk_ends_at(HeapWord* target) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
965 EndTreeSearchClosure etsc(target);
a61af66fc99e Initial load
duke
parents:
diff changeset
966 bool found_target = etsc.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
967 assert(found_target || etsc.found() == NULL, "Consistency check");
a61af66fc99e Initial load
duke
parents:
diff changeset
968 assert(!found_target || etsc.found() != NULL, "Consistency check");
a61af66fc99e Initial load
duke
parents:
diff changeset
969 return etsc.found();
a61af66fc99e Initial load
duke
parents:
diff changeset
970 }
a61af66fc99e Initial load
duke
parents:
diff changeset
971
a61af66fc99e Initial load
duke
parents:
diff changeset
972 void BinaryTreeDictionary::beginSweepDictCensus(double coalSurplusPercent,
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
973 float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
974 BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current,
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
975 inter_sweep_estimate,
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
976 intra_sweep_estimate);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
977 bsc.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
978 }
a61af66fc99e Initial load
duke
parents:
diff changeset
979
a61af66fc99e Initial load
duke
parents:
diff changeset
980 // Closures and methods for calculating total bytes returned to the
a61af66fc99e Initial load
duke
parents:
diff changeset
981 // free lists in the tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
982 NOT_PRODUCT(
a61af66fc99e Initial load
duke
parents:
diff changeset
983 class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
984 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
985 void do_list(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
986 fl->set_returnedBytes(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
987 }
a61af66fc99e Initial load
duke
parents:
diff changeset
988 };
a61af66fc99e Initial load
duke
parents:
diff changeset
989
a61af66fc99e Initial load
duke
parents:
diff changeset
990 void BinaryTreeDictionary::initializeDictReturnedBytes() {
a61af66fc99e Initial load
duke
parents:
diff changeset
991 InitializeDictReturnedBytesClosure idrb;
a61af66fc99e Initial load
duke
parents:
diff changeset
992 idrb.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
993 }
a61af66fc99e Initial load
duke
parents:
diff changeset
994
a61af66fc99e Initial load
duke
parents:
diff changeset
995 class ReturnedBytesClosure : public AscendTreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
996 size_t _dictReturnedBytes;
a61af66fc99e Initial load
duke
parents:
diff changeset
997 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
998 ReturnedBytesClosure() { _dictReturnedBytes = 0; }
a61af66fc99e Initial load
duke
parents:
diff changeset
999 void do_list(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 _dictReturnedBytes += fl->returnedBytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 size_t dictReturnedBytes() { return _dictReturnedBytes; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1004
a61af66fc99e Initial load
duke
parents:
diff changeset
1005 size_t BinaryTreeDictionary::sumDictReturnedBytes() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 ReturnedBytesClosure rbc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 rbc.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1008
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 return rbc.dictReturnedBytes();
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1011
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 // Count the number of entries in the tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 class treeCountClosure : public DescendTreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 uint count;
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 treeCountClosure(uint c) { count = c; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 void do_list(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1021
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 size_t BinaryTreeDictionary::totalCount() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 treeCountClosure ctc(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1024 ctc.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 return ctc.count;
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 )
a61af66fc99e Initial load
duke
parents:
diff changeset
1028
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 // Calculate surpluses for the lists in the tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 class setTreeSurplusClosure : public AscendTreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
1031 double percentage;
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 setTreeSurplusClosure(double v) { percentage = v; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 void do_list(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 double splitSurplusPercent = percentage;
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 fl->set_surplus(fl->count() -
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 (ssize_t)((double)fl->desired() * splitSurplusPercent));
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1039 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1040
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 void BinaryTreeDictionary::setTreeSurplus(double splitSurplusPercent) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 setTreeSurplusClosure sts(splitSurplusPercent);
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 sts.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1044 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1045
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 // Set hints for the lists in the tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 class setTreeHintsClosure : public DescendTreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
1048 size_t hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 setTreeHintsClosure(size_t v) { hint = v; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1051 void do_list(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 fl->set_hint(hint);
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 assert(fl->hint() == 0 || fl->hint() > fl->size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 "Current hint is inconsistent");
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 if (fl->surplus() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1056 hint = fl->size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1057 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1058 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1060
a61af66fc99e Initial load
duke
parents:
diff changeset
1061 void BinaryTreeDictionary::setTreeHints(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 setTreeHintsClosure sth(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1063 sth.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1064 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1065
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 // Save count before previous sweep and splits and coalesces.
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 class clearTreeCensusClosure : public AscendTreeCensusClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
1068 void do_list(FreeList* fl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 fl->set_prevSweep(fl->count());
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 fl->set_coalBirths(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1071 fl->set_coalDeaths(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 fl->set_splitBirths(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 fl->set_splitDeaths(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1075 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1076
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 void BinaryTreeDictionary::clearTreeCensus(void) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 clearTreeCensusClosure ctc;
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 ctc.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1081
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 // Do reporting and post sweep clean up.
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 void BinaryTreeDictionary::endSweepDictCensus(double splitSurplusPercent) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 // Does walking the tree 3 times hurt?
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 setTreeSurplus(splitSurplusPercent);
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 setTreeHints();
a61af66fc99e Initial load
duke
parents:
diff changeset
1087 if (PrintGC && Verbose) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1088 reportStatistics();
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 clearTreeCensus();
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1092
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 // Print summary statistics
a61af66fc99e Initial load
duke
parents:
diff changeset
1094 void BinaryTreeDictionary::reportStatistics() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1095 verify_par_locked();
a61af66fc99e Initial load
duke
parents:
diff changeset
1096 gclog_or_tty->print("Statistics for BinaryTreeDictionary:\n"
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 "------------------------------------\n");
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 size_t totalSize = totalChunkSize(debug_only(NULL));
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 size_t freeBlocks = numFreeBlocks();
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 gclog_or_tty->print("Total Free Space: %d\n", totalSize);
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 gclog_or_tty->print("Max Chunk Size: %d\n", maxChunkSize());
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 gclog_or_tty->print("Number of Blocks: %d\n", freeBlocks);
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 if (freeBlocks > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 gclog_or_tty->print("Av. Block Size: %d\n", totalSize/freeBlocks);
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 gclog_or_tty->print("Tree Height: %d\n", treeHeight());
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1108
a61af66fc99e Initial load
duke
parents:
diff changeset
1109 // Print census information - counts, births, deaths, etc.
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 // for each list in the tree. Also print some summary
a61af66fc99e Initial load
duke
parents:
diff changeset
1111 // information.
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1112 class PrintTreeCensusClosure : public AscendTreeCensusClosure {
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1113 int _print_line;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 size_t _totalFree;
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1115 FreeList _total;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1116
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 public:
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1118 PrintTreeCensusClosure() {
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1119 _print_line = 0;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 _totalFree = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 }
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1122 FreeList* total() { return &_total; }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 size_t totalFree() { return _totalFree; }
a61af66fc99e Initial load
duke
parents:
diff changeset
1124 void do_list(FreeList* fl) {
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1125 if (++_print_line >= 40) {
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1126 FreeList::print_labels_on(gclog_or_tty, "size");
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1127 _print_line = 0;
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1128 }
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1129 fl->print_on(gclog_or_tty);
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1130 _totalFree += fl->count() * fl->size() ;
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1131 total()->set_count( total()->count() + fl->count() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1132 total()->set_bfrSurp( total()->bfrSurp() + fl->bfrSurp() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1133 total()->set_surplus( total()->splitDeaths() + fl->surplus() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1134 total()->set_desired( total()->desired() + fl->desired() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1135 total()->set_prevSweep( total()->prevSweep() + fl->prevSweep() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1136 total()->set_beforeSweep(total()->beforeSweep() + fl->beforeSweep());
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1137 total()->set_coalBirths( total()->coalBirths() + fl->coalBirths() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1138 total()->set_coalDeaths( total()->coalDeaths() + fl->coalDeaths() );
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1139 total()->set_splitBirths(total()->splitBirths() + fl->splitBirths());
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1140 total()->set_splitDeaths(total()->splitDeaths() + fl->splitDeaths());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1141 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1142 };
a61af66fc99e Initial load
duke
parents:
diff changeset
1143
a61af66fc99e Initial load
duke
parents:
diff changeset
1144 void BinaryTreeDictionary::printDictCensus(void) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1145
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 gclog_or_tty->print("\nBinaryTree\n");
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1147 FreeList::print_labels_on(gclog_or_tty, "size");
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1148 PrintTreeCensusClosure ptc;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 ptc.do_tree(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1150
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1151 FreeList* total = ptc.total();
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1152 FreeList::print_labels_on(gclog_or_tty, " ");
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1153 total->print_on(gclog_or_tty, "TOTAL\t");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 gclog_or_tty->print(
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1155 "totalFree(words): " SIZE_FORMAT_W(16)
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1156 " growth: %8.5f deficit: %8.5f\n",
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 ptc.totalFree(),
12
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1158 (double)(total->splitBirths() + total->coalBirths()
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1159 - total->splitDeaths() - total->coalDeaths())
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1160 /(total->prevSweep() != 0 ? (double)total->prevSweep() : 1.0),
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1161 (double)(total->desired() - total->count())
6432c3bb6240 6668743: CMS: Consolidate block statistics reporting code
ysr
parents: 0
diff changeset
1162 /(total->desired() != 0 ? (double)total->desired() : 1.0));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1164
1145
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1165 class PrintFreeListsClosure : public AscendTreeCensusClosure {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1166 outputStream* _st;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1167 int _print_line;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1168
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1169 public:
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1170 PrintFreeListsClosure(outputStream* st) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1171 _st = st;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1172 _print_line = 0;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1173 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1174 void do_list(FreeList* fl) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1175 if (++_print_line >= 40) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1176 FreeList::print_labels_on(_st, "size");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1177 _print_line = 0;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1178 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1179 fl->print_on(gclog_or_tty);
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1180 size_t sz = fl->size();
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1181 for (FreeChunk* fc = fl->head(); fc != NULL;
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1182 fc = fc->next()) {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1183 _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ") %s",
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1184 fc, (HeapWord*)fc + sz,
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1185 fc->cantCoalesce() ? "\t CC" : "");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1186 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1187 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1188 };
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1189
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1190 void BinaryTreeDictionary::print_free_lists(outputStream* st) const {
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1191
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1192 FreeList::print_labels_on(st, "size");
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1193 PrintFreeListsClosure pflc(st);
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1194 pflc.do_tree(root());
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1195 }
e018e6884bd8 6631166: CMS: better heuristics when combatting fragmentation
ysr
parents: 269
diff changeset
1196
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1197 // Verify the following tree invariants:
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 // . _root has no parent
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 // . parent and child point to each other
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 // . each node's key correctly related to that of its child(ren)
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 void BinaryTreeDictionary::verifyTree() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1202 guarantee(root() == NULL || totalFreeBlocks() == 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 totalSize() != 0, "_totalSize should't be 0?");
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 verifyTreeHelper(root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1207
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 size_t BinaryTreeDictionary::verifyPrevFreePtrs(TreeList* tl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 size_t ct = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 for (FreeChunk* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 ct++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1212 assert(curFC->prev() == NULL || curFC->prev()->isFree(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 "Chunk should be free");
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 return ct;
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1217
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 // Note: this helper is recursive rather than iterative, so use with
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 // caution on very deep trees; and watch out for stack overflow errors;
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 // In general, to be used only for debugging.
a61af66fc99e Initial load
duke
parents:
diff changeset
1221 void BinaryTreeDictionary::verifyTreeHelper(TreeList* tl) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 if (tl == NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 guarantee(tl->size() != 0, "A list must has a size");
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 guarantee(tl->left() == NULL || tl->left()->parent() == tl,
a61af66fc99e Initial load
duke
parents:
diff changeset
1226 "parent<-/->left");
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 guarantee(tl->right() == NULL || tl->right()->parent() == tl,
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 "parent<-/->right");;
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 guarantee(tl->left() == NULL || tl->left()->size() < tl->size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 "parent !> left");
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 guarantee(tl->right() == NULL || tl->right()->size() > tl->size(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 "parent !< left");
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 guarantee(tl->head() == NULL || tl->head()->isFree(), "!Free");
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 guarantee(tl->head() == NULL || tl->head_as_TreeChunk()->list() == tl,
a61af66fc99e Initial load
duke
parents:
diff changeset
1235 "list inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 guarantee(tl->count() > 0 || (tl->head() == NULL && tl->tail() == NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 "list count is inconsistent");
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 guarantee(tl->count() > 1 || tl->head() == tl->tail(),
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 "list is incorrectly constructed");
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 size_t count = verifyPrevFreePtrs(tl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 guarantee(count == (size_t)tl->count(), "Node count is incorrect");
a61af66fc99e Initial load
duke
parents:
diff changeset
1242 if (tl->head() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 tl->head_as_TreeChunk()->verifyTreeChunkList();
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 verifyTreeHelper(tl->left());
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 verifyTreeHelper(tl->right());
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1248
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 void BinaryTreeDictionary::verify() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 verifyTree();
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 guarantee(totalSize() == totalSizeInTree(root()), "Total Size inconsistency");
a61af66fc99e Initial load
duke
parents:
diff changeset
1252 }