aboutsummaryrefslogtreecommitdiffstats
path: root/src/itree.c
diff options
context:
space:
mode:
authorStefan Monnier2022-10-09 19:45:26 -0400
committerStefan Monnier2022-10-09 19:45:26 -0400
commit7cbeeabc7e6271948e7bb93020c2e4e50c65f384 (patch)
tree777b281d62878ab7cc5a12b7e3fbc8952bf95dbc /src/itree.c
parent4f3f7aebc957732f4fbe5c799da5367f46607680 (diff)
downloademacs-7cbeeabc7e6271948e7bb93020c2e4e50c65f384.tar.gz
emacs-7cbeeabc7e6271948e7bb93020c2e4e50c65f384.zip
Tighten up handling of `otick`
Move args between `build_overlay` and `add_buffer_overlay`, to try and keep buffer positions together with their buffer. Be more strict in the `otick` values passed to `interval_tree_insert`. Move a few things around to try and reduce dependencies through `.h` files. Fix a thinko bug in `check_tree`. * src/alloc.c (build_overlay): Remove `begin` and `end` args. * src/buffer.c (add_buffer_overlay): Move from `buffer.h`. Add `begin` and `end` args. (copy_overlays): Adjust accordingly. (Fmake_overlay): Use BUF_BEG and BUF_Z; adjust call to `build_overlay` and `add_buffer_overlay`. (Fmove_overlay): Use BUF_BEG and BUF_Z; Use the new `begin` and `end` args of `add_buffer_overlay` so we don't need to use `interval_node_set_region` when moving to a new buffer. (remove_buffer_overlay, set_overlay_region): Move from `buffer.h`. * src/buffer.h (set_overlay_region, add_buffer_overlay) (remove_buffer_overlay): Move to `buffer.c`. (build_overlay): Move from `lisp.h`. (maybe_alloc_buffer_overlays): Delete function (inline into its only caller). * src/itree.c (interval_tree_insert): Move declaration `from buffer.h`. (check_tree): Fix initial offset in call to `recurse_check_tree`. Remove redundant check of the `limit` value. (interval_node_init): Remove `begin` and `end` args. (interval_tree_insert): Mark it as static. Assert that the new node's `otick` should already be uptodate and its new parent as well. (itree_insert_node): New function. (interval_tree_insert_gap): Assert the otick of the removed+added nodes were uptodate and mark them as uptodate again after adjusting their positions. (interval_tree_inherit_offset): Check that the parent is at least as uptodate as the child. * src/lisp.h (build_overlay): Move to `buffer.h`. * src/itree.h (interval_node_init): Adjust accordingly. (interval_tree_insert): Remove declaration. (itree_insert_node): New declaration.
Diffstat (limited to 'src/itree.c')
-rw-r--r--src/itree.c55
1 files changed, 34 insertions, 21 deletions
diff --git a/src/itree.c b/src/itree.c
index b57c3cc656f..bbab70dac7c 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -142,6 +142,7 @@ static void interval_tree_rotate_right (struct interval_tree *, struct interval_
142static void interval_tree_insert_fix (struct interval_tree *, struct interval_node *); 142static void interval_tree_insert_fix (struct interval_tree *, struct interval_node *);
143static void interval_tree_transplant (struct interval_tree *, struct interval_node *, struct interval_node *); 143static void interval_tree_transplant (struct interval_tree *, struct interval_node *, struct interval_node *);
144static struct interval_generator* interval_generator_create (struct interval_tree *); 144static struct interval_generator* interval_generator_create (struct interval_tree *);
145static void interval_tree_insert (struct interval_tree *, struct interval_node *);
145 146
146/* The sentinel node, the null node. */ 147/* The sentinel node, the null node. */
147struct interval_node itree_null; 148struct interval_node itree_null;
@@ -260,11 +261,8 @@ check_tree (struct interval_tree *tree)
260 return true; 261 return true;
261 262
262 intmax_t size = 0; 263 intmax_t size = 0;
263 ptrdiff_t offset = tree->root->offset; 264 recurse_check_tree (tree->root, tree->otick, 0,
264 ptrdiff_t limit 265 PTRDIFF_MIN, PTRDIFF_MAX, &size);
265 = recurse_check_tree (tree->root, tree->otick, offset,
266 PTRDIFF_MIN, PTRDIFF_MAX, &size);
267 eassert (limit == tree->root->limit + offset);
268 return true; 266 return true;
269} 267}
270 268
@@ -375,12 +373,11 @@ interval_stack_pop (struct interval_stack *stack)
375 373
376void 374void
377interval_node_init (struct interval_node *node, 375interval_node_init (struct interval_node *node,
378 ptrdiff_t begin, ptrdiff_t end,
379 bool front_advance, bool rear_advance, 376 bool front_advance, bool rear_advance,
380 Lisp_Object data) 377 Lisp_Object data)
381{ 378{
382 node->begin = begin; 379 node->begin = -1;
383 node->end = max (begin, end); 380 node->end = -1;
384 node->front_advance = front_advance; 381 node->front_advance = front_advance;
385 node->rear_advance = rear_advance; 382 node->rear_advance = rear_advance;
386 node->data = data; 383 node->data = data;
@@ -488,7 +485,7 @@ interval_tree_size (struct interval_tree *tree)
488 Note, that inserting a node twice results in undefined behaviour. 485 Note, that inserting a node twice results in undefined behaviour.
489*/ 486*/
490 487
491void 488static void
492interval_tree_insert (struct interval_tree *tree, struct interval_node *node) 489interval_tree_insert (struct interval_tree *tree, struct interval_node *node)
493{ 490{
494 eassert (node && node->begin <= node->end && node != ITREE_NULL); 491 eassert (node && node->begin <= node->end && node != ITREE_NULL);
@@ -497,6 +494,9 @@ interval_tree_insert (struct interval_tree *tree, struct interval_node *node)
497 struct interval_node *parent = ITREE_NULL; 494 struct interval_node *parent = ITREE_NULL;
498 struct interval_node *child = tree->root; 495 struct interval_node *child = tree->root;
499 uintmax_t otick = tree->otick; 496 uintmax_t otick = tree->otick;
497 /* It's the responsability of the caller to set `otick` on the node,
498 to "confirm" that the begin/end fields are uptodate. */
499 eassert (node->otick == otick);
500 500
501 /* Find the insertion point, accumulate node's offset and update 501 /* Find the insertion point, accumulate node's offset and update
502 ancestors limit values. */ 502 ancestors limit values. */
@@ -526,7 +526,7 @@ interval_tree_insert (struct interval_tree *tree, struct interval_node *node)
526 node->red = true; 526 node->red = true;
527 node->offset = 0; 527 node->offset = 0;
528 node->limit = node->end; 528 node->limit = node->end;
529 node->otick = otick; 529 eassert (node->parent == ITREE_NULL || node->parent->otick >= node->otick);
530 530
531 /* Fix/update the tree */ 531 /* Fix/update the tree */
532 ++tree->size; 532 ++tree->size;
@@ -534,6 +534,16 @@ interval_tree_insert (struct interval_tree *tree, struct interval_node *node)
534 interval_tree_insert_fix (tree, node); 534 interval_tree_insert_fix (tree, node);
535} 535}
536 536
537void
538itree_insert_node (struct interval_tree *tree, struct interval_node *node,
539 ptrdiff_t begin, ptrdiff_t end)
540{
541 node->begin = begin;
542 node->end = end;
543 node->otick = tree->otick;
544 interval_tree_insert (tree, node);
545}
546
537/* Return true, if NODE is a member of TREE. */ 547/* Return true, if NODE is a member of TREE. */
538 548
539static bool 549static bool
@@ -849,6 +859,7 @@ interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t l
849{ 859{
850 if (length <= 0 || tree->root == ITREE_NULL) 860 if (length <= 0 || tree->root == ITREE_NULL)
851 return; 861 return;
862 uintmax_t ootick = tree->otick;
852 863
853 /* FIXME: Don't allocate generator/stack anew every time. */ 864 /* FIXME: Don't allocate generator/stack anew every time. */
854 865
@@ -907,13 +918,16 @@ interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t l
907 } 918 }
908 919
909 /* Reinsert nodes starting at POS having front-advance. */ 920 /* Reinsert nodes starting at POS having front-advance. */
921 uintmax_t notick = tree->otick;
910 nodeptr_and_flag nav; 922 nodeptr_and_flag nav;
911 while ((nav = interval_stack_pop (saved), 923 while ((nav = interval_stack_pop (saved),
912 node = nav_nodeptr (nav))) 924 node = nav_nodeptr (nav)))
913 { 925 {
926 eassert (node->otick == ootick);
914 node->begin += length; 927 node->begin += length;
915 if (node->end != pos || node->rear_advance) 928 if (node->end != pos || node->rear_advance)
916 node->end += length; 929 node->end += length;
930 node->otick = notick;
917 interval_tree_insert (tree, node); 931 interval_tree_insert (tree, node);
918 } 932 }
919 933
@@ -1123,12 +1137,19 @@ interval_tree_update_limit (struct interval_node *node)
1123static void 1137static void
1124interval_tree_inherit_offset (uintmax_t otick, struct interval_node *node) 1138interval_tree_inherit_offset (uintmax_t otick, struct interval_node *node)
1125{ 1139{
1140 eassert (node->parent == ITREE_NULL || node->parent->otick >= node->otick);
1126 if (node->otick == otick) 1141 if (node->otick == otick)
1127 { 1142 {
1128 eassert (node->offset == 0); 1143 eassert (node->offset == 0);
1129 return; 1144 return;
1130 } 1145 }
1131 1146
1147 /* Offsets can be inherited from dirty nodes (with out of date
1148 otick) during insert and remove. Offsets aren't inherited
1149 downward from the root for these operations so rotations are
1150 performed on potentially "dirty" nodes, where we only make sure
1151 the *local* offsets are all zero. */
1152
1132 if (node->offset) 1153 if (node->offset)
1133 { 1154 {
1134 node->begin += node->offset; 1155 node->begin += node->offset;
@@ -1140,17 +1161,9 @@ interval_tree_inherit_offset (uintmax_t otick, struct interval_node *node)
1140 node->right->offset += node->offset; 1161 node->right->offset += node->offset;
1141 node->offset = 0; 1162 node->offset = 0;
1142 } 1163 }
1143 /* FIXME: I wonder when/why this condition can be false, and more 1164 /* The only thing that matters about `otick` is whether it's equal to
1144 generally why we'd want to propagate offsets that may not be 1165 that of the tree. We could also "blindly" inherit from parent->otick,
1145 fully up-to-date. --stef 1166 but we need to tree's `otick` anyway for when there's no parent. */
1146
1147 Offsets can be inherited from dirty nodes (with out of date
1148 otick) during insert and remove. Offsets aren't inherited
1149 downward from the root for these operations so rotations are
1150 performed on potentially "dirty" nodes. We could fix this by
1151 always inheriting offsets downward from the root for every insert
1152 and remove. --matt
1153 */
1154 if (node->parent == ITREE_NULL || node->parent->otick == otick) 1167 if (node->parent == ITREE_NULL || node->parent->otick == otick)
1155 node->otick = otick; 1168 node->otick = otick;
1156} 1169}