aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatt Armstrong2022-10-08 19:53:36 -0700
committerMatt Armstrong2022-10-08 20:37:28 -0700
commitfe14454101cfd9951b76549773645b2ffeed66bd (patch)
treed602c057fdd45b5393daf9832f98f1a18b72aceb /src
parent92a0bf6ce2d2afe909d8a075ad9760eb003a8e73 (diff)
downloademacs-fe14454101cfd9951b76549773645b2ffeed66bd.tar.gz
emacs-fe14454101cfd9951b76549773645b2ffeed66bd.zip
Debug check overlay tree invariants
* src/itree.c (check_tree): (recurse_check_tree): new functions. (interval_tree_insert): call them. (interval_tree_remove): ditto. (interval_tree_insert_fix): ditto.
Diffstat (limited to 'src')
-rw-r--r--src/itree.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/src/itree.c b/src/itree.c
index 05851007f5a..4ad47b2e3fa 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -204,7 +204,67 @@ itree_init (void)
204 iter = interval_generator_create (NULL); 204 iter = interval_generator_create (NULL);
205} 205}
206 206
207 207static ptrdiff_t
208recurse_check_tree (struct interval_node *node, uintmax_t tree_otick,
209 ptrdiff_t offset, ptrdiff_t min_begin,
210 ptrdiff_t max_begin, intmax_t *size)
211{
212 if (node == ITREE_NULL)
213 return PTRDIFF_MIN;
214 ++*size;
215
216 /* Validate structure. */
217 eassert (
218 node->parent == ITREE_NULL
219 || (node->parent->left == node || node->parent->right == node));
220 eassert (node->left == ITREE_NULL || node->left->parent == node);
221 eassert (node->right == ITREE_NULL || node->right->parent == node);
222
223 /* Red nodes cannot have red parents. */
224 eassert (node->parent == ITREE_NULL
225 || !(node->red && node->parent->red));
226
227 eassert (node->offset == 0 || node->otick < tree_otick);
228
229 offset += node->offset;
230 ptrdiff_t begin = node->begin + offset;
231 ptrdiff_t end = node->end + offset;
232 ptrdiff_t limit = node->limit + offset;
233
234 eassert (min_begin <= max_begin);
235 eassert (min_begin <= begin);
236 eassert (begin <= max_begin);
237 eassert (end <= limit);
238
239 ptrdiff_t left_limit
240 = recurse_check_tree (node->left, tree_otick, offset, min_begin,
241 begin, size);
242 ptrdiff_t right_limit
243 = recurse_check_tree (node->right, tree_otick, offset, begin,
244 max_begin, size);
245 eassert (left_limit <= limit);
246 eassert (right_limit <= limit);
247 eassert (limit == max (end, max (left_limit, right_limit)));
248 return limit;
249}
250
251static bool
252check_tree (struct interval_tree *tree)
253{
254 eassert (tree != NULL);
255 eassert ((tree->size == 0) == (tree->root == ITREE_NULL));
256 if (tree->root == ITREE_NULL)
257 return true;
258
259 intmax_t size = 0;
260 ptrdiff_t offset = tree->root->offset;
261 ptrdiff_t limit
262 = recurse_check_tree (tree->root, tree->otick, offset,
263 PTRDIFF_MIN, PTRDIFF_MAX, &size);
264 eassert (limit == tree->root->limit + offset);
265 return true;
266}
267
208/* +===================================================================================+ 268/* +===================================================================================+
209 * | Stack 269 * | Stack
210 * +===================================================================================+ */ 270 * +===================================================================================+ */
@@ -429,6 +489,7 @@ void
429interval_tree_insert (struct interval_tree *tree, struct interval_node *node) 489interval_tree_insert (struct interval_tree *tree, struct interval_node *node)
430{ 490{
431 eassert (node && node->begin <= node->end && node != ITREE_NULL); 491 eassert (node && node->begin <= node->end && node != ITREE_NULL);
492 eassert (check_tree (tree));
432 493
433 struct interval_node *parent = ITREE_NULL; 494 struct interval_node *parent = ITREE_NULL;
434 struct interval_node *child = tree->root; 495 struct interval_node *child = tree->root;
@@ -468,6 +529,7 @@ interval_tree_insert (struct interval_tree *tree, struct interval_node *node)
468 /* Fix/update the tree */ 529 /* Fix/update the tree */
469 ++tree->size; 530 ++tree->size;
470 interval_tree_insert_fix (tree, node); 531 interval_tree_insert_fix (tree, node);
532 eassert (check_tree (tree));
471} 533}
472 534
473/* Return true, if NODE is a member of TREE. */ 535/* Return true, if NODE is a member of TREE. */
@@ -632,6 +694,7 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
632{ 694{
633 /* eassert (itree_limits_are_stable (tree->root)); */ 695 /* eassert (itree_limits_are_stable (tree->root)); */
634 eassert (interval_tree_contains (tree, node)); 696 eassert (interval_tree_contains (tree, node));
697 eassert (check_tree (tree));
635 698
636 /* `broken`, if non-NULL, holds a node that's being moved up to where a black 699 /* `broken`, if non-NULL, holds a node that's being moved up to where a black
637 node used to be, which may thus require further fixups in its parents 700 node used to be, which may thus require further fixups in its parents
@@ -708,6 +771,7 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
708 771
709 eassert ((tree->size == 0) == (tree->root == ITREE_NULL)); 772 eassert ((tree->size == 0) == (tree->root == ITREE_NULL));
710 /* eassert (itree_limits_are_stable (tree->root)); */ 773 /* eassert (itree_limits_are_stable (tree->root)); */
774 eassert (check_tree (tree));
711 775
712 return node; 776 return node;
713} 777}
@@ -1277,6 +1341,7 @@ interval_tree_insert_fix (struct interval_tree *tree, struct interval_node *node
1277 /* The root may have been changed to red due to the algorithm. Set 1341 /* The root may have been changed to red due to the algorithm. Set
1278 it to black so that property #5 is satisfied. */ 1342 it to black so that property #5 is satisfied. */
1279 tree->root->red = false; 1343 tree->root->red = false;
1344 eassert (check_tree (tree));
1280} 1345}
1281 1346
1282/* Return accumulated offsets of NODE's parents. */ 1347/* Return accumulated offsets of NODE's parents. */