annotate src/share/vm/gc_implementation/concurrentMarkSweep/binaryTreeDictionary.cpp @ 452:00b023ae2d78

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