diff options
| author | Stefan Monnier | 2022-10-09 19:45:26 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2022-10-09 19:45:26 -0400 |
| commit | 7cbeeabc7e6271948e7bb93020c2e4e50c65f384 (patch) | |
| tree | 777b281d62878ab7cc5a12b7e3fbc8952bf95dbc /src | |
| parent | 4f3f7aebc957732f4fbe5c799da5367f46607680 (diff) | |
| download | emacs-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')
| -rw-r--r-- | src/alloc.c | 8 | ||||
| -rw-r--r-- | src/buffer.c | 58 | ||||
| -rw-r--r-- | src/buffer.h | 35 | ||||
| -rw-r--r-- | src/itree.c | 55 | ||||
| -rw-r--r-- | src/itree.h | 5 | ||||
| -rw-r--r-- | src/lisp.h | 1 |
6 files changed, 83 insertions, 79 deletions
diff --git a/src/alloc.c b/src/alloc.c index 50968b7e121..00f2991f250 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3702,19 +3702,17 @@ build_symbol_with_pos (Lisp_Object symbol, Lisp_Object position) | |||
| 3702 | return val; | 3702 | return val; |
| 3703 | } | 3703 | } |
| 3704 | 3704 | ||
| 3705 | /* Return a new overlay with specified START, END and PLIST. */ | 3705 | /* Return a new (deleted) overlay with PLIST. */ |
| 3706 | 3706 | ||
| 3707 | Lisp_Object | 3707 | Lisp_Object |
| 3708 | build_overlay (ptrdiff_t begin, ptrdiff_t end, | 3708 | build_overlay (bool front_advance, bool rear_advance, |
| 3709 | bool front_advance, bool rear_advance, | ||
| 3710 | Lisp_Object plist) | 3709 | Lisp_Object plist) |
| 3711 | { | 3710 | { |
| 3712 | struct Lisp_Overlay *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Overlay, plist, | 3711 | struct Lisp_Overlay *p = ALLOCATE_PSEUDOVECTOR (struct Lisp_Overlay, plist, |
| 3713 | PVEC_OVERLAY); | 3712 | PVEC_OVERLAY); |
| 3714 | Lisp_Object overlay = make_lisp_ptr (p, Lisp_Vectorlike); | 3713 | Lisp_Object overlay = make_lisp_ptr (p, Lisp_Vectorlike); |
| 3715 | struct interval_node *node = xmalloc (sizeof (*node)); | 3714 | struct interval_node *node = xmalloc (sizeof (*node)); |
| 3716 | interval_node_init (node, begin, end, front_advance, | 3715 | interval_node_init (node, front_advance, rear_advance, overlay); |
| 3717 | rear_advance, overlay); | ||
| 3718 | p->interval = node; | 3716 | p->interval = node; |
| 3719 | p->buffer = NULL; | 3717 | p->buffer = NULL; |
| 3720 | set_overlay_plist (overlay, plist); | 3718 | set_overlay_plist (overlay, plist); |
diff --git a/src/buffer.c b/src/buffer.c index f59fddcbdeb..e1303f2a880 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -638,6 +638,16 @@ even if it is dead. The return value is never nil. */) | |||
| 638 | return buffer; | 638 | return buffer; |
| 639 | } | 639 | } |
| 640 | 640 | ||
| 641 | static void | ||
| 642 | add_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov, | ||
| 643 | ptrdiff_t begin, ptrdiff_t end) | ||
| 644 | { | ||
| 645 | eassert (! ov->buffer); | ||
| 646 | if (! b->overlays) | ||
| 647 | b->overlays = interval_tree_create (); | ||
| 648 | ov->buffer = b; | ||
| 649 | itree_insert_node (b->overlays, ov->interval, begin, end); | ||
| 650 | } | ||
| 641 | 651 | ||
| 642 | /* Copy overlays of buffer FROM to buffer TO. */ | 652 | /* Copy overlays of buffer FROM to buffer TO. */ |
| 643 | 653 | ||
| @@ -650,11 +660,10 @@ copy_overlays (struct buffer *from, struct buffer *to) | |||
| 650 | ITREE_FOREACH (node, from->overlays, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING) | 660 | ITREE_FOREACH (node, from->overlays, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING) |
| 651 | { | 661 | { |
| 652 | Lisp_Object ov = node->data; | 662 | Lisp_Object ov = node->data; |
| 653 | Lisp_Object copy = build_overlay (node->begin, node->end, | 663 | Lisp_Object copy = build_overlay (node->front_advance, |
| 654 | node->front_advance, | ||
| 655 | node->rear_advance, | 664 | node->rear_advance, |
| 656 | Fcopy_sequence (OVERLAY_PLIST (ov))); | 665 | Fcopy_sequence (OVERLAY_PLIST (ov))); |
| 657 | add_buffer_overlay (to, XOVERLAY (copy)); | 666 | add_buffer_overlay (to, XOVERLAY (copy), node->begin, node->end); |
| 658 | } | 667 | } |
| 659 | } | 668 | } |
| 660 | 669 | ||
| @@ -897,6 +906,15 @@ does not run the hooks `kill-buffer-hook', | |||
| 897 | return buf; | 906 | return buf; |
| 898 | } | 907 | } |
| 899 | 908 | ||
| 909 | static void | ||
| 910 | remove_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov) | ||
| 911 | { | ||
| 912 | eassert (b->overlays); | ||
| 913 | eassert (ov->buffer == b); | ||
| 914 | interval_tree_remove (ov->buffer->overlays, ov->interval); | ||
| 915 | ov->buffer = NULL; | ||
| 916 | } | ||
| 917 | |||
| 900 | /* Mark OV as no longer associated with its buffer. */ | 918 | /* Mark OV as no longer associated with its buffer. */ |
| 901 | 919 | ||
| 902 | static void | 920 | static void |
| @@ -3486,12 +3504,11 @@ for the rear of the overlay advance when text is inserted there | |||
| 3486 | temp = beg; beg = end; end = temp; | 3504 | temp = beg; beg = end; end = temp; |
| 3487 | } | 3505 | } |
| 3488 | 3506 | ||
| 3489 | ptrdiff_t obeg = clip_to_bounds (BEG, XFIXNUM (beg), b->text->z); | 3507 | ptrdiff_t obeg = clip_to_bounds (BUF_BEG (b), XFIXNUM (beg), BUF_Z (b)); |
| 3490 | ptrdiff_t oend = clip_to_bounds (obeg, XFIXNUM (end), b->text->z); | 3508 | ptrdiff_t oend = clip_to_bounds (obeg, XFIXNUM (end), BUF_Z (b)); |
| 3491 | ov = build_overlay (obeg, oend, | 3509 | ov = build_overlay (! NILP (front_advance), |
| 3492 | ! NILP (front_advance), | ||
| 3493 | ! NILP (rear_advance), Qnil); | 3510 | ! NILP (rear_advance), Qnil); |
| 3494 | add_buffer_overlay (b, XOVERLAY (ov)); | 3511 | add_buffer_overlay (b, XOVERLAY (ov), obeg, oend); |
| 3495 | 3512 | ||
| 3496 | /* We don't need to redisplay the region covered by the overlay, because | 3513 | /* We don't need to redisplay the region covered by the overlay, because |
| 3497 | the overlay has no properties at the moment. */ | 3514 | the overlay has no properties at the moment. */ |
| @@ -3518,6 +3535,15 @@ modify_overlay (struct buffer *buf, ptrdiff_t start, ptrdiff_t end) | |||
| 3518 | modiff_incr (&BUF_OVERLAY_MODIFF (buf), 1); | 3535 | modiff_incr (&BUF_OVERLAY_MODIFF (buf), 1); |
| 3519 | } | 3536 | } |
| 3520 | 3537 | ||
| 3538 | INLINE void | ||
| 3539 | set_overlay_region (struct Lisp_Overlay *ov, ptrdiff_t begin, ptrdiff_t end) | ||
| 3540 | { | ||
| 3541 | eassert (ov->buffer); | ||
| 3542 | begin = clip_to_bounds (BEG, begin, ov->buffer->text->z); | ||
| 3543 | end = clip_to_bounds (begin, end, ov->buffer->text->z); | ||
| 3544 | interval_node_set_region (ov->buffer->overlays, ov->interval, begin, end); | ||
| 3545 | } | ||
| 3546 | |||
| 3521 | DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0, | 3547 | DEFUN ("move-overlay", Fmove_overlay, Smove_overlay, 3, 4, 0, |
| 3522 | doc: /* Set the endpoints of OVERLAY to BEG and END in BUFFER. | 3548 | doc: /* Set the endpoints of OVERLAY to BEG and END in BUFFER. |
| 3523 | If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now. | 3549 | If BUFFER is omitted, leave OVERLAY in the same buffer it inhabits now. |
| @@ -3528,7 +3554,6 @@ buffer. */) | |||
| 3528 | struct buffer *b, *ob = 0; | 3554 | struct buffer *b, *ob = 0; |
| 3529 | Lisp_Object obuffer; | 3555 | Lisp_Object obuffer; |
| 3530 | specpdl_ref count = SPECPDL_INDEX (); | 3556 | specpdl_ref count = SPECPDL_INDEX (); |
| 3531 | ptrdiff_t n_beg, n_end; | ||
| 3532 | ptrdiff_t o_beg UNINIT, o_end UNINIT; | 3557 | ptrdiff_t o_beg UNINIT, o_end UNINIT; |
| 3533 | 3558 | ||
| 3534 | CHECK_OVERLAY (overlay); | 3559 | CHECK_OVERLAY (overlay); |
| @@ -3555,11 +3580,14 @@ buffer. */) | |||
| 3555 | temp = beg; beg = end; end = temp; | 3580 | temp = beg; beg = end; end = temp; |
| 3556 | } | 3581 | } |
| 3557 | 3582 | ||
| 3558 | specbind (Qinhibit_quit, Qt); | 3583 | specbind (Qinhibit_quit, Qt); /* FIXME: Why? */ |
| 3559 | 3584 | ||
| 3560 | obuffer = Foverlay_buffer (overlay); | 3585 | obuffer = Foverlay_buffer (overlay); |
| 3561 | b = XBUFFER (buffer); | 3586 | b = XBUFFER (buffer); |
| 3562 | 3587 | ||
| 3588 | ptrdiff_t n_beg = clip_to_bounds (BUF_BEG (b), XFIXNUM (beg), BUF_Z (b)); | ||
| 3589 | ptrdiff_t n_end = clip_to_bounds (n_beg, XFIXNUM (end), BUF_Z (b)); | ||
| 3590 | |||
| 3563 | if (!NILP (obuffer)) | 3591 | if (!NILP (obuffer)) |
| 3564 | { | 3592 | { |
| 3565 | ob = XBUFFER (obuffer); | 3593 | ob = XBUFFER (obuffer); |
| @@ -3572,13 +3600,11 @@ buffer. */) | |||
| 3572 | { | 3600 | { |
| 3573 | if (! NILP (obuffer)) | 3601 | if (! NILP (obuffer)) |
| 3574 | remove_buffer_overlay (XBUFFER (obuffer), XOVERLAY (overlay)); | 3602 | remove_buffer_overlay (XBUFFER (obuffer), XOVERLAY (overlay)); |
| 3575 | add_buffer_overlay (XBUFFER (buffer), XOVERLAY (overlay)); | 3603 | add_buffer_overlay (XBUFFER (buffer), XOVERLAY (overlay), n_beg, n_end); |
| 3576 | } | 3604 | } |
| 3577 | /* Set the overlay boundaries, which may clip them. */ | 3605 | else |
| 3578 | set_overlay_region (XOVERLAY (overlay), XFIXNUM (beg), XFIXNUM (end)); | 3606 | interval_node_set_region (b->overlays, XOVERLAY (overlay)->interval, |
| 3579 | 3607 | n_beg, n_end); | |
| 3580 | n_beg = OVERLAY_START (overlay); | ||
| 3581 | n_end = OVERLAY_END (overlay); | ||
| 3582 | 3608 | ||
| 3583 | /* If the overlay has changed buffers, do a thorough redisplay. */ | 3609 | /* If the overlay has changed buffers, do a thorough redisplay. */ |
| 3584 | if (!BASE_EQ (buffer, obuffer)) | 3610 | if (!BASE_EQ (buffer, obuffer)) |
diff --git a/src/buffer.h b/src/buffer.h index a4e3934cad2..288acd4f5ee 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -1189,6 +1189,7 @@ extern void fix_overlays_before (struct buffer *, ptrdiff_t, ptrdiff_t); | |||
| 1189 | extern void mmap_set_vars (bool); | 1189 | extern void mmap_set_vars (bool); |
| 1190 | extern void restore_buffer (Lisp_Object); | 1190 | extern void restore_buffer (Lisp_Object); |
| 1191 | extern void set_buffer_if_live (Lisp_Object); | 1191 | extern void set_buffer_if_live (Lisp_Object); |
| 1192 | extern Lisp_Object build_overlay (bool, bool, Lisp_Object); | ||
| 1192 | 1193 | ||
| 1193 | /* Return B as a struct buffer pointer, defaulting to the current buffer. */ | 1194 | /* Return B as a struct buffer pointer, defaulting to the current buffer. */ |
| 1194 | 1195 | ||
| @@ -1408,40 +1409,6 @@ overlay_end (struct Lisp_Overlay *ov) | |||
| 1408 | return interval_node_end (ov->buffer->overlays, ov->interval); | 1409 | return interval_node_end (ov->buffer->overlays, ov->interval); |
| 1409 | } | 1410 | } |
| 1410 | 1411 | ||
| 1411 | INLINE void | ||
| 1412 | set_overlay_region (struct Lisp_Overlay *ov, ptrdiff_t begin, ptrdiff_t end) | ||
| 1413 | { | ||
| 1414 | eassert (ov->buffer); | ||
| 1415 | begin = clip_to_bounds (BEG, begin, ov->buffer->text->z); | ||
| 1416 | end = clip_to_bounds (begin, end, ov->buffer->text->z); | ||
| 1417 | interval_node_set_region (ov->buffer->overlays, ov->interval, begin, end); | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | INLINE void | ||
| 1421 | maybe_alloc_buffer_overlays (struct buffer *b) | ||
| 1422 | { | ||
| 1423 | if (! b->overlays) | ||
| 1424 | b->overlays = interval_tree_create (); | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | INLINE void | ||
| 1428 | add_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov) | ||
| 1429 | { | ||
| 1430 | eassert (! ov->buffer); | ||
| 1431 | maybe_alloc_buffer_overlays (b); | ||
| 1432 | ov->buffer = b; | ||
| 1433 | interval_tree_insert (b->overlays, ov->interval); | ||
| 1434 | } | ||
| 1435 | |||
| 1436 | INLINE void | ||
| 1437 | remove_buffer_overlay (struct buffer *b, struct Lisp_Overlay *ov) | ||
| 1438 | { | ||
| 1439 | eassert (b->overlays); | ||
| 1440 | eassert (ov->buffer == b); | ||
| 1441 | interval_tree_remove (ov->buffer->overlays, ov->interval); | ||
| 1442 | ov->buffer = NULL; | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | /* Return the start of OV in its buffer, or -1 if OV is not associated | 1412 | /* Return the start of OV in its buffer, or -1 if OV is not associated |
| 1446 | with any buffer. */ | 1413 | with any buffer. */ |
| 1447 | 1414 | ||
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_ | |||
| 142 | static void interval_tree_insert_fix (struct interval_tree *, struct interval_node *); | 142 | static void interval_tree_insert_fix (struct interval_tree *, struct interval_node *); |
| 143 | static void interval_tree_transplant (struct interval_tree *, struct interval_node *, struct interval_node *); | 143 | static void interval_tree_transplant (struct interval_tree *, struct interval_node *, struct interval_node *); |
| 144 | static struct interval_generator* interval_generator_create (struct interval_tree *); | 144 | static struct interval_generator* interval_generator_create (struct interval_tree *); |
| 145 | static 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. */ |
| 147 | struct interval_node itree_null; | 148 | struct 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 | ||
| 376 | void | 374 | void |
| 377 | interval_node_init (struct interval_node *node, | 375 | interval_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 | ||
| 491 | void | 488 | static void |
| 492 | interval_tree_insert (struct interval_tree *tree, struct interval_node *node) | 489 | interval_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 | ||
| 537 | void | ||
| 538 | itree_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 | ||
| 539 | static bool | 549 | static 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) | |||
| 1123 | static void | 1137 | static void |
| 1124 | interval_tree_inherit_offset (uintmax_t otick, struct interval_node *node) | 1138 | interval_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 | } |
diff --git a/src/itree.h b/src/itree.h index 7fdc9c07c93..5733ec15305 100644 --- a/src/itree.h +++ b/src/itree.h | |||
| @@ -112,7 +112,7 @@ enum interval_tree_order { | |||
| 112 | ITREE_PRE_ORDER, | 112 | ITREE_PRE_ORDER, |
| 113 | }; | 113 | }; |
| 114 | 114 | ||
| 115 | void interval_node_init (struct interval_node *, ptrdiff_t, ptrdiff_t, bool, bool, Lisp_Object); | 115 | void interval_node_init (struct interval_node *, bool, bool, Lisp_Object); |
| 116 | ptrdiff_t interval_node_begin (struct interval_tree *, struct interval_node *); | 116 | ptrdiff_t interval_node_begin (struct interval_tree *, struct interval_node *); |
| 117 | ptrdiff_t interval_node_end (struct interval_tree *, struct interval_node *); | 117 | ptrdiff_t interval_node_end (struct interval_tree *, struct interval_node *); |
| 118 | void interval_node_set_region (struct interval_tree *, struct interval_node *, ptrdiff_t, ptrdiff_t); | 118 | void interval_node_set_region (struct interval_tree *, struct interval_node *, ptrdiff_t, ptrdiff_t); |
| @@ -120,7 +120,8 @@ struct interval_tree *interval_tree_create (void); | |||
| 120 | void interval_tree_destroy (struct interval_tree *); | 120 | void interval_tree_destroy (struct interval_tree *); |
| 121 | intmax_t interval_tree_size (struct interval_tree *); | 121 | intmax_t interval_tree_size (struct interval_tree *); |
| 122 | void interval_tree_clear (struct interval_tree *); | 122 | void interval_tree_clear (struct interval_tree *); |
| 123 | void interval_tree_insert (struct interval_tree *, struct interval_node *); | 123 | void itree_insert_node (struct interval_tree *tree, struct interval_node *node, |
| 124 | ptrdiff_t begin, ptrdiff_t end); | ||
| 124 | struct interval_node *interval_tree_remove (struct interval_tree *, struct interval_node *); | 125 | struct interval_node *interval_tree_remove (struct interval_tree *, struct interval_node *); |
| 125 | struct interval_generator *interval_tree_iter_start (struct interval_tree *, ptrdiff_t, ptrdiff_t, enum interval_tree_order, | 126 | struct interval_generator *interval_tree_iter_start (struct interval_tree *, ptrdiff_t, ptrdiff_t, enum interval_tree_order, |
| 126 | const char* file, int line); | 127 | const char* file, int line); |
diff --git a/src/lisp.h b/src/lisp.h index 7d838afb5c9..7cd78712814 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4415,7 +4415,6 @@ extern Lisp_Object make_float (double); | |||
| 4415 | extern void display_malloc_warning (void); | 4415 | extern void display_malloc_warning (void); |
| 4416 | extern specpdl_ref inhibit_garbage_collection (void); | 4416 | extern specpdl_ref inhibit_garbage_collection (void); |
| 4417 | extern Lisp_Object build_symbol_with_pos (Lisp_Object, Lisp_Object); | 4417 | extern Lisp_Object build_symbol_with_pos (Lisp_Object, Lisp_Object); |
| 4418 | extern Lisp_Object build_overlay (ptrdiff_t, ptrdiff_t, bool, bool, Lisp_Object); | ||
| 4419 | extern void free_cons (struct Lisp_Cons *); | 4418 | extern void free_cons (struct Lisp_Cons *); |
| 4420 | extern void init_alloc_once (void); | 4419 | extern void init_alloc_once (void); |
| 4421 | extern void init_alloc (void); | 4420 | extern void init_alloc (void); |