diff options
| author | Matt Armstrong | 2022-10-08 19:53:36 -0700 |
|---|---|---|
| committer | Matt Armstrong | 2022-10-08 20:37:28 -0700 |
| commit | fe14454101cfd9951b76549773645b2ffeed66bd (patch) | |
| tree | d602c057fdd45b5393daf9832f98f1a18b72aceb /src | |
| parent | 92a0bf6ce2d2afe909d8a075ad9760eb003a8e73 (diff) | |
| download | emacs-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.c | 67 |
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 | 207 | static ptrdiff_t | |
| 208 | recurse_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 | |||
| 251 | static bool | ||
| 252 | check_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 | |||
| 429 | interval_tree_insert (struct interval_tree *tree, struct interval_node *node) | 489 | interval_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. */ |