GNU bug report logs -
#79200
31.0.50; Duplicated elements for '#<marker at' in buffer-undo-list
Previous Next
To reply to this bug, email your comments to 79200 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Fri, 08 Aug 2025 16:45:03 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Óscar Fuentes <oscarfv <at> eclipso.eu>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Fri, 08 Aug 2025 16:45:04 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
emacs -Q
write in *scratch* some lines with random words:
arins
arseina
aierni
iosrn nioni
ionugfw
sronuf
Now undo a few of those lines (C-_), move the cursor and C-_ again to
redo.
C-h v buffer-undo-list
shows a content like this:
(nil (#("sreint" 0 6 (fontified t)) . 164)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6)
(#<marker at 164 in *scratch*> . -6) nil (#("
"
0 1 (fontified t))
. 170)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker in no buffer> . -1) nil
(#("aor" 0 3 (fontified t)) . 171)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3)
(#<marker at 164 in *scratch*> . -3) nil (#("
"
0 1 (fontified t))
. 174)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
(#<marker at 164 in *scratch*> . -1)
etc.
On a long-lived session, those elements are so abundant and they are
added so fast that exhaust the capacity for undo info. On certain
circunstances, while undoing, "No further undo information" is shown
after just four undos affecting a few lines each.
On those sessions, eventually, a warning like this is displayed:
Warning (undo): Buffer ‘blah.el’ undo info was 36040665 bytes long.
The undo info was discarded because it exceeded `undo-outer-limit'.
In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
version 1.18.4) of 2025-08-08 built on zen
Repository revision: 12354bcfdc288f111c411c87e8bdebe6dcb41a4d
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12101016
System Description: Debian GNU/Linux 13 (trixie)
Configured using:
'configure 'CPPFLAGS=-O2 -fno-omit-frame-pointer -g3'
--with-native-compilation --with-tree-sitter
--without-toolkit-scroll-bars --with-x-toolkit=lucid --with-modules
--without-imagemagick'
Configured features:
CAIRO FREETYPE GIF GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG LIBOTF
LIBSELINUX LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG
SECCOMP SOUND SQLITE3 THREADS TIFF TREE_SITTER WEBP X11 XAW3D XDBE XIM
XPM LUCID ZLIB
Important settings:
value of $LANG: C
locale-coding-system: nil
Major mode: Help
Minor modes in effect:
tooltip-mode: t
global-eldoc-mode: t
eldoc-mode: t
show-paren-mode: t
electric-indent-mode: t
mouse-wheel-mode: t
tool-bar-mode: t
menu-bar-mode: t
file-name-shadow-mode: t
isearch-fold-quotes-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
minibuffer-regexp-mode: t
buffer-read-only: t
line-number-mode: t
indent-tabs-mode: t
transient-mark-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
Load-path shadows:
None found.
Features:
(shadow sort mail-extr dabbrev emacsbug lisp-mnt message mailcap
yank-media puny dired dired-loaddefs rfc822 mml mml-sec password-cache
epa derived epg rfc6068 epg-config gnus-util time-date mm-decode
mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader
sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils
cl-extra pp cl-print compile text-property-search comint subr-x ansi-osc
ansi-color ring comp-run comp-common rx thingatpt help-fns byte-opt gv
bytecomp byte-compile radix-tree help-mode cl-loaddefs cl-lib rmc
iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook
vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd touch-screen tool-bar dnd fontset image regexp-opt
fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode
register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads inotify dynamic-setting system-font-setting font-render-setting
cairo x-toolkit x multi-tty move-toolbar make-network-process
tty-child-frames native-compile emacs)
Memory information:
((conses 16 110423 18017) (symbols 48 7340 0) (strings 32 32932 3183)
(string-bytes 1 1000000) (vectors 16 20389)
(vector-slots 8 227284 7471) (floats 8 56 60) (intervals 56 438 16)
(buffers 1064 12))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 08:30:02 GMT)
Full text and
rfc822 format available.
Message #8 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> emacs -Q
>
> write in *scratch* some lines with random words:
>
> arins
> arseina
> aierni
>
> iosrn nioni
> ionugfw
>
> sronuf
>
> Now undo a few of those lines (C-_), move the cursor and C-_ again to
> redo.
Interesting. I come from a slightly different angle, that in my mac+igc
port I had sometimes only 3 undos before I got "no more undo
information". and I thought I had messed up something.
My cimpler recipe is
1. Make a new buffer x.el
2. Type an a
3. undo
4. C-h v buffer-undo-list
=>
Value:
(nil ("a" . 1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) nil (1 . 2) (t . 0))
Local in buffer x.el; global value is nil
So far I can't see what is the cause. I would have guessed something in
or around primitive-undo, but that hasn't changed forever.
Adding Stef.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 08:56:01 GMT)
Full text and
rfc822 format available.
Message #11 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
>
>> emacs -Q
>>
>> write in *scratch* some lines with random words:
>>
>> arins
>> arseina
>> aierni
>>
>> iosrn nioni
>> ionugfw
>>
>> sronuf
>>
>> Now undo a few of those lines (C-_), move the cursor and C-_ again to
>> redo.
>
> Interesting. I come from a slightly different angle, that in my mac+igc
> port I had sometimes only 3 undos before I got "no more undo
> information". and I thought I had messed up something.
>
> My cimpler recipe is
>
> 1. Make a new buffer x.el
> 2. Type an a
> 3. undo
> 4. C-h v buffer-undo-list
>
> =>
>
> Value:
> (nil ("a" . 1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) nil (1 . 2) (t . 0))
> Local in buffer x.el; global value is nil
Hmm. I'm seeing different results: "only" five markers between "a"
insertions.
> So far I can't see what is the cause. I would have guessed something in
> or around primitive-undo, but that hasn't changed forever.
>
> Adding Stef.
Well, compact_undo_list is a nop with HAVE_MPS:
static Lisp_Object
compact_undo_list (Lisp_Object list)
{
#ifndef HAVE_MPS
Lisp_Object tail, *prev = &list;
for (tail = list; CONSP (tail); tail = XCDR (tail))
{
if (CONSP (XCAR (tail))
&& MARKERP (XCAR (XCAR (tail)))
&& !vectorlike_marked_p (&XMARKER (XCAR (XCAR (tail)))->header))
*prev = XCDR (tail);
else
prev = xcdr_addr (tail);
}
#endif
return list;
}
We still truncate undo lists, but we don't "compact" them, i.e. treat
them as weak structures and remove markers that are referred to only in
undo lists. Correct?
The "obvious" fix would be to use a weak hash table to associate undo
information with markers rather than keeping them in the undo
list. However, that sounds quite hard to do, and it might make undo a
lot more expensive.
Pip
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:02:02 GMT)
Full text and
rfc822 format available.
Message #14 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
>
>> emacs -Q
>>
>> write in *scratch* some lines with random words:
>>
>> arins
>> arseina
>> aierni
>>
>> iosrn nioni
>> ionugfw
>>
>> sronuf
>>
>> Now undo a few of those lines (C-_), move the cursor and C-_ again to
>> redo.
>
> Interesting. I come from a slightly different angle, that in my mac+igc
> port I had sometimes only 3 undos before I got "no more undo
> information". and I thought I had messed up something.
Same here, but igc/Linux. Please note that the recipe on my report is
with yesterday's master, though.
> My cimpler recipe is
>
> 1. Make a new buffer x.el
> 2. Type an a
> 3. undo
> 4. C-h v buffer-undo-list
>
> =>
>
> Value:
> (nil ("a" . 1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) nil (1 . 2) (t . 0))
> Local in buffer x.el; global value is nil
I can't reproduce this with my master's build:
emacs -Q x.el
type an a
undo
C-h v buffer-undo-list
Its value is
(nil (#("a" 0 1 (fontified t)) . 1) (#<marker at 1 in x.el> . -1) nil
(1 . 2) (t . -1))
Local in buffer x.el; global value is nil
However, doing the same with my igc build of 1 of August yields this:
Its value is
(nil (#("a" 0 1 (fontified t)) . 1) (#<marker at 1 in x.el> . -1)
(#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1) nil
(1 . 2) (t . -1))
Local in buffer x.el; global value is nil
> So far I can't see what is the cause. I would have guessed something in
> or around primitive-undo, but that hasn't changed forever.
Eli in emacs-devel pointed to the possibility that something is creating
lots of markers. Checking if those repeated elements in buffer-undo-list
point to the same marker or to different ones would be revealing. Or
not: I don't even know if getting markers to the same place in a buffer
yield the same object or new ones.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:03:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Pip Cet <pipcet <at> protonmail.com> writes:
> insertions.
>
>> So far I can't see what is the cause. I would have guessed something in
>> or around primitive-undo, but that hasn't changed forever.
>>
>> Adding Stef.
>
> Well, compact_undo_list is a nop with HAVE_MPS:
Sorry, I forgot to mention an important detail: this happens in master
but not emacs-30. Oscar's report is also for master, IIRC.
Really puzzling.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:16:01 GMT)
Full text and
rfc822 format available.
Message #20 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Pip Cet <pipcet <at> protonmail.com> writes:
>
>> insertions.
>>
>>> So far I can't see what is the cause. I would have guessed something in
>>> or around primitive-undo, but that hasn't changed forever.
>>>
>>> Adding Stef.
>>
>> Well, compact_undo_list is a nop with HAVE_MPS:
>
> Sorry, I forgot to mention an important detail: this happens in master
> but not emacs-30. Oscar's report is also for master, IIRC.
>
> Really puzzling.
However, it seems that on igc it is more easily reproducible.
For a moment I thought that I messed up my bug report, because a couple
of attempts at reproducing the problem on master failed, but then I made
a few more undos/redos and the sequences of duplicated elements
appeared.
Something triggers this and then explodes.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:16:02 GMT)
Full text and
rfc822 format available.
Message #23 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
>>
>>> emacs -Q
>>>
>>> write in *scratch* some lines with random words:
>>>
>>> arins
>>> arseina
>>> aierni
>>>
>>> iosrn nioni
>>> ionugfw
>>>
>>> sronuf
>>>
>>> Now undo a few of those lines (C-_), move the cursor and C-_ again to
>>> redo.
>>
>> Interesting. I come from a slightly different angle, that in my mac+igc
>> port I had sometimes only 3 undos before I got "no more undo
>> information". and I thought I had messed up something.
>
> Same here, but igc/Linux. Please note that the recipe on my report is
> with yesterday's master, though.
>
>> My cimpler recipe is
>>
>> 1. Make a new buffer x.el
>> 2. Type an a
>> 3. undo
>> 4. C-h v buffer-undo-list
>>
>> =>
>>
>> Value:
>> (nil ("a" . 1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) nil (1 . 2) (t . 0))
>> Local in buffer x.el; global value is nil
>
> I can't reproduce this with my master's build:
>
> emacs -Q x.el
>
> type an a
>
> undo
>
> C-h v buffer-undo-list
>
> Its value is
> (nil (#("a" 0 1 (fontified t)) . 1) (#<marker at 1 in x.el> . -1) nil
> (1 . 2) (t . -1))
> Local in buffer x.el; global value is nil
>
> However, doing the same with my igc build of 1 of August yields this:
>
> Its value is
> (nil (#("a" 0 1 (fontified t)) . 1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1) nil
> (1 . 2) (t . -1))
> Local in buffer x.el; global value is nil
Now I'm completely confused. Your report had
In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
version 1.18.4) of 2025-08-08 built on zen
Repository revision: 12354bcfdc288f111c411c87e8bdebe6dcb41a4d
Repository branch: master
but it's not happending in master?
And I think, if didn't make a cockpit error, I tested that with master.
Have to check this later, though.
>
>
>> So far I can't see what is the cause. I would have guessed something in
>> or around primitive-undo, but that hasn't changed forever.
>
> Eli in emacs-devel pointed to the possibility that something is creating
> lots of markers. Checking if those repeated elements in buffer-undo-list
> point to the same marker or to different ones would be revealing. Or
> not: I don't even know if getting markers to the same place in a buffer
> yield the same object or new ones.
Hm.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:19:01 GMT)
Full text and
rfc822 format available.
Message #26 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> Date: Fri, 08 Aug 2025 18:43:51 +0200
> From: Óscar Fuentes via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
>
>
> emacs -Q
>
> write in *scratch* some lines with random words:
>
> arins
> arseina
> aierni
>
> iosrn nioni
> ionugfw
>
> sronuf
>
> Now undo a few of those lines (C-_), move the cursor and C-_ again to
> redo.
>
> C-h v buffer-undo-list
>
> shows a content like this:
>
> (nil (#("sreint" 0 6 (fontified t)) . 164)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6)
> (#<marker at 164 in *scratch*> . -6) nil (#("
> "
> 0 1 (fontified t))
> . 170)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker in no buffer> . -1) nil
> (#("aor" 0 3 (fontified t)) . 171)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3)
> (#<marker at 164 in *scratch*> . -3) nil (#("
> "
> 0 1 (fontified t))
> . 174)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> (#<marker at 164 in *scratch*> . -1)
> etc.
>
> On a long-lived session, those elements are so abundant and they are
> added so fast that exhaust the capacity for undo info. On certain
> circunstances, while undoing, "No further undo information" is shown
> after just four undos affecting a few lines each.
>
> On those sessions, eventually, a warning like this is displayed:
>
> Warning (undo): Buffer ‘blah.el’ undo info was 36040665 bytes long.
> The undo info was discarded because it exceeded `undo-outer-limit'.
Your bug report says this is on master branch:
> In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
> version 1.18.4) of 2025-08-08 built on zen
> Repository revision: 12354bcfdc288f111c411c87e8bdebe6dcb41a4d
> Repository branch: master
But I can only reproduce this on the igc branch. On master, I see a
single entry for marker adjustment, not many identical ones.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:19:02 GMT)
Full text and
rfc822 format available.
Message #29 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Pip Cet <pipcet <at> protonmail.com> writes:
>>
>>> insertions.
>>>
>>>> So far I can't see what is the cause. I would have guessed something in
>>>> or around primitive-undo, but that hasn't changed forever.
>>>>
>>>> Adding Stef.
>>>
>>> Well, compact_undo_list is a nop with HAVE_MPS:
>>
>> Sorry, I forgot to mention an important detail: this happens in master
>> but not emacs-30. Oscar's report is also for master, IIRC.
>>
>> Really puzzling.
>
> However, it seems that on igc it is more easily reproducible.
>
> For a moment I thought that I messed up my bug report, because a couple
> of attempts at reproducing the problem on master failed, but then I made
> a few more undos/redos and the sequences of duplicated elements
> appeared.
>
> Something triggers this and then explodes.
Okay, thanks. At least I don't have to check if I made a cockpit error
:-). But I guess I have to check emacs-30 again, if this is kind of
"random".
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:21:02 GMT)
Full text and
rfc822 format available.
Message #32 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> Cc: 79200 <at> debbugs.gnu.org, Stefan Monnier <monnier <at> iro.umontreal.ca>
> Date: Sat, 09 Aug 2025 11:01:37 +0200
> From: Óscar Fuentes via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
>
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
> > Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> >
> >> emacs -Q
> >>
> >> write in *scratch* some lines with random words:
> >>
> >> arins
> >> arseina
> >> aierni
> >>
> >> iosrn nioni
> >> ionugfw
> >>
> >> sronuf
> >>
> >> Now undo a few of those lines (C-_), move the cursor and C-_ again to
> >> redo.
> >
> > Interesting. I come from a slightly different angle, that in my mac+igc
> > port I had sometimes only 3 undos before I got "no more undo
> > information". and I thought I had messed up something.
>
> Same here, but igc/Linux. Please note that the recipe on my report is
> with yesterday's master, though.
I cannot reproduce on master. Maybe you should try invoking GC there
before you look at the value of buffer-undo-list.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:22:02 GMT)
Full text and
rfc822 format available.
Message #35 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
>>
>>> emacs -Q
>>>
>>> write in *scratch* some lines with random words:
>>>
>>> arins
>>> arseina
>>> aierni
>>>
>>> iosrn nioni
>>> ionugfw
>>>
>>> sronuf
>>>
>>> Now undo a few of those lines (C-_), move the cursor and C-_ again to
>>> redo.
>>
>> Interesting. I come from a slightly different angle, that in my mac+igc
>> port I had sometimes only 3 undos before I got "no more undo
>> information". and I thought I had messed up something.
>
> Same here, but igc/Linux. Please note that the recipe on my report is
> with yesterday's master, though.
If there's a problem with master, we should fix that first :-)
However, one reason that results may be somewhat unpredictable is that
buffer-undo-list can change when GC is triggered (on master): marker
entries don't prevent the marker from being collected and the list
entries are removed in that case.
>> So far I can't see what is the cause. I would have guessed something in
>> or around primitive-undo, but that hasn't changed forever.
>
> Eli in emacs-devel pointed to the possibility that something is creating
> lots of markers. Checking if those repeated elements in buffer-undo-list
> point to the same marker or to different ones would be revealing.
Calling sxhash-eq is probably the quickest way to establish whether two
markers are eq. If the same marker turned up twice in the same section
of an undo list, that would be a bug somewhere:
(dolist (el buffer-undo-list)
(and (consp el)
(markerp (car el))
(message "%S %S" (car el) (sxhash-eq (car el)))))
> Or not: I don't even know if getting markers to the same place in a
> buffer yield the same object or new ones.
New ones, in general.
Pip
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:24:02 GMT)
Full text and
rfc822 format available.
Message #38 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
>
>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>>
>>> Pip Cet <pipcet <at> protonmail.com> writes:
>>>
>>>> insertions.
>>>>
>>>>> So far I can't see what is the cause. I would have guessed something in
>>>>> or around primitive-undo, but that hasn't changed forever.
>>>>>
>>>>> Adding Stef.
>>>>
>>>> Well, compact_undo_list is a nop with HAVE_MPS:
>>>
>>> Sorry, I forgot to mention an important detail: this happens in master
>>> but not emacs-30. Oscar's report is also for master, IIRC.
>>>
>>> Really puzzling.
>>
>> However, it seems that on igc it is more easily reproducible.
>>
>> For a moment I thought that I messed up my bug report, because a couple
>> of attempts at reproducing the problem on master failed, but then I made
>> a few more undos/redos and the sequences of duplicated elements
>> appeared.
>>
>> Something triggers this and then explodes.
>
> Okay, thanks. At least I don't have to check if I made a cockpit error
> :-). But I guess I have to check emacs-30 again, if this is kind of
> "random".
Or it's related to what Pip said about compact_...
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:24:03 GMT)
Full text and
rfc822 format available.
Message #41 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>>> My cimpler recipe is
>>>
>>> 1. Make a new buffer x.el
>>> 2. Type an a
>>> 3. undo
>>> 4. C-h v buffer-undo-list
>>>
>>> =>
>>>
>>> Value:
>>> (nil ("a" . 1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>>> (#<marker at 1 in x.el> . -1) nil (1 . 2) (t . 0))
>>> Local in buffer x.el; global value is nil
>>
>> I can't reproduce this with my master's build:
>>
>> emacs -Q x.el
>>
>> type an a
>>
>> undo
>>
>> C-h v buffer-undo-list
>>
>> Its value is
>> (nil (#("a" 0 1 (fontified t)) . 1) (#<marker at 1 in x.el> . -1) nil
>> (1 . 2) (t . -1))
>> Local in buffer x.el; global value is nil
>>
>> However, doing the same with my igc build of 1 of August yields this:
>>
>> Its value is
>> (nil (#("a" 0 1 (fontified t)) . 1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1) nil
>> (1 . 2) (t . -1))
>> Local in buffer x.el; global value is nil
>
> Now I'm completely confused. Your report had
>
> In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
> version 1.18.4) of 2025-08-08 built on zen
> Repository revision: 12354bcfdc288f111c411c87e8bdebe6dcb41a4d
> Repository branch: master
>
> but it's not happending in master?
It doesn't happen here with your recipe, I need more elaborate sequences
of inputs mixed with undos/redos. I *think* that multiple undo
boundaries are a requisite.
> And I think, if didn't make a cockpit error, I tested that with master.
> Have to check this later, though.
Maybe from your build's revision to mine something changed. Or, perhaps,
there is a randomness component at play. I just executed emacs under
valgrind and it spewed lots of stuff.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:37:01 GMT)
Full text and
rfc822 format available.
Message #44 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Pip Cet <pipcet <at> protonmail.com> writes:
>> Eli in emacs-devel pointed to the possibility that something is creating
>> lots of markers. Checking if those repeated elements in buffer-undo-list
>> point to the same marker or to different ones would be revealing.
>
> Calling sxhash-eq is probably the quickest way to establish whether two
> markers are eq. If the same marker turned up twice in the same section
> of an undo list, that would be a bug somewhere:
>
> (dolist (el buffer-undo-list)
> (and (consp el)
> (markerp (car el))
> (message "%S %S" (car el) (sxhash-eq (car el)))))
Thanks. Below is the output of eval'ing your dolist in *scratch*, with
the contents of buffer-undo-list after that.
Indeed, there are elements with the same sxhash-eq.
Also puzzling to my ignorant eyes are the instances of "#<marker in no
buffer>"
But added to that is Eli's question: why so many markers? It's just
*scratch* with about 10 non-empty lines with a few characters each.
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker (moves after insertion) at 206 in *scratch*> 63047179
#<marker at 206 in *scratch*> 63063029
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker in no buffer> 63088759
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63062382
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 206 in *scratch*> 63084662
#<marker at 200 in *scratch*> 54326086
#<marker (moves after insertion) at 206 in *scratch*> 63099033
#<marker at 206 in *scratch*> 63099265
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker in no buffer> 63085240
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 63076420
#<marker at 206 in *scratch*> 63078272
#<marker at 206 in *scratch*> 63097527
#<marker at 206 in *scratch*> 63097003
#<marker at 206 in *scratch*> 63109330
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 206 in *scratch*> 62981980
#<marker at 200 in *scratch*> 54326086
#<marker (moves after insertion) at 206 in *scratch*> 63110895
#<marker at 206 in *scratch*> 63107698
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker in no buffer> 62981522
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 62948227
#<marker at 206 in *scratch*> 62947655
#<marker at 206 in *scratch*> 62949025
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker at 206 in *scratch*> 62981465
#<marker at 200 in *scratch*> 54326086
#<marker (moves after insertion) at 206 in *scratch*> 62948681
#<marker at 206 in *scratch*> 62954545
#<marker at 206 in *scratch*> 62987879
#<marker in no buffer> 62987620
#<marker at 200 in *scratch*> 54326086
#<marker at 206 in *scratch*> 62987879
nil
(nil (200 . 206) nil (199 . 200) nil (198 . 199) nil (196 . 198) nil
(191 . 196) nil (190 . 191) nil (183 . 190) nil (182 . 183) nil
(181 . 182) nil (180 . 181) nil (176 . 180) nil (174 . 176) nil (#("
"
0
2
(fontified
t))
.
174)
(#<marker at 200 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2) nil
(#("aten" 0 4 (fontified t)) . 176)
(#<marker at 200 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -4) nil (#("
"
0 1 (fontified t))
. 180)
(#<marker at 200 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1) nil
(#("a" 0 1 (fontified t)) . 181)
(#<marker at 200 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1) nil (#("
"
0 1 (fontified t))
. 182)
(#<marker at 200 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1) nil
(#("tseaint" 0 7 (fontified t)) . 183)
(#<marker at 200 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7)
(#<marker at 206 in *scratch*> . -7) nil (#("
"
0 1 (fontified t))
. 190)
(#<marker at 200 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1) nil
(#("arsei" 0 5 (fontified t)) . 191)
(#<marker at 200 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5) nil (#("
"
0 2 (fontified t))
. 196)
(#<marker at 200 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -2) nil
(#("a" 0 1 (fontified t)) . 198)
(#<marker at 200 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1) nil (#("
"
0 1 (fontified t))
. 199)
(#<marker at 200 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1) nil
(#("atesnt" 0 6 (fontified t)) . 200)
(#<marker at 200 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6)
(#<marker at 206 in *scratch*> . -6) nil (#("
"
0 1 (fontified t))
. 206)
(#<marker at 200 in *scratch*> . -1)
(#<marker (moves after insertion) at 206 in *scratch*> . 1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker in no buffer> . -1) nil
(#("a" 0 1 (fontified t)) . 207)
(#<marker at 200 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1) nil (#("
"
0 1 (fontified t))
. 208)
(#<marker at 200 in *scratch*> . -1)
(#<marker (moves after insertion) at 206 in *scratch*> . 1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker in no buffer> . -1) nil
(#("enars" 0 5 (fontified t)) . 209)
(#<marker at 200 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -3)
(#<marker at 206 in *scratch*> . -4)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5)
(#<marker at 206 in *scratch*> . -5) nil (#("
"
0 1 (fontified t))
. 214)
(#<marker at 200 in *scratch*> . -1)
(#<marker (moves after insertion) at 206 in *scratch*> . 1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker in no buffer> . -1) nil
(#("etn" 0 3 (fontified t)) . 215)
(#<marker at 200 in *scratch*> . -3)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -2)
(#<marker at 206 in *scratch*> . -3)
(#<marker at 206 in *scratch*> . -3)
(#<marker at 206 in *scratch*> . -3)
(#<marker at 206 in *scratch*> . -3) nil (#("
"
0 1 (fontified t))
. 218)
(#<marker at 200 in *scratch*> . -1)
(#<marker (moves after insertion) at 206 in *scratch*> . 1)
(#<marker at 206 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1)
(#<marker in no buffer> . -1) nil
(#("a" 0 1 (fontified t)) . 219)
(#<marker at 200 in *scratch*> . -1)
(#<marker at 206 in *scratch*> . -1) nil (219 . 220) nil
(218 . 219) nil (215 . 218) nil (214 . 215) nil (209 . 214) nil
(208 . 209) nil (207 . 208) nil (206 . 207) nil (200 . 206) nil
(199 . 200) nil (198 . 199) nil (196 . 198) nil (191 . 196) nil
(190 . 191) nil (183 . 190) nil (182 . 183) nil (181 . 182) nil
(180 . 181) nil (176 . 180) nil (174 . 176) nil (167 . 174) nil
(166 . 167) nil (165 . 166) nil (163 . 165) nil (162 . 163) nil
(161 . 162) nil (160 . 161) nil (154 . 160) nil (153 . 154) nil
(148 . 153) (t . 0) nil (1 . 148) (t . 0))
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 09:48:02 GMT)
Full text and
rfc822 format available.
Message #47 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
> Your bug report says this is on master branch:
>
>> In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
>> version 1.18.4) of 2025-08-08 built on zen
>> Repository revision: 12354bcfdc288f111c411c87e8bdebe6dcb41a4d
>> Repository branch: master
>
> But I can only reproduce this on the igc branch. On master, I see a
> single entry for marker adjustment, not many identical ones.
On master you need more elaborate sequences of typing, undoing and
redoing, but it is definitively reproducible.
Maybe it is easier on igc because it does not do compactation, as Pip
noted.
Also tried your suggestion of calling garbage-collect (on master) before
looking at buffer-undo-list. The sequences of duplicated elements
remained.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 10:14:02 GMT)
Full text and
rfc822 format available.
Message #50 received at submit <at> debbugs.gnu.org (full text, mbox):
Pip Cet via "Bug reports for GNU Emacs, the Swiss army knife of text
editors" <bug-gnu-emacs <at> gnu.org> writes:
> Well, compact_undo_list is a nop with HAVE_MPS:
>
> static Lisp_Object
> compact_undo_list (Lisp_Object list)
> {
> #ifndef HAVE_MPS
> Lisp_Object tail, *prev = &list;
>
> for (tail = list; CONSP (tail); tail = XCDR (tail))
> {
> if (CONSP (XCAR (tail))
> && MARKERP (XCAR (XCAR (tail)))
> && !vectorlike_marked_p (&XMARKER (XCAR (XCAR (tail)))->header))
> *prev = XCDR (tail);
> else
> prev = xcdr_addr (tail);
> }
> #endif
> return list;
> }
>
> We still truncate undo lists, but we don't "compact" them, i.e. treat
> them as weak structures and remove markers that are referred to only in
> undo lists. Correct?
I think you are correct. buffer_step -> compact_buffer ->
truncate_undo_list, but no compact.
> The "obvious" fix would be to use a weak hash table to associate undo
> information with markers rather than keeping them in the undo
> list. However, that sounds quite hard to do, and it might make undo a
> lot more expensive.
Hm, yes that sounds hard. Hm.
Do you think we could, in compact, locally keep track of markers already
seen, and coalesce their entries somehow? My memory of the undo stuff is
pretty hazy, alas, and probably outdated, too.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 10:14:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 10:19:01 GMT)
Full text and
rfc822 format available.
Message #56 received at submit <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Pip Cet via "Bug reports for GNU Emacs, the Swiss army knife of text
> editors" <bug-gnu-emacs <at> gnu.org> writes:
>
>> Well, compact_undo_list is a nop with HAVE_MPS:
>>
>> static Lisp_Object
>> compact_undo_list (Lisp_Object list)
>> {
>> #ifndef HAVE_MPS
>> Lisp_Object tail, *prev = &list;
>>
>> for (tail = list; CONSP (tail); tail = XCDR (tail))
>> {
>> if (CONSP (XCAR (tail))
>> && MARKERP (XCAR (XCAR (tail)))
>> && !vectorlike_marked_p (&XMARKER (XCAR (XCAR (tail)))->header))
>> *prev = XCDR (tail);
>> else
>> prev = xcdr_addr (tail);
>> }
>> #endif
>> return list;
>> }
>>
>> We still truncate undo lists, but we don't "compact" them, i.e. treat
>> them as weak structures and remove markers that are referred to only in
>> undo lists. Correct?
>
> I think you are correct. buffer_step -> compact_buffer ->
> truncate_undo_list, but no compact.
>
>> The "obvious" fix would be to use a weak hash table to associate undo
>> information with markers rather than keeping them in the undo
>> list. However, that sounds quite hard to do, and it might make undo a
>> lot more expensive.
>
> Hm, yes that sounds hard. Hm.
>
> Do you think we could, in compact, locally keep track of markers already
> seen, and coalesce their entries somehow? My memory of the undo stuff is
> pretty hazy, alas, and probably outdated, too.
This is in primtive-undo for markers
simple.el:
3758 ;; Adjust the valid marker adjustments
3759 (dolist (adj valid-marker-adjustments)
3760 ;; Insert might have invalidated some of the markers
3761 ;; via modification hooks. Update only the currently
3762 ;; valid ones (bug#25599).
3763 (if (marker-buffer (car adj))
3764 (set-marker (car adj)
3765 (- (car adj) (cdr adj)))))))
So, it would seem that one could do that. Famous last words :-).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 10:19:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 10:51:02 GMT)
Full text and
rfc822 format available.
Message #62 received at submit <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Pip Cet via "Bug reports for GNU Emacs, the Swiss army knife of text
> editors" <bug-gnu-emacs <at> gnu.org> writes:
>
>> Well, compact_undo_list is a nop with HAVE_MPS:
>>
>> static Lisp_Object
>> compact_undo_list (Lisp_Object list)
>> {
>> #ifndef HAVE_MPS
>> Lisp_Object tail, *prev = &list;
>>
>> for (tail = list; CONSP (tail); tail = XCDR (tail))
>> {
>> if (CONSP (XCAR (tail))
>> && MARKERP (XCAR (XCAR (tail)))
>> && !vectorlike_marked_p (&XMARKER (XCAR (XCAR (tail)))->header))
>> *prev = XCDR (tail);
>> else
>> prev = xcdr_addr (tail);
>> }
>> #endif
>> return list;
>> }
>>
>> We still truncate undo lists, but we don't "compact" them, i.e. treat
>> them as weak structures and remove markers that are referred to only in
>> undo lists. Correct?
>
> I think you are correct. buffer_step -> compact_buffer ->
> truncate_undo_list, but no compact.
>
>> The "obvious" fix would be to use a weak hash table to associate undo
>> information with markers rather than keeping them in the undo
>> list. However, that sounds quite hard to do, and it might make undo a
>> lot more expensive.
>
> Hm, yes that sounds hard. Hm.
>
> Do you think we could, in compact, locally keep track of markers already
> seen, and coalesce their entries somehow? My memory of the undo stuff is
> pretty hazy, alas, and probably outdated, too.
So far, I've seen no markers showing up twice in the same section of the
undo list; that would be a bug in BUF_MARKERS, I think. So I'm not sure
how coalescing would work.
Over here, most of the markers in the undo list appear to be constructed
in the format_mode_line_unwind_data function. So maybe something like
this is needed:
From d5cf17f88fbba4cdfc61ebea725e12a2c8b9aa42 Mon Sep 17 00:00:00 2001
From: Pip Cet <pipcet <at> protonmail.com>
Date: Sat, 9 Aug 2025 10:32:19 +0000
Subject: [PATCH] Detach markers explicitly so they don't wind up on the undo
list
* src/xdisp.c (unwind_format_mode_line): Detach markers when we're
done with them.
---
src/xdisp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/xdisp.c b/src/xdisp.c
index 432dd5dceca..2406bb6f3d9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -13828,6 +13828,7 @@ unwind_format_mode_line (Lisp_Object vector)
current_buffer = XBUFFER (buffer);
set_point_from_marker (AREF (vector, 11));
+ detach_marker (AREF (vector, 11));
ASET (vector, 11, Qnil);
current_buffer = cb;
}
--
2.50.0
Famous last words: I think this is safe and AREF (vector, 11) is never
leaked to Lisp. And I'm not sure whether the only reason it helps here
might be a local peculiarity...
Of course, none of this is very satisfying: we can perform manual memory
management for markers in C code, but it's very hard to do so from Lisp
code.
Pip
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 10:51:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 10:54:02 GMT)
Full text and
rfc822 format available.
Message #68 received at submit <at> debbugs.gnu.org (full text, mbox):
Reverting this commit fixes the problem, both in master and igc:
commit 6f494d74f645d6cffd98e168721a0347de271a54
Author: Pengji Zhang <me <at> pengjiz.com>
Date: Sat Mar 29 19:04:58 2025 +0800
New user option to hide minor mode lighters (bug#77361)
* lisp/bindings.el (mode-line-collapse-minor-modes): New user
option.
(mode-line-minor-modes): New variable to hold mode line
constructs for minor modes.
(mode-line--make-lighter-menu): New helper function to generate
the menu for hidden minor modes.
(mode-line--minor-modes): New helper function to computer mode
line constructs for minor mode lighters.
(mode-line-modes): Use the new variable 'mode-line-minor-modes',
and adjust the order of elements so the indicator for hidden
minor modes is shown towards the end.
* doc/lispref/modes.texi (Mode Line Basics): Move the paragraph
for 'mode-line-compact' from here...
* doc/emacs/display.texi (Optional Mode Line): ...to here, and
document the new user option.
* etc/NEWS: Annouce the new user option.
Seriously.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 10:54:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 11:16:02 GMT)
Full text and
rfc822 format available.
Message #74 received at submit <at> debbugs.gnu.org (full text, mbox):
Pip Cet <pipcet <at> protonmail.com> writes:
>>> The "obvious" fix would be to use a weak hash table to associate undo
>>> information with markers rather than keeping them in the undo
>>> list. However, that sounds quite hard to do, and it might make undo a
>>> lot more expensive.
>>
>> Hm, yes that sounds hard. Hm.
>>
>> Do you think we could, in compact, locally keep track of markers already
>> seen, and coalesce their entries somehow? My memory of the undo stuff is
>> pretty hazy, alas, and probably outdated, too.
>
> So far, I've seen no markers showing up twice in the same section of the
> undo list; that would be a bug in BUF_MARKERS, I think. So I'm not sure
> how coalescing would work.
Okay. The primitive-undo code of course only indicates that it can
happen, not how often.
> Over here, most of the markers in the undo list appear to be constructed
> in the format_mode_line_unwind_data function. So maybe something like
> this is needed:
>
> From d5cf17f88fbba4cdfc61ebea725e12a2c8b9aa42 Mon Sep 17 00:00:00 2001
> From: Pip Cet <pipcet <at> protonmail.com>
> Date: Sat, 9 Aug 2025 10:32:19 +0000
> Subject: [PATCH] Detach markers explicitly so they don't wind up on the undo
> list
>
> * src/xdisp.c (unwind_format_mode_line): Detach markers when we're
> done with them.
> ---
> src/xdisp.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/src/xdisp.c b/src/xdisp.c
> index 432dd5dceca..2406bb6f3d9 100644
> --- a/src/xdisp.c
> +++ b/src/xdisp.c
> @@ -13828,6 +13828,7 @@ unwind_format_mode_line (Lisp_Object vector)
>
> current_buffer = XBUFFER (buffer);
> set_point_from_marker (AREF (vector, 11));
> + detach_marker (AREF (vector, 11));
> ASET (vector, 11, Qnil);
> current_buffer = cb;
> }
I think that should be done. The 11 is always made with build_marker, so
it's guaranteed to be correct, and a win.
(And Gnus seems to not cite anything after an inline patch Also
interesting :-/).
> Famous last words: I think this is safe and AREF (vector, 11) is never
> leaked to Lisp. And I'm not sure whether the only reason it helps here
> might be a local peculiarity...
I think it should go in. I've also checked it's safe.
And I'll run with it in my Emacs.
> Of course, none of this is very satisfying: we can perform manual memory
> management for markers in C code, but it's very hard to do so from Lisp
> code.
Yes, the more general problem is that old GC is "eagerly weak" so to
speak, while MPS Is "lazily weak". I have no idea what to do about that.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 11:16:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 11:17:02 GMT)
Full text and
rfc822 format available.
Message #80 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> telefonica.net> writes:
> Reverting this commit fixes the problem, both in master and igc:
>
> commit 6f494d74f645d6cffd98e168721a0347de271a54
> Author: Pengji Zhang <me <at> pengjiz.com>
> Date: Sat Mar 29 19:04:58 2025 +0800
>
> New user option to hide minor mode lighters (bug#77361)
>
> * lisp/bindings.el (mode-line-collapse-minor-modes): New user
> option.
> (mode-line-minor-modes): New variable to hold mode line
> constructs for minor modes.
> (mode-line--make-lighter-menu): New helper function to generate
> the menu for hidden minor modes.
> (mode-line--minor-modes): New helper function to computer mode
> line constructs for minor mode lighters.
> (mode-line-modes): Use the new variable 'mode-line-minor-modes',
> and adjust the order of elements so the indicator for hidden
> minor modes is shown towards the end.
>
> * doc/lispref/modes.texi (Mode Line Basics): Move the paragraph
> for 'mode-line-compact' from here...
> * doc/emacs/display.texi (Optional Mode Line): ...to here, and
> document the new user option.
> * etc/NEWS: Annouce the new user option.
>
>
>
> Seriously.
Makes sense: no idea what that is, but it's something with mode-lines,
and what Pip found out is also the mode-line department.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 11:18:01 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 11:21:01 GMT)
Full text and
rfc822 format available.
Message #86 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> From: Óscar Fuentes <oscarfv <at> telefonica.net>
> Cc: 79200 <at> debbugs.gnu.org
> Date: Sat, 09 Aug 2025 11:47:21 +0200
> X-Spam-Status: No
>
> Eli Zaretskii <eliz <at> gnu.org> writes:
>
> > Your bug report says this is on master branch:
> >
> >> In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, X toolkit, cairo
> >> version 1.18.4) of 2025-08-08 built on zen
> >> Repository revision: 12354bcfdc288f111c411c87e8bdebe6dcb41a4d
> >> Repository branch: master
> >
> > But I can only reproduce this on the igc branch. On master, I see a
> > single entry for marker adjustment, not many identical ones.
>
> On master you need more elaborate sequences of typing, undoing and
> redoing, but it is definitively reproducible.
Why does one need more elaborate sequences on master?
> Maybe it is easier on igc because it does not do compactation, as Pip
> noted.
If compacting the undo-list solves the issue on master, I don't see
this as a grave problem on master.
> Also tried your suggestion of calling garbage-collect (on master) before
> looking at buffer-undo-list. The sequences of duplicated elements
> remained.
On the master branch or on the igc branch?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 11:39:01 GMT)
Full text and
rfc822 format available.
Message #89 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
>> > But I can only reproduce this on the igc branch. On master, I see a
>> > single entry for marker adjustment, not many identical ones.
>>
>> On master you need more elaborate sequences of typing, undoing and
>> redoing, but it is definitively reproducible.
>
> Why does one need more elaborate sequences on master?
I don't know why. I mentioned the lack of compaction in igc as a
possible factor.
>> Maybe it is easier on igc because it does not do compactation, as Pip
>> noted.
>
> If compacting the undo-list solves the issue on master, I don't see
> this as a grave problem on master.
The copious sequences of #marker elements happen on master too (the
contents of `buffer-undo-list` that I copied on the previous messages
are from master.) I don't know if they end inundating buffer-undo-list
to the point of losing undo info like they do in igc, though, but looks
like a bug to me even if there are no user-observable effects. Those
sequences use memory and require cpu time, for sure.
>> Also tried your suggestion of calling garbage-collect (on master) before
>> looking at buffer-undo-list. The sequences of duplicated elements
>> remained.
>
> On the master branch or on the igc branch?
On master, as mentioned.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 11:43:01 GMT)
Full text and
rfc822 format available.
Message #92 received at submit <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Makes sense: no idea what that is, but it's something with mode-lines,
> and what Pip found out is also the mode-line department.
And with Pip's patch applied, I can now longer reproduce the problem.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 11:43:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:01:02 GMT)
Full text and
rfc822 format available.
Message #98 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Makes sense: no idea what that is, but it's something with mode-lines,
>> and what Pip found out is also the mode-line department.
>
> And with Pip's patch applied, I can now longer reproduce the problem.
Applied the patch to igc (adding the call to detach_marker.) It took a
while of monkeying around, but eventually...
(nil (363 . 364) nil (354 . 363) nil (353 . 354) nil (352 . 353) nil
(351 . 352) nil (#("
"
0 1 (fontified t))
. 351)
(#<marker (moves after insertion) at 351 in *scratch*> . 1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 363 in *scratch*> . -1)
(#<marker at 363 in *scratch*> . -1)
(#<marker in no buffer> . -1) nil
(#("n" 0 1 (fontified t)) . 352)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 363 in *scratch*> . -1)
etc.
Bummer.
Looks like the patch puts igc on the same footing as master wrt the
required work to reproduce the problem.
As a side note, executing igc-collect removed some elements:
(nil (363 . 364) nil (354 . 363) nil (353 . 354) nil (352 . 353) nil
(351 . 352) nil (#("
"
0 1 (fontified t))
. 351)
(#<marker (moves after insertion) at 351 in *scratch*> . 1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker at 364 in *scratch*> . -1)
(#<marker in no buffer> . -1) (#<marker in no buffer> . -1)
(#<marker in no buffer> . -1) nil
(#("n" 0 1 (fontified t)) . 352)
etc.
Note that on my first copy&paste of buffer-undo-list the first sequence
of repeated elements was 8, but above it shows 6. The other repeated
sequences show a similar change.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:02:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:30:02 GMT)
Full text and
rfc822 format available.
Message #104 received at submit <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> telefonica.net> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>>
>>> Makes sense: no idea what that is, but it's something with mode-lines,
>>> and what Pip found out is also the mode-line department.
>>
>> And with Pip's patch applied, I can now longer reproduce the problem.
>
> Applied the patch to igc (adding the call to detach_marker.) It took a
> while of monkeying around, but eventually...
I'm afraid I must be monkeying around differently; I haven't found a way
to produce similar undo lists with the patch applied on feature/igc.
Our options here are either to find a recipe which results in what
appears to be an undesirable undo list, or to run Emacs in rr and
produce one in some way, then inspect the rr session to see where the
undesirable markers were produced and whether there's a way to clean up
when they're no longer in use.
> (nil (363 . 364) nil (354 . 363) nil (353 . 354) nil (352 . 353) nil
> (351 . 352) nil (#("
> "
> 0 1 (fontified t))
> . 351)
> (#<marker (moves after insertion) at 351 in *scratch*> . 1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 363 in *scratch*> . -1)
> (#<marker at 363 in *scratch*> . -1)
That's 6 markers at position 364, then two at position 363.
Note that it's not necessarily a bug for several markers to share a
position; it is inefficient for too many of those to show up in an undo
list, but I'm not sure it can always be avoided.
> (#<marker in no buffer> . -1) nil
> (#("n" 0 1 (fontified t)) . 352)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 363 in *scratch*> . -1)
> etc.
>
>
> Bummer.
>
> Looks like the patch puts igc on the same footing as master wrt the
> required work to reproduce the problem.
>
> As a side note, executing igc-collect removed some elements:
It moved some markers to point nowhere (I'm not sure how, or whether it
was igc-collect itself rather than unrelated code that ran, maybe
because of auto-saving or a timer).
> (nil (363 . 364) nil (354 . 363) nil (353 . 354) nil (352 . 353) nil
> (351 . 352) nil (#("
> "
> 0 1 (fontified t))
> . 351)
> (#<marker (moves after insertion) at 351 in *scratch*> . 1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker in no buffer> . -1) (#<marker in no buffer> . -1)
> (#<marker in no buffer> . -1) nil
> (#("n" 0 1 (fontified t)) . 352)
> etc.
>
> Note that on my first copy&paste of buffer-undo-list the first sequence
> of repeated elements was 8, but above it shows 6. The other repeated
> sequences show a similar change.
I don't see a run of 8 markers at the same position.
Pip
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:30:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:32:01 GMT)
Full text and
rfc822 format available.
Message #110 received at submit <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> telefonica.net> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>>
>>> Makes sense: no idea what that is, but it's something with mode-lines,
>>> and what Pip found out is also the mode-line department.
>>
>> And with Pip's patch applied, I can now longer reproduce the problem.
>
> Applied the patch to igc (adding the call to detach_marker.) It took a
> while of monkeying around, but eventually...
>
>
> (nil (363 . 364) nil (354 . 363) nil (353 . 354) nil (352 . 353) nil
> (351 . 352) nil (#("
> "
> 0 1 (fontified t))
> . 351)
> (#<marker (moves after insertion) at 351 in *scratch*> . 1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 363 in *scratch*> . -1)
> (#<marker at 363 in *scratch*> . -1)
> (#<marker in no buffer> . -1) nil
> (#("n" 0 1 (fontified t)) . 352)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 363 in *scratch*> . -1)
> etc.
>
>
> Bummer.
>
> Looks like the patch puts igc on the same footing as master wrt the
> required work to reproduce the problem.
That's something, thanks to Pip!
Can you determine if these are different markers (sxhash-eq)?
> As a side note, executing igc-collect removed some elements:
>
> (nil (363 . 364) nil (354 . 363) nil (353 . 354) nil (352 . 353) nil
> (351 . 352) nil (#("
> "
> 0 1 (fontified t))
> . 351)
> (#<marker (moves after insertion) at 351 in *scratch*> . 1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker at 364 in *scratch*> . -1)
> (#<marker in no buffer> . -1) (#<marker in no buffer> . -1)
> (#<marker in no buffer> . -1) nil
> (#("n" 0 1 (fontified t)) . 352)
> etc.
>
> Note that on my first copy&paste of buffer-undo-list the first sequence
> of repeated elements was 8, but above it shows 6. The other repeated
> sequences show a similar change.
I would guess igc_collect also does a "weak collection". But it's only a
guess.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:32:03 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:50:02 GMT)
Full text and
rfc822 format available.
Message #116 received at submit <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Can you determine if these are different markers (sxhash-eq)?
And within a group? To find out if it would be worthwhle to coalesce
adjustments.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:50:03 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:50:04 GMT)
Full text and
rfc822 format available.
Message #122 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>> Looks like the patch puts igc on the same footing as master wrt the
>> required work to reproduce the problem.
>
> That's something, thanks to Pip!
>
> Can you determine if these are different markers (sxhash-eq)?
Yes, sxhash-eq indicates that there are repeated markers, but not into
the same sequence. Actually, the sequences themselves are repeated:
(this is on igc with Pip's patch applied, but without reverting the
commit I identified)
#<marker (moves after insertion) at 351 in *scratch*> 418927
#<marker at 364 in *scratch*> 663376
#<marker at 364 in *scratch*> 663379
#<marker at 364 in *scratch*> 678696
#<marker at 364 in *scratch*> 678699
#<marker at 364 in *scratch*> 683321
#<marker at 364 in *scratch*> 683322
#<marker in no buffer> 125961
#<marker in no buffer> 125960
#<marker in no buffer> 732225
#<marker at 364 in *scratch*> 663376
#<marker at 364 in *scratch*> 663379
#<marker at 364 in *scratch*> 678696
#<marker at 364 in *scratch*> 678699
#<marker at 364 in *scratch*> 683321
#<marker at 364 in *scratch*> 683322
#<marker in no buffer> 125961
#<marker in no buffer> 125960
#<marker (moves after insertion) at 353 in *scratch*> 420616
#<marker at 364 in *scratch*> 663376
#<marker at 364 in *scratch*> 663379
#<marker at 364 in *scratch*> 678696
#<marker at 364 in *scratch*> 678699
#<marker at 364 in *scratch*> 683321
#<marker at 364 in *scratch*> 683322
#<marker in no buffer> 125961
#<marker in no buffer> 125960
#<marker in no buffer> 735044
#<marker at 364 in *scratch*> 663376
#<marker at 364 in *scratch*> 663379
#<marker at 364 in *scratch*> 678696
#<marker at 364 in *scratch*> 678699
#<marker at 364 in *scratch*> 683321
#<marker at 364 in *scratch*> 683322
#<marker in no buffer> 125961
#<marker in no buffer> 125960
#<marker (moves after insertion) at 363 in *scratch*> 425399
#<marker at 364 in *scratch*> 663376
#<marker at 364 in *scratch*> 663379
#<marker at 364 in *scratch*> 678696
#<marker at 364 in *scratch*> 678699
#<marker at 364 in *scratch*> 683321
#<marker at 364 in *scratch*> 683322
#<marker in no buffer> 125961
#<marker in no buffer> 125960
#<marker in no buffer> 733791
#<marker at 364 in *scratch*> 663376
#<marker at 364 in *scratch*> 663379
#<marker at 364 in *scratch*> 678696
#<marker at 364 in *scratch*> 678699
#<marker at 364 in *scratch*> 683321
#<marker at 364 in *scratch*> 683322
#<marker in no buffer> 125961
#<marker in no buffer> 125960
#<marker (moves after insertion) at 364 in *scratch*> 411420
#<marker (moves after insertion) at 364 in *scratch*> 411101
#<marker (moves after insertion) at 364 in *scratch*> 416868
#<marker at 364 in *scratch*> 663376
#<marker at 364 in *scratch*> 663379
#<marker at 364 in *scratch*> 678696
#<marker at 364 in *scratch*> 678699
#<marker at 364 in *scratch*> 683321
#<marker at 364 in *scratch*> 683322
#<marker in no buffer> 125961
#<marker in no buffer> 125960
#<marker in no buffer> 736545
#<marker in no buffer> 125960
#<marker (moves after insertion) at 338 in *scratch*> 438736
#<marker at 339 in *scratch*> 398619
#<marker at 340 in *scratch*> 398618
#<marker in no buffer> 396666
#<marker in no buffer> 125960
#<marker at 340 in *scratch*> 398618
#<marker in no buffer> 125967
#<marker in no buffer> 125960
#<marker (moves after insertion) at 340 in *scratch*> 439505
#<marker (moves after insertion) at 341 in *scratch*> 437760
#<marker (moves after insertion) at 342 in *scratch*> 436696
#<marker in no buffer> 399181
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 351 in *scratch*> 418927
#<marker in no buffer> 397926
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 353 in *scratch*> 420616
#<marker in no buffer> 400830
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 363 in *scratch*> 425399
#<marker in no buffer> 399510
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 364 in *scratch*> 411420
#<marker (moves after insertion) at 364 in *scratch*> 411101
#<marker (moves after insertion) at 364 in *scratch*> 416868
#<marker in no buffer> 404453
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 364 in *scratch*> 406678
#<marker (moves after insertion) at 364 in *scratch*> 408097
#<marker in no buffer> 405207
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 231 in *scratch*> 240196
#<marker in no buffer> 218066
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 236 in *scratch*> 221331
#<marker in no buffer> 218138
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 364 in *scratch*> 222596
#<marker (moves after insertion) at 365 in *scratch*> 223098
#<marker (moves after insertion) at 366 in *scratch*> 223963
#<marker in no buffer> 218723
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 367 in *scratch*> 226017
#<marker in no buffer> 220121
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 367 in *scratch*> 216127
#<marker in no buffer> 219420
#<marker in no buffer> 125960 [2 times]
#<marker (moves after insertion) at 367 in *scratch*> 220218
#<marker in no buffer> 220281
#<marker in no buffer> 125960
nil
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:51:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:55:02 GMT)
Full text and
rfc822 format available.
Message #128 received at submit <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes Óscar Fuentes <oscarfv <at> telefonica.net> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>>> Looks like the patch puts igc on the same footing as master wrt the
>>> required work to reproduce the problem.
>>
>> That's something, thanks to Pip!
>>
>> Can you determine if these are different markers (sxhash-eq)?
>
> Yes, sxhash-eq indicates that there are repeated markers, but not into
> the same sequence. Actually, the sequences themselves are repeated:
>
> (this is on igc with Pip's patch applied, but without reverting the
> commit I identified)
Thanks. If they are not in the same group then trying to coalesce
entries is not worth it, I think.
Maybe another case like that of the mode-line. Without something rr
pretty hard to debug (no rr on macOS :-/).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 12:55:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 13:19:02 GMT)
Full text and
rfc822 format available.
Message #134 received at submit <at> debbugs.gnu.org (full text, mbox):
Pip Cet <pipcet <at> protonmail.com> writes:
> Óscar Fuentes <oscarfv <at> telefonica.net> writes:
>
>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>>
>>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>>>
>>>> Makes sense: no idea what that is, but it's something with mode-lines,
>>>> and what Pip found out is also the mode-line department.
>>>
>>> And with Pip's patch applied, I can now longer reproduce the problem.
>>
>> Applied the patch to igc (adding the call to detach_marker.) It took a
>> while of monkeying around, but eventually...
>
> I'm afraid I must be monkeying around differently; I haven't found a way
> to produce similar undo lists with the patch applied on feature/igc.
>
> Our options here are either to find a recipe which results in what
> appears to be an undesirable undo list, or to run Emacs in rr and
> produce one in some way, then inspect the rr session to see where the
> undesirable markers were produced and whether there's a way to clean up
> when they're no longer in use.
>
>> (nil (363 . 364) nil (354 . 363) nil (353 . 354) nil (352 . 353) nil
>> (351 . 352) nil (#("
>> "
>> 0 1 (fontified t))
>> . 351)
>> (#<marker (moves after insertion) at 351 in *scratch*> . 1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 363 in *scratch*> . -1)
>> (#<marker at 363 in *scratch*> . -1)
>
> That's 6 markers at position 364, then two at position 363.
>
> Note that it's not necessarily a bug for several markers to share a
> position; it is inefficient for too many of those to show up in an undo
> list, but I'm not sure it can always be avoided.
>
>> (#<marker in no buffer> . -1) nil
>> (#("n" 0 1 (fontified t)) . 352)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 363 in *scratch*> . -1)
>> etc.
>>
>>
>> Bummer.
>>
>> Looks like the patch puts igc on the same footing as master wrt the
>> required work to reproduce the problem.
>>
>> As a side note, executing igc-collect removed some elements:
>
> It moved some markers to point nowhere (I'm not sure how, or whether it
> was igc-collect itself rather than unrelated code that ran, maybe
> because of auto-saving or a timer).
>
>> (nil (363 . 364) nil (354 . 363) nil (353 . 354) nil (352 . 353) nil
>> (351 . 352) nil (#("
>> "
>> 0 1 (fontified t))
>> . 351)
>> (#<marker (moves after insertion) at 351 in *scratch*> . 1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker at 364 in *scratch*> . -1)
>> (#<marker in no buffer> . -1) (#<marker in no buffer> . -1)
>> (#<marker in no buffer> . -1) nil
>> (#("n" 0 1 (fontified t)) . 352)
>> etc.
>>
>> Note that on my first copy&paste of buffer-undo-list the first sequence
>> of repeated elements was 8, but above it shows 6. The other repeated
>> sequences show a similar change.
>
> I don't see a run of 8 markers at the same position.
>
> Pip
Another thought: the format_mode_line_unwind is only called from
display_mode_line (redisplay) and format-mode-line. Why does soemthing
land in the undo list at all? DOes that make sense at all?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 13:19:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 13:35:02 GMT)
Full text and
rfc822 format available.
Message #140 received at submit <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Another thought: the format_mode_line_unwind is only called from
> display_mode_line (redisplay) and format-mode-line. Why does soemthing
> land in the undo list at all? DOes that make sense at all?
jit-lock uses this, which turns undo recording off
subr.el:
5253 (defmacro with-silent-modifications (&rest body)
5254 "Execute BODY, pretending it does not modify the buffer.
5255 This macro is typically used around modifications of
5256 text properties that do not really affect the buffer's content.
5257 If BODY performs real modifications to the buffer's text, other
5258 than cosmetic ones, undo data may become corrupted.
5259
5260 This macro will run BODY normally, but doesn't count its buffer
5261 modifications as being buffer modifications. This affects things
5262 like `buffer-modified-p', checking whether the file is locked by
5263 someone else, running buffer modification hooks, and other things
5264 of that nature."
5265 (declare (debug t) (indent 0))
5266 (let ((modified (make-symbol "modified")))
5267 `(let* ((,modified (buffer-modified-p))
5268 (buffer-undo-list t)
^^^^^^^^^^^^^^^^^^
Maybe there specbinds missing somewhere.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 13:35:03 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 13:47:02 GMT)
Full text and
rfc822 format available.
Message #146 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> Cc: 79200 <at> debbugs.gnu.org, oscarfv <at> telefonica.net, monnier <at> iro.umontreal.ca,
> me <at> pengjiz.com
> From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
> Date: Sat, 09 Aug 2025 15:18:39 +0200
>
> Another thought: the format_mode_line_unwind is only called from
> display_mode_line (redisplay) and format-mode-line. Why does soemthing
> land in the undo list at all? DOes that make sense at all?
Because it creates a marker:
ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
And then, when you delete text at point, Emacs adjusts all the
markers, and puts the relevant elements into buffer-undo-list. So if
you have many markers there, you will have many elements in
buffer-undo-list, one element for each marker.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 13:52:02 GMT)
Full text and
rfc822 format available.
Message #149 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> Cc: 79200 <at> debbugs.gnu.org, oscarfv <at> telefonica.net, monnier <at> iro.umontreal.ca,
> me <at> pengjiz.com
> From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
> Date: Sat, 09 Aug 2025 15:33:56 +0200
>
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
> > Another thought: the format_mode_line_unwind is only called from
> > display_mode_line (redisplay) and format-mode-line. Why does soemthing
> > land in the undo list at all? DOes that make sense at all?
>
> jit-lock uses this, which turns undo recording off
>
> subr.el:
> 5253 (defmacro with-silent-modifications (&rest body)
> 5254 "Execute BODY, pretending it does not modify the buffer.
> 5255 This macro is typically used around modifications of
> 5256 text properties that do not really affect the buffer's content.
> 5257 If BODY performs real modifications to the buffer's text, other
> 5258 than cosmetic ones, undo data may become corrupted.
> 5259
> 5260 This macro will run BODY normally, but doesn't count its buffer
> 5261 modifications as being buffer modifications. This affects things
> 5262 like `buffer-modified-p', checking whether the file is locked by
> 5263 someone else, running buffer modification hooks, and other things
> 5264 of that nature."
> 5265 (declare (debug t) (indent 0))
> 5266 (let ((modified (make-symbol "modified")))
> 5267 `(let* ((,modified (buffer-modified-p))
> 5268 (buffer-undo-list t)
> ^^^^^^^^^^^^^^^^^^
> Maybe there specbinds missing somewhere.
I don't think so. The additions to buffer-undo-list are because of
deleting some text, and that cannot be disabled. The problem we see
is because there are many-many markers where the text is deleted.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 14:07:03 GMT)
Full text and
rfc822 format available.
Message #152 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
>> Cc: 79200 <at> debbugs.gnu.org, oscarfv <at> telefonica.net, monnier <at> iro.umontreal.ca,
>> me <at> pengjiz.com
>> From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
>> Date: Sat, 09 Aug 2025 15:33:56 +0200
>>
>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>>
>> > Another thought: the format_mode_line_unwind is only called from
>> > display_mode_line (redisplay) and format-mode-line. Why does soemthing
>> > land in the undo list at all? DOes that make sense at all?
>>
>> jit-lock uses this, which turns undo recording off
>>
>> subr.el:
>> 5253 (defmacro with-silent-modifications (&rest body)
>> 5254 "Execute BODY, pretending it does not modify the buffer.
>> 5255 This macro is typically used around modifications of
>> 5256 text properties that do not really affect the buffer's content.
>> 5257 If BODY performs real modifications to the buffer's text, other
>> 5258 than cosmetic ones, undo data may become corrupted.
>> 5259
>> 5260 This macro will run BODY normally, but doesn't count its buffer
>> 5261 modifications as being buffer modifications. This affects things
>> 5262 like `buffer-modified-p', checking whether the file is locked by
>> 5263 someone else, running buffer modification hooks, and other things
>> 5264 of that nature."
>> 5265 (declare (debug t) (indent 0))
>> 5266 (let ((modified (make-symbol "modified")))
>> 5267 `(let* ((,modified (buffer-modified-p))
>> 5268 (buffer-undo-list t)
>> ^^^^^^^^^^^^^^^^^^
>> Maybe there specbinds missing somewhere.
>
> I don't think so. The additions to buffer-undo-list are because of
> deleting some text, and that cannot be disabled. The problem we see
> is because there are many-many markers where the text is deleted.
Right, thanks. It goes like this (call graph, incoming):
- record_marker_adjustments undo.c:127
- record_delete record_delete:187
+ casify_region casify_region:555
+ adjust_after_replace adjust_after_replace:1408
+ replace_range replace_range:1639
+ del_range_2 del_range_2:2030
+ record_change record_change:201
Hm, so binding buffer-undo-list would have no effect.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 16:01:02 GMT)
Full text and
rfc822 format available.
Message #155 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello, everybody.
On Sat, Aug 09, 2025 at 10:29:15 +0200, Gerd Möllmann wrote:
> Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> > emacs -Q
> > write in *scratch* some lines with random words:
> > arins
> > arseina
> > aierni
> > iosrn nioni
> > ionugfw
> > sronuf
> > Now undo a few of those lines (C-_), move the cursor and C-_ again to
> > redo.
> Interesting. I come from a slightly different angle, that in my mac+igc
> port I had sometimes only 3 undos before I got "no more undo
> information". and I thought I had messed up something.
> My cimpler recipe is
> 1. Make a new buffer x.el
> 2. Type an a
> 3. undo
> 4. C-h v buffer-undo-list
I have an equally simple recipe, which suggests undo is not the culprit.
Note step 3.
1. emacs -Q
2. Type asdf.
3. M-: buffer-undo-list. This gives:
(nil (148 . 152) (t . 0) nil (1 . 148) (t . 0))
4. Type <backspace>.
5. M-: buffer-undo-list. This gives:
(nil (#("f" 0 1 (fontified t)) . -151) (#<marker at 151 in *scratch*>
. -1) (#<marker at 151 in *scratch*> . -1) (#<marker at 151 in
*scratch*> . -1) (#<marker at 151 in *scratch*> . -1) (#<marker at
151 in *scratch*> . -1) (#<marker at 15\1 in *scratch*> . -1)
(#<marker at 151 in *scratch*> . -1) (#<marker at 151 in *scratch*> .
-1) (#<marker at 151 in *scratch*> . -1) 152 ...)
[ That enforced dumning down of the output by truncation is most
annoying. I haven't found a way to get a complete output. ]
Unlike other people here, I see this in the emacs-30 branch, too.
> =>
> Value:
> (nil ("a" . 1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
> (#<marker at 1 in x.el> . -1) nil (1 . 2) (t . 0))
> Local in buffer x.el; global value is nil
> So far I can't see what is the cause. I would have guessed something in
> or around primitive-undo, but that hasn't changed forever.
My theory is that the cause is general poor marker hygiene. In the elisp
manual, there is (or was) a recommendation that after finishing use of a
marker, one should remove it from the buffer's list of markers with
(move-marker foo nil)
(or the C equivalent). There are lots of places (probably several
hundred) where this is not done.
I tried gdb with a break point on Fpoint_marker, but every hit I got
(about 15) was from save-excursion, which does clean up the marker it
uses for point.
I tried disabling inessential features like font-lock-mode, and setting
post-self-insert-hook to nil. This made no essential difference fo
buffer-undo-list.
[ .... ]
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 16:31:01 GMT)
Full text and
rfc822 format available.
Message #158 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
> Hello, everybody.
Hallo Alan!
> I have an equally simple recipe, which suggests undo is not the culprit.
> Note step 3.
>
> 1. emacs -Q
> 2. Type asdf.
> 3. M-: buffer-undo-list. This gives:
>
> (nil (148 . 152) (t . 0) nil (1 . 148) (t . 0))
>
> 4. Type <backspace>.
> 5. M-: buffer-undo-list. This gives:
>
> (nil (#("f" 0 1 (fontified t)) . -151) (#<marker at 151 in *scratch*>
> . -1) (#<marker at 151 in *scratch*> . -1) (#<marker at 151 in
> *scratch*> . -1) (#<marker at 151 in *scratch*> . -1) (#<marker at
> 151 in *scratch*> . -1) (#<marker at 15\1 in *scratch*> . -1)
> (#<marker at 151 in *scratch*> . -1) (#<marker at 151 in *scratch*> .
> -1) (#<marker at 151 in *scratch*> . -1) 152 ...)
>
> [ That enforced dumning down of the output by truncation is most
> annoying. I haven't found a way to get a complete output. ]
(I think M-: (pp buffer-undo-list) would do the trick for the
truncated output.)
>
> Unlike other people here, I see this in the emacs-30 branch, too.
Yes, make sense. After Eli's hint, I found this incoming call tree:
- record_marker_adjustments undo.c:127
- record_delete record_delete:187
+ casify_region casify_region:555
+ adjust_after_replace adjust_after_replace:1408
+ replace_range replace_range:1639
+ del_range_2 del_range_2:2030
+ record_change record_change:201
where record_marker_adjustments puts basically all present markers in a
buffer's undo list. del_range_2 I would interpret that any text deletion
might do that.
I think a garbage-collect with the old GC will clean up the undo list
eventually by calling compact_undo_list. With MPS, that doesn't work.
The cleanup in compact_undo_list cannot be used because MPS's weak
objects and GC work completely differently.
At the moment I'm a bit out of ideas. Waiting for a divine inspiration,
so to speak.
>
>> =>
>
>> Value:
>> (nil ("a" . 1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) (#<marker at 1 in x.el> . -1)
>> (#<marker at 1 in x.el> . -1) nil (1 . 2) (t . 0))
>> Local in buffer x.el; global value is nil
>
>> So far I can't see what is the cause. I would have guessed something in
>> or around primitive-undo, but that hasn't changed forever.
>
> My theory is that the cause is general poor marker hygiene. In the elisp
> manual, there is (or was) a recommendation that after finishing use of a
> marker, one should remove it from the buffer's list of markers with
>
> (move-marker foo nil)
>
> (or the C equivalent). There are lots of places (probably several
> hundred) where this is not done.
Yeah, for sure.
> I tried gdb with a break point on Fpoint_marker, but every hit I got
> (about 15) was from save-excursion, which does clean up the marker it
> uses for point.
>
> I tried disabling inessential features like font-lock-mode, and setting
> post-self-insert-hook to nil. This made no essential difference fo
> buffer-undo-list.
>
> [ .... ]
Yes, see above. I think it's that adding to the undo list when deleting
text (at least when deleting, haven't checked), and the creation of
many markers.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 18:29:01 GMT)
Full text and
rfc822 format available.
Message #161 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
> I have an equally simple recipe, which suggests undo is not the culprit.
> Note step 3.
>
> 1. emacs -Q
> 2. Type asdf.
> 3. M-: buffer-undo-list. This gives:
>
> (nil (148 . 152) (t . 0) nil (1 . 148) (t . 0))
>
> 4. Type <backspace>.
> 5. M-: buffer-undo-list. This gives:
>
> (nil (#("f" 0 1 (fontified t)) . -151) (#<marker at 151 in *scratch*>
> . -1) (#<marker at 151 in *scratch*> . -1) (#<marker at 151 in
> *scratch*> . -1) (#<marker at 151 in *scratch*> . -1) (#<marker at
> 151 in *scratch*> . -1) (#<marker at 15\1 in *scratch*> . -1)
> (#<marker at 151 in *scratch*> . -1) (#<marker at 151 in *scratch*> .
> -1) (#<marker at 151 in *scratch*> . -1) 152 ...)
Thanks Alan.
> [ That enforced dumning down of the output by truncation is most
> annoying. I haven't found a way to get a complete output. ]
I use C-h v buffer-undo-list which has no qualms about displaying
thousands of lines.
> Unlike other people here, I see this in the emacs-30 branch, too.
Interesting, because the commit I bisected as the cause (6f494d74f64) is
only in master and igc. There is something much more general at play
here, as you suggest.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sat, 09 Aug 2025 18:31:01 GMT)
Full text and
rfc822 format available.
Message #164 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Alan Mackenzie <acm <at> muc.de> writes:
>
>> Hello, everybody.
>
> Hallo Alan!
>
>> I have an equally simple recipe, which suggests undo is not the culprit.
>> Note step 3.
>>
>> 1. emacs -Q
>> 2. Type asdf.
>> 3. M-: buffer-undo-list. This gives:
>>
>> (nil (148 . 152) (t . 0) nil (1 . 148) (t . 0))
>>
>> 4. Type <backspace>.
>> 5. M-: buffer-undo-list. This gives:
>>
>> (nil (#("f" 0 1 (fontified t)) . -151) (#<marker at 151 in *scratch*>
>> . -1) (#<marker at 151 in *scratch*> . -1) (#<marker at 151 in
>> *scratch*> . -1) (#<marker at 151 in *scratch*> . -1) (#<marker at
>> 151 in *scratch*> . -1) (#<marker at 15\1 in *scratch*> . -1)
>> (#<marker at 151 in *scratch*> . -1) (#<marker at 151 in *scratch*> .
>> -1) (#<marker at 151 in *scratch*> . -1) 152 ...)
>>
>> [ That enforced dumning down of the output by truncation is most
>> annoying. I haven't found a way to get a complete output. ]
>
> (I think M-: (pp buffer-undo-list) would do the trick for the
> truncated output.)
>
>
>>
>> Unlike other people here, I see this in the emacs-30 branch, too.
>
> Yes, make sense. After Eli's hint, I found this incoming call tree:
>
> - record_marker_adjustments undo.c:127
> - record_delete record_delete:187
> + casify_region casify_region:555
> + adjust_after_replace adjust_after_replace:1408
> + replace_range replace_range:1639
> + del_range_2 del_range_2:2030
> + record_change record_change:201
>
> where record_marker_adjustments puts basically all present markers in a
> buffer's undo list. del_range_2 I would interpret that any text deletion
> might do that.
I think it may make more sense to find out who goes around creating
markers and not cleaning up after them. But I suspect many places cannot
easily be fixed because the markers might be exposed to Lisp.
> I think a garbage-collect with the old GC will clean up the undo list
> eventually by calling compact_undo_list. With MPS, that doesn't work.
> The cleanup in compact_undo_list cannot be used because MPS's weak
> objects and GC work completely differently.
That's my understanding, too. And it means that this probably isn't
horribly important to fix on the master branch. On feature/igc, it looks
like something has to be done.
> At the moment I'm a bit out of ideas. Waiting for a divine inspiration,
> so to speak.
Maybe some markers could be marked at creation time as not being
important enough to be recorded in the undo list? I'm not really sure
which markers are being recorded and which need to be for undo to work.
Pip
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 04:46:01 GMT)
Full text and
rfc822 format available.
Message #167 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> Cc: 79200 <at> debbugs.gnu.org, Alan Mackenzie <acm <at> muc.de>,
> Stefan Monnier <monnier <at> iro.umontreal.ca>,
> Óscar Fuentes <oscarfv <at> eclipso.eu>
> Date: Sat, 09 Aug 2025 18:30:37 +0000
> From: Pip Cet via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
>
> I think it may make more sense to find out who goes around creating
> markers and not cleaning up after them.
Isn't that format_mode_line_unwind_data, which you found, and the
missing detach_marker call?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 04:56:02 GMT)
Full text and
rfc822 format available.
Message #170 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Pip Cet <pipcet <at> protonmail.com> writes:
>> - record_marker_adjustments undo.c:127
>> - record_delete record_delete:187
>> + casify_region casify_region:555
>> + adjust_after_replace adjust_after_replace:1408
>> + replace_range replace_range:1639
>> + del_range_2 del_range_2:2030
>> + record_change record_change:201
>>
>> where record_marker_adjustments puts basically all present markers in a
>> buffer's undo list. del_range_2 I would interpret that any text deletion
>> might do that.
>
> I think it may make more sense to find out who goes around creating
> markers and not cleaning up after them. But I suspect many places cannot
> easily be fixed because the markers might be exposed to Lisp.
Probably. Good question is how to find these places, especially when
they are created in Lisp :-/.
>
>> I think a garbage-collect with the old GC will clean up the undo list
>> eventually by calling compact_undo_list. With MPS, that doesn't work.
>> The cleanup in compact_undo_list cannot be used because MPS's weak
>> objects and GC work completely differently.
>
> That's my understanding, too. And it means that this probably isn't
> horribly important to fix on the master branch. On feature/igc, it looks
> like something has to be done.
>
>> At the moment I'm a bit out of ideas. Waiting for a divine inspiration,
>> so to speak.
>
> Maybe some markers could be marked at creation time as not being
> important enough to be recorded in the undo list? I'm not really sure
> which markers are being recorded and which need to be for undo to work.
Might be possible but also requires to find where the markers are
created, find out if they are nver required for undo, and so on.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 12:37:02 GMT)
Full text and
rfc822 format available.
Message #173 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello, Gerd.
On Sun, Aug 10, 2025 at 06:55:45 +0200, Gerd Möllmann wrote:
> Pip Cet <pipcet <at> protonmail.com> writes:
> >> - record_marker_adjustments undo.c:127
> >> - record_delete record_delete:187
> >> + casify_region casify_region:555
> >> + adjust_after_replace adjust_after_replace:1408
> >> + replace_range replace_range:1639
> >> + del_range_2 del_range_2:2030
> >> + record_change record_change:201
> >> where record_marker_adjustments puts basically all present markers in a
> >> buffer's undo list. del_range_2 I would interpret that any text deletion
> >> might do that.
> > I think it may make more sense to find out who goes around creating
> > markers and not cleaning up after them. But I suspect many places cannot
> > easily be fixed because the markers might be exposed to Lisp.
> Probably. Good question is how to find these places, especially when
> they are created in Lisp :-/.
I've made a start on this (see patch below). It's mainly in the C files,
where I grepped for Fpoint_marker and Fcopy_marker, and tidied up the
uses which didn't tidy up their uses of markers. But also in some Lisp
files, which are directly part of the command loop (simple.el), or called
from it in hooks (jit.el, electric.el).
Unfortunately, this hasn't helped much. When I type "asdfasdf" into
*scratch* on emacs -Q, then <BACKSPACE>, I still see five point markers
in buffer-undo-list. If I <BACKSPACE> a second time, this adds on a
further ten point markers to b-u-list.
It's worth mentioning that these markers aren't eq to eachother. At
least, not all of them. I have a strong suspicion that there are
duplicates in the 15 markers in buffer-undo-list after my two deletions.
It is unclear whether the <BACKSPACE> creates these markers, or just puts
existing markers into buffer-undo-list. Maybe we could do with a
primitive in marker.c which would print out the current buffer's list of
markers.
> >> I think a garbage-collect with the old GC will clean up the undo list
> >> eventually by calling compact_undo_list. With MPS, that doesn't work.
> >> The cleanup in compact_undo_list cannot be used because MPS's weak
> >> objects and GC work completely differently.
> > That's my understanding, too. And it means that this probably isn't
> > horribly important to fix on the master branch. On feature/igc, it looks
> > like something has to be done.
> >> At the moment I'm a bit out of ideas. Waiting for a divine inspiration,
> >> so to speak.
> > Maybe some markers could be marked at creation time as not being
> > important enough to be recorded in the undo list? I'm not really sure
> > which markers are being recorded and which need to be for undo to work.
This might be a silly question, but why do we have to put markers into
buffer-undo-list at all? Surely they should "fix themselves" as other
changes in the buffer get undone?
> Might be possible but also requires to find where the markers are
> created, find out if they are nver required for undo, and so on.
Here's a patch which tidies up several markers. Unfortunately it doesn't
seem to make a massive difference to the problem.
diff --git a/lisp/abbrev.el b/lisp/abbrev.el
index c06b6b06406..9574d4d4d0a 100644
--- a/lisp/abbrev.el
+++ b/lisp/abbrev.el
@@ -783,6 +783,10 @@ abbrev-expansion
(defun abbrev--before-point ()
"Try and find an abbrev before point. Return it if found, nil otherwise."
(unless (eq abbrev-start-location-buffer (current-buffer))
+;;;; EXPERIMENTAL STOUGH, 2025-08-09
+ (when (markerp abbrev-start-location)
+ (set-marker abbrev-start-location nil))
+;;;; END OF EXPERIMENTAL STOUGH
(setq abbrev-start-location nil))
(let ((tables (abbrev--active-tables))
@@ -803,7 +807,11 @@ abbrev--before-point
(when (> end start)
(setq name (buffer-substring start end))
(goto-char pos) ; Restore point.
- (list (abbrev-symbol name tables) name start end)))
+ (list (abbrev-symbol name tables) name start end))
+;;;; EXPERIMENTAL STOUGH, 2025-08-09
+ ;; (set-marker start nil) NO!!!
+;;;; END OF EXP STOUGH
+ )
(while (and tables (not (car res)))
(let* ((table (pop tables))
@@ -1090,7 +1098,12 @@ abbrev--default-expand
;; where it started.
(if (and (> startpos endmark)
(= (point) endmark)) ;Obey skeletons that move point.
- (goto-char startpos))))))))
+ (goto-char startpos)))
+;;;; EXPERIMENTAL STOUGH, 2025-08-09
+ (set-marker startpos nil)
+ (set-marker endmark nil)
+;;;; END OF EXP STOUGH
+ )))))
(defun unexpand-abbrev ()
"Undo the expansion of the last abbrev that expanded.
diff --git a/lisp/electric.el b/lisp/electric.el
index 39e13e1ca0c..c8fcba803cc 100644
--- a/lisp/electric.el
+++ b/lisp/electric.el
@@ -279,7 +279,11 @@ electric-indent-post-self-insert-function
;; to `indent-according-to-mode' but after we may
;; not be (Bug#15767).
(when (and (eolp))
- (delete-horizontal-space t))))))
+ (delete-horizontal-space t))))
+;;;; EXPERIMENTAL STOUGH, 2025-08-09
+ (set-marker before nil)
+;;;; END OF EXPERIMENTAL STOUGH
+ ))
(unless (and electric-indent-inhibit
(not at-newline))
(condition-case-unless-debug ()
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index 711d7ca8cac..3e8c75abc7b 100644
--- a/lisp/jit-lock.el
+++ b/lisp/jit-lock.el
@@ -502,7 +502,12 @@ jit-lock-force-redisplay
;; Don't cause refontification (it's already been done), but just do
;; some random buffer change, so as to force redisplay.
(put-text-property start end 'fontified nil)
- (put-text-property start end 'fontified t)))))
+ (put-text-property start end 'fontified t)
+;;;; EXPERIMENTAL STOUGH, 2025-08-09
+ (move-marker start nil)
+ (move-marker end nil)
+;;;; END OF EXPERIMENTAL STOUGH
+ ))))
;;; Stealth fontification.
@@ -751,7 +756,10 @@ jit-lock--antiblink-post-command
(jit-lock-context-fontify)
(cancel-timer jit-lock--antiblink-grace-timer)
(setq jit-lock--antiblink-grace-timer nil))))
- ;; Update variables (and release the marker).
+ ;; Update variables (and release the markers).
+;;;; EXPERIMENTAL STOUGH, 2025-08-09
+ (set-marker new-l-b-p nil)
+;;;; END OF EXP. STOUGH
(set-marker jit-lock--antiblink-line-beginning-position nil)
(setq jit-lock--antiblink-line-beginning-position new-l-b-p
jit-lock--antiblink-string-or-comment new-s-o-c)))
diff --git a/src/lread.c b/src/lread.c
index 57d3239e283..b0cc1b6ec0c 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -2244,8 +2244,12 @@ readevalloop (Lisp_Object readcharfun,
/* Just for cleanliness, convert END to a marker
if it is an integer. */
- if (FIXNUMP (end))
- end = Fpoint_max_marker ();
+ /* EXPERIMENTAL STOUGH, 2025-08-09 */
+ /* DON'T make this conversion! It is thouroughly unclean,
+ since we never unchain_marker it, so it is left clogging
+ up the buffer's marker list. */
+ /* if (FIXNUMP (end)) */
+ /* end = Fpoint_max_marker (); */
}
/* On the first cycle, we can easily test here
@@ -2312,8 +2316,11 @@ readevalloop (Lisp_Object readcharfun,
&& XHASH_TABLE (read_objects_completed)->count > 0)
read_objects_completed = Qnil;
- if (!NILP (start) && continue_reading_p)
- start = Fpoint_marker ();
+ /* EXPERIMENTAL STOUGH, 2025-08-09 */
+ /* DON'T create another marker each time around this loop! This just
+ clogs up the buffer's marker list with useless markers. */
+ /* if (!NILP (start) && continue_reading_p) */
+ /* start = Fpoint_marker (); */
/* Restore saved point and BEGV. */
unbind_to (count1, Qnil);
diff --git a/src/window.c b/src/window.c
index 1ac004af5e0..a96a6aa2eb8 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6592,6 +6592,9 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
if (lose)
{
+ /* EXPERIMENTAL STOUGH, 2025-08-09 */
+ unchain_marker (XMARKER (opoint_marker));
+ /* END OF EXP STOUGH */
if (noerror)
return;
else
@@ -6689,6 +6692,9 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
}
else
{
+ /* EXPERIMENTAL STOUGH, 2025-08-09 */
+ unchain_marker (XMARKER (opoint_marker));
+ /* END OF EXP STOUGH */
if (noerror)
return;
else
@@ -6701,6 +6707,9 @@ window_scroll_line_based (Lisp_Object window, int n, bool whole, bool noerror)
? make_fixnum (BUF_PT (XBUFFER (w->contents)))
: Fmarker_position (w->pointm)),
w->contents);
+ /* EXPERIMENTAL STOUGH, 2025-08-09 */
+ unchain_marker (XMARKER (opoint_marker));
+ /* END OF EXP STOUGH */
}
diff --git a/src/xdisp.c b/src/xdisp.c
index 2691296b282..c787657e429 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12085,6 +12085,9 @@ DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
}
SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
bidi_unshelve_cache (itdata, false);
+ /* EXPERIMENTAL STOUGH, 2025-08-09 */
+ Fset_marker (opoint, Qnil, Qnil);
+ /* END OF EXPERIMENTAL STOUGH */
}
set_buffer_internal_1 (oldb);
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 13:12:02 GMT)
Full text and
rfc822 format available.
Message #176 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
>> > I think it may make more sense to find out who goes around creating
>> > markers and not cleaning up after them. But I suspect many places cannot
>> > easily be fixed because the markers might be exposed to Lisp.
>
>> Probably. Good question is how to find these places, especially when
>> they are created in Lisp :-/.
>
> I've made a start on this (see patch below). It's mainly in the C files,
> where I grepped for Fpoint_marker and Fcopy_marker, and tidied up the
> uses which didn't tidy up their uses of markers. But also in some Lisp
> files, which are directly part of the command loop (simple.el), or called
> from it in hooks (jit.el, electric.el).
Hi Alan,
Thanks.
> Unfortunately, this hasn't helped much. When I type "asdfasdf" into
> *scratch* on emacs -Q, then <BACKSPACE>, I still see five point markers
> in buffer-undo-list. If I <BACKSPACE> a second time, this adds on a
> further ten point markers to b-u-list.
>
> It's worth mentioning that these markers aren't eq to eachother. At
> least, not all of them. I have a strong suspicion that there are
> duplicates in the 15 markers in buffer-undo-list after my two
> deletions.
Hm, you mean eq markers inside the same undo group has duplicates? That
I haven't seen yet. There is code in primitive-undo for that case,
though, so it seems to be expected in some case. No idea.
If the same marker appears twice in different undo groups, then that's
normal. The entries for markers mean something like "add some delta to
the marker's position when we undo this record".
> It is unclear whether the <BACKSPACE> creates these markers, or just puts
> existing markers into buffer-undo-list. Maybe we could do with a
> primitive in marker.c which would print out the current buffer's list of
> markers.
I don't believe it creates the markers. But I'm pretty sure that
record_change can put a lot of markers to a buffer's undo list. It just
considers all markers in a buffer's markers list as relevant for undo.
IOW, when we undo, all these markers need their positions changed. It
has no way to recognize markers that are only used temporarily.
...
> This might be a silly question, but why do we have to put markers into
> buffer-undo-list at all? Surely they should "fix themselves" as other
> changes in the buffer get undone?
Please see above. I hope that explains it.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 14:42:01 GMT)
Full text and
rfc822 format available.
Message #179 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello, Gerd.
On Sun, Aug 10, 2025 at 15:11:24 +0200, Gerd Möllmann wrote:
> Alan Mackenzie <acm <at> muc.de> writes:
> >> > I think it may make more sense to find out who goes around creating
> >> > markers and not cleaning up after them. But I suspect many places cannot
> >> > easily be fixed because the markers might be exposed to Lisp.
> >> Probably. Good question is how to find these places, especially when
> >> they are created in Lisp :-/.
> > I've made a start on this (see patch below). It's mainly in the C files,
> > where I grepped for Fpoint_marker and Fcopy_marker, and tidied up the
> > uses which didn't tidy up their uses of markers. But also in some Lisp
> > files, which are directly part of the command loop (simple.el), or called
> > from it in hooks (jit.el, electric.el).
> Hi Alan,
> Thanks.
> > Unfortunately, this hasn't helped much. When I type "asdfasdf" into
> > *scratch* on emacs -Q, then <BACKSPACE>, I still see five point markers
> > in buffer-undo-list. If I <BACKSPACE> a second time, this adds on a
> > further ten point markers to b-u-list.
> > It's worth mentioning that these markers aren't eq to eachother. At
> > least, not all of them. I have a strong suspicion that there are
> > duplicates in the 15 markers in buffer-undo-list after my two
> > deletions.
> Hm, you mean eq markers inside the same undo group has duplicates? That
> I haven't seen yet. There is code in primitive-undo for that case,
> though, so it seems to be expected in some case. No idea.
Ah, OK.
> If the same marker appears twice in different undo groups, then that's
> normal. The entries for markers mean something like "add some delta to
> the marker's position when we undo this record".
Yes
> > It is unclear whether the <BACKSPACE> creates these markers, or just puts
> > existing markers into buffer-undo-list. Maybe we could do with a
> > primitive in marker.c which would print out the current buffer's list of
> > markers.
Yes, I've called it buffer-marker-list, and it looks like this:
diff --git a/src/lisp.h b/src/lisp.h
index 64b5c227583..bc5a404c261 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1400,6 +1400,9 @@ #define XSETTHREAD(a, b) XSETPSEUDOVECTOR (a, b, PVEC_THREAD)
#define XSETMUTEX(a, b) XSETPSEUDOVECTOR (a, b, PVEC_MUTEX)
#define XSETCONDVAR(a, b) XSETPSEUDOVECTOR (a, b, PVEC_CONDVAR)
#define XSETNATIVE_COMP_UNIT(a, b) XSETPSEUDOVECTOR (a, b, PVEC_NATIVE_COMP_UNIT)
+/* EXPERIMENTAL STOUGH, 2025-08-10 */
+#define XSETMARKER(a, b) XSETPSEUDOVECTOR (a, b, PVEC_MARKER)
+/* END OF EXPERIMENTAL STOUGH */
/* Efficiently convert a pointer to a Lisp object and back. The
pointer is represented as a fixnum, so the garbage collector
diff --git a/src/marker.c b/src/marker.c
index 4ab68ec7bbe..c5be58d1d7a 100644
--- a/src/marker.c
+++ b/src/marker.c
@@ -424,6 +424,24 @@ buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t bytepos)
/* Operations on markers. */
+/* EXPERIMENTAL STOUGH, 2025-08-10 */
+DEFUN ("buffer-marker-list", Fbuffer_marker_list, Sbuffer_marker_list, 0, 0, 0,
+ doc: /* Return (a copy of) the list of markers in the current buffer. */)
+ (void)
+{
+ Lisp_Object markers = Qnil;
+ Lisp_Object mk;
+
+ for (struct Lisp_Marker *ma = BUF_MARKERS (current_buffer); ma; ma = ma->next)
+ {
+ XSETMARKER (mk, ma);
+ markers = (Fcons (mk, markers));
+ }
+ return Fnreverse (markers);
+}
+
+/* END OF EXPERIMENTAL STOUGH */
+
DEFUN ("marker-buffer", Fmarker_buffer, Smarker_buffer, 1, 1, 0,
doc: /* Return the buffer that MARKER points into, or nil if none.
Returns nil if MARKER points into a dead buffer. */)
@@ -833,6 +851,9 @@ verify_bytepos (ptrdiff_t charpos)
void
syms_of_marker (void)
{
+ /* EXPERIMENTAL STOUGH, 2025-08-10 */
+ defsubr (&Sbuffer_marker_list);
+ /* END OF EXPERIMENTAL STOUGH */
defsubr (&Smarker_position);
defsubr (&Smarker_last_position);
defsubr (&Smarker_buffer);
> I don't believe it creates the markers. But I'm pretty sure that
> record_change can put a lot of markers to a buffer's undo list. It just
> considers all markers in a buffer's markers list as relevant for undo.
> IOW, when we undo, all these markers need their positions changed. It
> has no way to recognize markers that are only used temporarily.
In emacs -Q, C-x b foo <RET>.
Now do M-: (length (buffer-marker-list)). It returns 9. Repeat. It
now returns 14. Then, successively, 19, 26, 31, 36, .... OK, between
the 19 and 26 I had finger trouble.
But it would appear that the command loop, or something close to it, is
adding five frivolous point markers at each iteration. This is in my
"EXPERIMENTAL"ly patched master. It may be even worse in a vanilla
master.
> ...
> > This might be a silly question, but why do we have to put markers into
> > buffer-undo-list at all? Surely they should "fix themselves" as other
> > changes in the buffer get undone?
> Please see above. I hope that explains it.
Thanks. I'll study it more carefully when I'm in a less hacky mood.
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 14:57:01 GMT)
Full text and
rfc822 format available.
Message #182 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
>> I don't believe it creates the markers. But I'm pretty sure that
>> record_change can put a lot of markers to a buffer's undo list. It just
>> considers all markers in a buffer's markers list as relevant for undo.
>> IOW, when we undo, all these markers need their positions changed. It
>> has no way to recognize markers that are only used temporarily.
>
> In emacs -Q, C-x b foo <RET>.
>
> Now do M-: (length (buffer-marker-list)). It returns 9. Repeat. It
> now returns 14. Then, successively, 19, 26, 31, 36, .... OK, between
> the 19 and 26 I had finger trouble.
>
> But it would appear that the command loop, or something close to it, is
> adding five frivolous point markers at each iteration. This is in my
> "EXPERIMENTAL"ly patched master. It may be even worse in a vanilla
> master.
Or redisplay like in the mode-line case, as Pip found out. In this
regard, I find the undo mechanism a bit unfortunate, but it has been
that way maybe even since the beginning.
The many "temporary" markers in the undo list should be an removed whit
the next garbage-collect. The function compact_undo_list does that. It
looks for markers that will be deleted because they are no longer
references and removes the undo entries for them. It's a bit like
a weak hash table containing markers.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 14:58:03 GMT)
Full text and
rfc822 format available.
Message #185 received at 79200 <at> debbugs.gnu.org (full text, mbox):
"Alan Mackenzie" <acm <at> muc.de> writes:
> Hello, Gerd.
>
> On Sun, Aug 10, 2025 at 06:55:45 +0200, Gerd Möllmann wrote:
>> Pip Cet <pipcet <at> protonmail.com> writes:
>
>> >> - record_marker_adjustments undo.c:127
>> >> - record_delete record_delete:187
>> >> + casify_region casify_region:555
>> >> + adjust_after_replace adjust_after_replace:1408
>> >> + replace_range replace_range:1639
>> >> + del_range_2 del_range_2:2030
>> >> + record_change record_change:201
>
>> >> where record_marker_adjustments puts basically all present markers in a
>> >> buffer's undo list. del_range_2 I would interpret that any text deletion
>> >> might do that.
>
>> > I think it may make more sense to find out who goes around creating
>> > markers and not cleaning up after them. But I suspect many places cannot
>> > easily be fixed because the markers might be exposed to Lisp.
>
>> Probably. Good question is how to find these places, especially when
>> they are created in Lisp :-/.
I think the Lisp part is easy: we can simply capture a backtrace and
attach it when creating the marker.
From f7a23531886fe458346f13ee08369d153b2de897 Mon Sep 17 00:00:00 2001
From: Pip Cet <pipcet <at> protonmail.com>
Date: Sun, 10 Aug 2025 14:53:49 +0000
Subject: [PATCH] store Lisp backtraces for markers
---
src/alloc.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/src/alloc.c b/src/alloc.c
index 07ca8474bf3..c8426e3a4dc 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3812,6 +3812,12 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
p->next = NULL;
p->insertion_type = 0;
p->need_adjustment = 0;
+ if (!NILP (Vmarker_backtrace))
+ {
+ Lisp_Object backtrace = make_nil_vector (32);
+ get_backtrace (XVECTOR (backtrace)->contents, 32);
+ Fputhash (make_lisp_ptr (p, Lisp_Vectorlike), backtrace, Vmarker_backtrace);
+ }
return make_lisp_ptr (p, Lisp_Vectorlike);
}
@@ -3836,6 +3842,12 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
m->need_adjustment = 0;
m->next = BUF_MARKERS (buf);
BUF_MARKERS (buf) = m;
+ if (!NILP (Vmarker_backtrace))
+ {
+ Lisp_Object backtrace = make_nil_vector (32);
+ get_backtrace (XVECTOR (backtrace)->contents, 32);
+ Fputhash (make_lisp_ptr (m, Lisp_Vectorlike), backtrace, Vmarker_backtrace);
+ }
return make_lisp_ptr (m, Lisp_Vectorlike);
}
@@ -7461,6 +7473,10 @@ syms_of_alloc (void)
If this portion is smaller than `gc-cons-threshold', this is ignored. */);
Vgc_cons_percentage = make_float (0.1);
+ DEFVAR_LISP ("marker-backtrace", Vmarker_backtrace,
+ doc: /* */);
+ Vmarker_backtrace = CALLN (Fmake_hash_table, QCtest, Qeq, QCweakness, Qkey);
+
DEFVAR_INT ("pure-bytes-used", pure_bytes_used,
doc: /* No longer used. */);
--
2.50.0
Use like this:
(dolist (el buffer-undo-list)
(and (consp el)
(markerp (car el))
(message "%S %S" (car el) (gethash (car el) marker-backtrace))))
> I've made a start on this (see patch below). It's mainly in the C files,
> where I grepped for Fpoint_marker and Fcopy_marker, and tidied up the
> uses which didn't tidy up their uses of markers. But also in some Lisp
> files, which are directly part of the command loop (simple.el), or called
> from it in hooks (jit.el, electric.el).
>
> Unfortunately, this hasn't helped much. When I type "asdfasdf" into
> *scratch* on emacs -Q, then <BACKSPACE>, I still see five point markers
> in buffer-undo-list. If I <BACKSPACE> a second time, this adds on a
> further ten point markers to b-u-list.
>
> It's worth mentioning that these markers aren't eq to eachother. At
> least, not all of them. I have a strong suspicion that there are
> duplicates in the 15 markers in buffer-undo-list after my two deletions.
>
> It is unclear whether the <BACKSPACE> creates these markers, or just puts
> existing markers into buffer-undo-list. Maybe we could do with a
> primitive in marker.c which would print out the current buffer's list of
> markers.
That also sounds like a useful debugging aid!
>
>> >> I think a garbage-collect with the old GC will clean up the undo list
>> >> eventually by calling compact_undo_list. With MPS, that doesn't work.
>> >> The cleanup in compact_undo_list cannot be used because MPS's weak
>> >> objects and GC work completely differently.
>
>> > That's my understanding, too. And it means that this probably isn't
>> > horribly important to fix on the master branch. On feature/igc, it looks
>> > like something has to be done.
>
>> >> At the moment I'm a bit out of ideas. Waiting for a divine inspiration,
>> >> so to speak.
>
>> > Maybe some markers could be marked at creation time as not being
>> > important enough to be recorded in the undo list? I'm not really sure
>> > which markers are being recorded and which need to be for undo to work.
>
> This might be a silly question, but why do we have to put markers into
> buffer-undo-list at all? Surely they should "fix themselves" as other
> changes in the buffer get undone?
I don't know the answer. I assume it's necessary for text removals which
result in two markers sharing a position when they didn't previously, so
we can undo those properly?
>> Might be possible but also requires to find where the markers are
>> created, find out if they are nver required for undo, and so on.
>
> Here's a patch which tidies up several markers. Unfortunately it doesn't
> seem to make a massive difference to the problem.
Have you tried applying the patch I posted earlier, too? It doesn't
appear to be included in your changes, but it made a difference here.
This is against feature/igc, but the code looks unchanged from master.
From d5cf17f88fbba4cdfc61ebea725e12a2c8b9aa42 Mon Sep 17 00:00:00 2001
From: Pip Cet <pipcet <at> protonmail.com>
Date: Sat, 9 Aug 2025 10:32:19 +0000
Subject: [PATCH] Detach markers explicitly so they don't wind up on the undo
list
* src/xdisp.c (unwind_format_mode_line): Detach markers when we're
done with them.
---
src/xdisp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/xdisp.c b/src/xdisp.c
index 432dd5dceca..2406bb6f3d9 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -13828,6 +13828,7 @@ unwind_format_mode_line (Lisp_Object vector)
current_buffer = XBUFFER (buffer);
set_point_from_marker (AREF (vector, 11));
+ detach_marker (AREF (vector, 11));
ASET (vector, 11, Qnil);
current_buffer = cb;
}
--
2.50.0
Pip
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 15:07:04 GMT)
Full text and
rfc822 format available.
Message #188 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Pip Cet <pipcet <at> protonmail.com> writes:
> I think the Lisp part is easy: we can simply capture a backtrace and
> attach it when creating the marker.
For the markers made in C maybe one could use a trick I've used in other
situations. Something like this
1. Add paramaters to build_marker and rename it.
Lisp_Object
build_marker_ (struct buffer *buf, ptrdiff_t charpos, const char *file,
int line)
2. Add a define
#define bufer_marker(b, p) build_marker((b), (p), __FILE__, __LINE__)
3. Do something with file and line in build_marker. One could store them
in new fields in Lisp_Marker for example, but such a change easily
ripples through. If one does that, one could print the file an line
in print.c for markers.
Pretty involved.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Sun, 10 Aug 2025 16:36:01 GMT)
Full text and
rfc822 format available.
Message #191 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello, Pip.
On Sun, Aug 10, 2025 at 14:56:56 +0000, Pip Cet wrote:
> "Alan Mackenzie" <acm <at> muc.de> writes:
> > Hello, Gerd.
> > On Sun, Aug 10, 2025 at 06:55:45 +0200, Gerd Möllmann wrote:
> >> Pip Cet <pipcet <at> protonmail.com> writes:
> >> >> - record_marker_adjustments undo.c:127
> >> >> - record_delete record_delete:187
> >> >> + casify_region casify_region:555
> >> >> + adjust_after_replace adjust_after_replace:1408
> >> >> + replace_range replace_range:1639
> >> >> + del_range_2 del_range_2:2030
> >> >> + record_change record_change:201
> >> >> where record_marker_adjustments puts basically all present markers in a
> >> >> buffer's undo list. del_range_2 I would interpret that any text deletion
> >> >> might do that.
> >> > I think it may make more sense to find out who goes around creating
> >> > markers and not cleaning up after them. But I suspect many places cannot
> >> > easily be fixed because the markers might be exposed to Lisp.
> >> Probably. Good question is how to find these places, especially when
> >> they are created in Lisp :-/.
> I think the Lisp part is easy: we can simply capture a backtrace and
> attach it when creating the marker.
I thought the C part was easy; just grepping for point_marker, and things
like that. ;-)
> >From f7a23531886fe458346f13ee08369d153b2de897 Mon Sep 17 00:00:00 2001
> From: Pip Cet <pipcet <at> protonmail.com>
> Date: Sun, 10 Aug 2025 14:53:49 +0000
> Subject: [PATCH] store Lisp backtraces for markers
> ---
> src/alloc.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
> diff --git a/src/alloc.c b/src/alloc.c
> index 07ca8474bf3..c8426e3a4dc 100644
> --- a/src/alloc.c
> +++ b/src/alloc.c
> @@ -3812,6 +3812,12 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0,
> p->next = NULL;
> p->insertion_type = 0;
> p->need_adjustment = 0;
> + if (!NILP (Vmarker_backtrace))
> + {
> + Lisp_Object backtrace = make_nil_vector (32);
> + get_backtrace (XVECTOR (backtrace)->contents, 32);
> + Fputhash (make_lisp_ptr (p, Lisp_Vectorlike), backtrace, Vmarker_backtrace);
> + }
> return make_lisp_ptr (p, Lisp_Vectorlike);
> }
> @@ -3836,6 +3842,12 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos)
> m->need_adjustment = 0;
> m->next = BUF_MARKERS (buf);
> BUF_MARKERS (buf) = m;
> + if (!NILP (Vmarker_backtrace))
> + {
> + Lisp_Object backtrace = make_nil_vector (32);
> + get_backtrace (XVECTOR (backtrace)->contents, 32);
> + Fputhash (make_lisp_ptr (m, Lisp_Vectorlike), backtrace, Vmarker_backtrace);
> + }
> return make_lisp_ptr (m, Lisp_Vectorlike);
> }
> @@ -7461,6 +7473,10 @@ syms_of_alloc (void)
> If this portion is smaller than `gc-cons-threshold', this is ignored. */);
> Vgc_cons_percentage = make_float (0.1);
> + DEFVAR_LISP ("marker-backtrace", Vmarker_backtrace,
> + doc: /* */);
> + Vmarker_backtrace = CALLN (Fmake_hash_table, QCtest, Qeq, QCweakness, Qkey);
> +
> DEFVAR_INT ("pure-bytes-used", pure_bytes_used,
> doc: /* No longer used. */);
> --
> 2.50.0
> Use like this:
> (dolist (el buffer-undo-list)
> (and (consp el)
> (markerp (car el))
> (message "%S %S" (car el) (gethash (car el) marker-backtrace))))
Have you got any results back from this, yet?
[ .... ]
> > It is unclear whether the <BACKSPACE> creates these markers, or just puts
> > existing markers into buffer-undo-list. Maybe we could do with a
> > primitive in marker.c which would print out the current buffer's list of
> > markers.
> That also sounds like a useful debugging aid!
I posted it (Fbuffer_marker_list) in an earlier reply to Gerd.
[ .... ]
> >> Might be possible but also requires to find where the markers are
> >> created, find out if they are nver required for undo, and so on.
> > Here's a patch which tidies up several markers. Unfortunately it doesn't
> > seem to make a massive difference to the problem.
> Have you tried applying the patch I posted earlier, too? It doesn't
> appear to be included in your changes, but it made a difference here.
I've just tried it. Repeated M-: (length (buffer-marker-list)) in an
empty buffer now reports an extra three markers per iteration rather than
the previous five. So, thanks!
We just need to track down those remaining three markers and remove them,
somehow. :-)
> This is against feature/igc, but the code looks unchanged from master.
Indeed, yes.
> >From d5cf17f88fbba4cdfc61ebea725e12a2c8b9aa42 Mon Sep 17 00:00:00 2001
> From: Pip Cet <pipcet <at> protonmail.com>
> Date: Sat, 9 Aug 2025 10:32:19 +0000
> Subject: [PATCH] Detach markers explicitly so they don't wind up on the undo
> list
> * src/xdisp.c (unwind_format_mode_line): Detach markers when we're
> done with them.
> ---
> src/xdisp.c | 1 +
> 1 file changed, 1 insertion(+)
> diff --git a/src/xdisp.c b/src/xdisp.c
> index 432dd5dceca..2406bb6f3d9 100644
> --- a/src/xdisp.c
> +++ b/src/xdisp.c
> @@ -13828,6 +13828,7 @@ unwind_format_mode_line (Lisp_Object vector)
> current_buffer = XBUFFER (buffer);
> set_point_from_marker (AREF (vector, 11));
> + detach_marker (AREF (vector, 11));
> ASET (vector, 11, Qnil);
> current_buffer = cb;
> }
> --
> 2.50.0
> Pip
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Mon, 11 Aug 2025 15:49:02 GMT)
Full text and
rfc822 format available.
Message #194 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello again, Pip.
On Sun, Aug 10, 2025 at 16:35:11 +0000, Alan Mackenzie wrote:
> On Sun, Aug 10, 2025 at 14:56:56 +0000, Pip Cet wrote:
> > "Alan Mackenzie" <acm <at> muc.de> writes:
> > > On Sun, Aug 10, 2025 at 06:55:45 +0200, Gerd Möllmann wrote:
> > >> Pip Cet <pipcet <at> protonmail.com> writes:
> > >> >> - record_marker_adjustments undo.c:127
> > >> >> - record_delete record_delete:187
> > >> >> + casify_region casify_region:555
> > >> >> + adjust_after_replace adjust_after_replace:1408
> > >> >> + replace_range replace_range:1639
> > >> >> + del_range_2 del_range_2:2030
> > >> >> + record_change record_change:201
> > I think the Lisp part is easy: we can simply capture a backtrace and
> > attach it when creating the marker.
[ .... ]
> Have you got any results back from this, yet?
I've got some results. With my modified master, when I repeatedly do M-:
(length (buffer-marker-list)), I get three extra markers each iteration.
Tracking them with (a slight modification of) your (Pip's) tool, I see
that all three are ostensibly created by read-from-minibuffer.
[ .... ]
> We just need to track down those remaining three markers and remove them,
> somehow. :-)
Fread_from_minibuffer just calls read_minibuf. By perusing the source,
it seems that two of the three repeating markers are created in
save_window_save, called from Fcurrent_window_configuration (which is
called from read_minibuf).
With a bit of refactoring, we could arrange for (at least) two of these
three regularly created markers to be nullified. This would be tedious
rather than difficult.
Is it worth the effort, though? It is unclear how much this would help
the OP's (Óscar's) problem, though it would surely help a bit.
> > This is against feature/igc, but the code looks unchanged from master.
> Indeed, yes.
> > Pip
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Mon, 11 Aug 2025 16:22:01 GMT)
Full text and
rfc822 format available.
Message #197 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>,
> Óscar Fuentes <oscarfv <at> eclipso.eu>, acm <at> muc.de,
> Stefan Monnier <monnier <at> iro.umontreal.ca>, 79200 <at> debbugs.gnu.org
> Date: Mon, 11 Aug 2025 15:48:13 +0000
> From: Alan Mackenzie <acm <at> muc.de>
>
> Fread_from_minibuffer just calls read_minibuf. By perusing the source,
> it seems that two of the three repeating markers are created in
> save_window_save, called from Fcurrent_window_configuration (which is
> called from read_minibuf).
>
> With a bit of refactoring, we could arrange for (at least) two of these
> three regularly created markers to be nullified. This would be tedious
> rather than difficult.
Why aren't they collected by GC?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Mon, 11 Aug 2025 16:36:02 GMT)
Full text and
rfc822 format available.
Message #200 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello, Eli.
On Mon, Aug 11, 2025 at 19:20:43 +0300, Eli Zaretskii wrote:
> > Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>,
> > Óscar Fuentes <oscarfv <at> eclipso.eu>, acm <at> muc.de,
> > Stefan Monnier <monnier <at> iro.umontreal.ca>, 79200 <at> debbugs.gnu.org
> > Date: Mon, 11 Aug 2025 15:48:13 +0000
> > From: Alan Mackenzie <acm <at> muc.de>
> > Fread_from_minibuffer just calls read_minibuf. By perusing the source,
> > it seems that two of the three repeating markers are created in
> > save_window_save, called from Fcurrent_window_configuration (which is
> > called from read_minibuf).
> > With a bit of refactoring, we could arrange for (at least) two of these
> > three regularly created markers to be nullified. This would be tedious
> > rather than difficult.
> Why aren't they collected by GC?
They are, eventually.
But my hypothesis is that between GC runs many hundreds of useless
markers clog up the buffer's list of markers, and these in turn clog up
the OP's (Óscar's) undo list.
And that if we could reduce the number of useless live markers we leave
to GC, we could resolve the OP's problem. It may even be that the vast
numbers of markers we suspect get created are slowing Emacs down
noticeably, though there's no firm evidence for this at the moment.
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Mon, 11 Aug 2025 16:55:02 GMT)
Full text and
rfc822 format available.
Message #203 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
> It may even be that the vast numbers of markers we suspect get created
> are slowing Emacs down noticeably, though there's no firm evidence for
> this at the moment.
I suspect that too, but who knows.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Mon, 11 Aug 2025 16:59:01 GMT)
Full text and
rfc822 format available.
Message #206 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> Date: Mon, 11 Aug 2025 16:35:22 +0000
> Cc: pipcet <at> protonmail.com, gerd.moellmann <at> gmail.com, oscarfv <at> eclipso.eu,
> monnier <at> iro.umontreal.ca, 79200 <at> debbugs.gnu.org, acm <at> muc.de
> From: Alan Mackenzie <acm <at> muc.de>
>
> On Mon, Aug 11, 2025 at 19:20:43 +0300, Eli Zaretskii wrote:
> > > Cc: Gerd Möllmann <gerd.moellmann <at> gmail.com>,
> > > Óscar Fuentes <oscarfv <at> eclipso.eu>, acm <at> muc.de,
> > > Stefan Monnier <monnier <at> iro.umontreal.ca>, 79200 <at> debbugs.gnu.org
> > > Date: Mon, 11 Aug 2025 15:48:13 +0000
> > > From: Alan Mackenzie <acm <at> muc.de>
>
> > > Fread_from_minibuffer just calls read_minibuf. By perusing the source,
> > > it seems that two of the three repeating markers are created in
> > > save_window_save, called from Fcurrent_window_configuration (which is
> > > called from read_minibuf).
>
> > > With a bit of refactoring, we could arrange for (at least) two of these
> > > three regularly created markers to be nullified. This would be tedious
> > > rather than difficult.
>
> > Why aren't they collected by GC?
>
> They are, eventually.
>
> But my hypothesis is that between GC runs many hundreds of useless
> markers clog up the buffer's list of markers, and these in turn clog up
> the OP's (Óscar's) undo list.
GC runs quite frequently, and will both collect these markers and
compact the undo list. So I don't think this is a part of Óscar's
problem, at least not on the master branch. (On the igc branch we
currently have no solution for compacting the undo list, and I hope we
will find one soon.)
> And that if we could reduce the number of useless live markers we leave
> to GC, we could resolve the OP's problem. It may even be that the vast
> numbers of markers we suspect get created are slowing Emacs down
> noticeably, though there's no firm evidence for this at the moment.
If GC solves the problem, I don't think we should waste energy and
make the code trickier by trying to get rid of these markers faster.
We have other objects in Emacs that take their time to be collected
(example: font objects), and we don't consider that a problem.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Mon, 11 Aug 2025 20:55:02 GMT)
Full text and
rfc822 format available.
Message #209 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
>> Why aren't they collected by GC?
>
> They are, eventually.
>
> But my hypothesis is that between GC runs many hundreds of useless
> markers clog up the buffer's list of markers, and these in turn clog up
> the OP's (Óscar's) undo list.
>
> And that if we could reduce the number of useless live markers we leave
> to GC, we could resolve the OP's problem. It may even be that the vast
> numbers of markers we suspect get created are slowing Emacs down
> noticeably, though there's no firm evidence for this at the moment.
Since yesterday I'm running igc with 6f494d74f645d6c reverted, Pip's
detach_marker patch and this in .emacs:
(defun delete-markers-from-buffer-undo-list ()
(when (sequencep buffer-undo-list)
(setq buffer-undo-list
(cl-delete-if
(lambda (el) (and (consp el) (markerp (car el))))
buffer-undo-list
:end 500))))
(defvar delete-markers-from-buffer-undo-list-timer
(run-with-idle-timer 3.0 t 'delete-markers-from-buffer-undo-list))
I'm aware that something like this can cause nasal demons, but so far no
ill effects observed.
I think Emacs/igc is using less memory than usual (in my past experience
at this time it should be well over 1GB, but it's stabilized on 0.8GB.)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 03:45:02 GMT)
Full text and
rfc822 format available.
Message #212 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> I think Emacs/igc is using less memory than usual (in my past experience
> at this time it should be well over 1GB, but it's stabilized on
> 0.8GB.)
I still don't understand why these marker entries in the undo list are
made. Maybe someone else knows?
I mean, when we undo, markers may have to be adjusted, that's clear. But
why only specific markers, the ones having marker entries? Why not go
go over all buffer markers and adjust them according to what is undone?
I don't get it :-/.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 04:51:02 GMT)
Full text and
rfc822 format available.
Message #215 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
>
>> I think Emacs/igc is using less memory than usual (in my past experience
>> at this time it should be well over 1GB, but it's stabilized on
>> 0.8GB.)
>
> I still don't understand why these marker entries in the undo list are
> made. Maybe someone else knows?
>
> I mean, when we undo, markers may have to be adjusted, that's clear. But
> why only specific markers, the ones having marker entries? Why not go
> go over all buffer markers and adjust them according to what is undone?
>
> I don't get it :-/.
Whatever. After landing here
37ea8275f7faad1192ddaba9f4a0789580675e17
Author: Barry O'Reilly <gundaetiapo <at> gmail.com>
AuthorDate: Mon Mar 24 22:47:39 2014 -0400
Commit: Barry O'Reilly <gundaetiapo <at> gmail.com>
CommitDate: Mon Mar 24 22:47:39 2014 -0400
in the history, I doubt it is wise to pursue the idea of removing marker
entries further, unless we have someone who knows the undo code in and
out.
An alternative for igc, maybe, could be to make the markers in the
marker adjustment entries weak references. We'd need such weak
references, though, as Lisp objects. I have a vague memory that igc had
that at some point, does someone remember?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 07:57:01 GMT)
Full text and
rfc822 format available.
Message #218 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> I still don't understand why these marker entries in the undo list are
> made. Maybe someone else knows?
The automatic update of markers is insufficiently precise when the we
undo a text deletion, because all the markers that were anywhere within
the deleted text end up with the same position after the deletion.
So we have to record the offset for those markers that were in the
middle of the deleted text such that when we re-insert the text we can
put those markers back to where they were.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 08:04:01 GMT)
Full text and
rfc822 format available.
Message #221 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>> I still don't understand why these marker entries in the undo list are
>> made. Maybe someone else knows?
>
> The automatic update of markers is insufficiently precise when the we
> undo a text deletion, because all the markers that were anywhere within
> the deleted text end up with the same position after the deletion.
> So we have to record the offset for those markers that were in the
> middle of the deleted text such that when we re-insert the text we can
> put those markers back to where they were.
Ah, right, of course! Thanks!
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 08:10:01 GMT)
Full text and
rfc822 format available.
Message #224 received at 79200 <at> debbugs.gnu.org (full text, mbox):
On Tue, Aug 12 2025, Gerd Möllmann wrote:
> An alternative for igc, maybe, could be to make the markers in the
> marker adjustment entries weak references. We'd need such weak
> references, though, as Lisp objects. I have a vague memory that igc had
> that at some point, does someone remember?
For a time we had weak-ref Lisp objects. I suppose putting such
weak-refs in the undo list would still break some code. Instead of
weak-refs one could also use another layer of indirection, e.g. put a
fixnum in the undo list and the fixnum is a key in a weak hashtable that
holds markers weakly.
Even better would be if we could put positions instead of markers in the
undo list. After undoing, positions should be correct again; in an
ideal world anyway.
Helmut
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 08:28:01 GMT)
Full text and
rfc822 format available.
Message #227 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Helmut Eller <eller.helmut <at> gmail.com> writes:
> On Tue, Aug 12 2025, Gerd Möllmann wrote:
>
>> An alternative for igc, maybe, could be to make the markers in the
>> marker adjustment entries weak references. We'd need such weak
>> references, though, as Lisp objects. I have a vague memory that igc had
>> that at some point, does someone remember?
>
> For a time we had weak-ref Lisp objects. I suppose putting such
> weak-refs in the undo list would still break some code. Instead of
> weak-refs one could also use another layer of indirection, e.g. put a
> fixnum in the undo list and the fixnum is a key in a weak hashtable that
> holds markers weakly.
Yes. Or one could give markers a unique integer id, store that instead
of the marker itself in the marker adjustment entries. Then,
primitive-undo could iterate over the buffer's markers and only do
something for those markers it has an id entry for.
If that would work, we wouldn't need to employ weakness, which I think
might be a win. It's of course fiddly again. How to find all places
relying on the fact that markers are in the entries, with some
certainty?
What breakage are you thinking of?
> Even better would be if we could put positions instead of markers in the
> undo list. After undoing, positions should be correct again; in an
> ideal world anyway.
After Stef reminded me: All markers in the deleted range get the same
position (ignoring details) after the deletion, so I think a position
alone wouldn't suffice.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 08:49:02 GMT)
Full text and
rfc822 format available.
Message #230 received at 79200 <at> debbugs.gnu.org (full text, mbox):
On Tue, Aug 12 2025, Gerd Möllmann wrote:
[...]
>> For a time we had weak-ref Lisp objects. I suppose putting such
>> weak-refs in the undo list would still break some code. Instead of
>> weak-refs one could also use another layer of indirection, e.g. put a
>> fixnum in the undo list and the fixnum is a key in a weak hashtable that
>> holds markers weakly.
>
> Yes. Or one could give markers a unique integer id, store that instead
> of the marker itself in the marker adjustment entries. Then,
> primitive-undo could iterate over the buffer's markers and only do
> something for those markers it has an id entry for.
>
> If that would work, we wouldn't need to employ weakness, which I think
> might be a win. It's of course fiddly again. How to find all places
> relying on the fact that markers are in the entries, with some
> certainty?
Maybe we could create a new kind of entry, e.g
(adjust-marker MARKER-ID ADJUSTMENT)
instead of (MARKER . ADJUSTMENT). Or create (apply FUN . ARGS).
> What breakage are you thinking of?
Code in the wild that is inspecting the undo list.
>> Even better would be if we could put positions instead of markers in the
>> undo list. After undoing, positions should be correct again; in an
>> ideal world anyway.
>
> After Stef reminded me: All markers in the deleted range get the same
> position (ignoring details) after the deletion, so I think a position
> alone wouldn't suffice.
Ah, I see.
Helmut
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 09:24:01 GMT)
Full text and
rfc822 format available.
Message #233 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Helmut Eller <eller.helmut <at> gmail.com> writes:
> On Tue, Aug 12 2025, Gerd Möllmann wrote:
>
> [...]
>>> For a time we had weak-ref Lisp objects. I suppose putting such
>>> weak-refs in the undo list would still break some code. Instead of
>>> weak-refs one could also use another layer of indirection, e.g. put a
>>> fixnum in the undo list and the fixnum is a key in a weak hashtable that
>>> holds markers weakly.
>>
>> Yes. Or one could give markers a unique integer id, store that instead
>> of the marker itself in the marker adjustment entries. Then,
>> primitive-undo could iterate over the buffer's markers and only do
>> something for those markers it has an id entry for.
>>
>> If that would work, we wouldn't need to employ weakness, which I think
>> might be a win. It's of course fiddly again. How to find all places
>> relying on the fact that markers are in the entries, with some
>> certainty?
>
> Maybe we could create a new kind of entry, e.g
>
> (adjust-marker MARKER-ID ADJUSTMENT)
That looks good. We could extend Elisp manual, which currently says
‘(MARKER . ADJUSTMENT)’
This kind of element records the fact that the marker MARKER was
relocated due to deletion of surrounding text, and that it moved
ADJUSTMENT character positions. If the marker's location is
consistent with the (TEXT . POSITION) element preceding it in the
undo list, then undoing this element moves MARKER − ADJUSTMENT
characters.
And the new entry would use 3 or 2 conses, but who cares.
Managing an id could be tricky though. I don't know how to handle
pdumped markers in this regard. Maybe one could arrange that pdumped
markers get ids from 0...N, or negative ones perhaps, and newly created
markers would then start with N+1 or 0. WDYT?
> instead of (MARKER . ADJUSTMENT). Or create (apply FUN . ARGS).
>
>> What breakage are you thinking of?
>
> Code in the wild that is inspecting the undo list.
Hadn't thought about that. But I guess a new entry format would handle
that. New Emacs version, new record -> extend your hack.
Let's see what the others think about such a plan.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 11:03:02 GMT)
Full text and
rfc822 format available.
Message #236 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>> I still don't understand why these marker entries in the undo list are
>> made. Maybe someone else knows?
>
> The automatic update of markers is insufficiently precise when the we
> undo a text deletion, because all the markers that were anywhere within
> the deleted text end up with the same position after the deletion.
> So we have to record the offset for those markers that were in the
> middle of the deleted text such that when we re-insert the text we can
> put those markers back to where they were.
Yeah, I was suspecting that and expecting some breakage due to my
barbaric workaround.
However, the fact that still no breakage was observed makes me think
that those markers are created for a very brief use (within the
execution span of a single command, for instance.)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 14:09:02 GMT)
Full text and
rfc822 format available.
Message #239 received at 79200 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Let's see what the others think about such a plan.
Please find attached a patch which gives an impression what that could
look like. Entirely untested of course, plus for my Emacs, which has a
different marker implementation, plus I'm not certain which other Lisp
or C could be affected by such a change.
[0001-Use-adjust-marker-entries-in-undo-lists.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 14:41:02 GMT)
Full text and
rfc822 format available.
Message #242 received at 79200 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Let's see what the others think about such a plan.
>
> Please find attached a patch which gives an impression what that could
> look like. Entirely untested of course, plus for my Emacs, which has a
> different marker implementation, plus I'm not certain which other Lisp
> or C could be affected by such a change.
Had the DEFSYM wrong. With that a simple undo works in emacs -q. YMMV.
[0001-Fix-DEFSYM.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 15:16:01 GMT)
Full text and
rfc822 format available.
Message #245 received at 79200 <at> debbugs.gnu.org (full text, mbox):
On Tue, Aug 12 2025, Gerd Möllmann wrote:
> +static ptrdiff_t
> +next_marker_id (void)
> +{
> + static ptrdiff_t next = 0;
> + return next++;
> +}
[...]
> DUMP_FIELD_COPY (out, marker, insertion_type);
> + DUMP_FIELD_COPY (out, marker, id);
> + out->id *= -1;
I wonder if we shouldn't simply dump and restore the next id counter
(with pdumper_remember_scalar).
Helmut
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 15:25:02 GMT)
Full text and
rfc822 format available.
Message #248 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Helmut Eller <eller.helmut <at> gmail.com> writes:
> On Tue, Aug 12 2025, Gerd Möllmann wrote:
>
>> +static ptrdiff_t
>> +next_marker_id (void)
>> +{
>> + static ptrdiff_t next = 0;
>> + return next++;
>> +}
> [...]
>> DUMP_FIELD_COPY (out, marker, insertion_type);
>> + DUMP_FIELD_COPY (out, marker, id);
>> + out->id *= -1;
>
> I wonder if we shouldn't simply dump and restore the next id counter
> (with pdumper_remember_scalar).
Yeah, I think that's better.
The above isn't correct anyway if we dump an Emacs that has a dump
loaded. In that case the marker to be dumped could have a negative id
already, and so on.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 15:48:02 GMT)
Full text and
rfc822 format available.
Message #251 received at 79200 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Helmut Eller <eller.helmut <at> gmail.com> writes:
>
>> On Tue, Aug 12 2025, Gerd Möllmann wrote:
>>
>>> +static ptrdiff_t
>>> +next_marker_id (void)
>>> +{
>>> + static ptrdiff_t next = 0;
>>> + return next++;
>>> +}
>> [...]
>>> DUMP_FIELD_COPY (out, marker, insertion_type);
>>> + DUMP_FIELD_COPY (out, marker, id);
>>> + out->id *= -1;
>>
>> I wonder if we shouldn't simply dump and restore the next id counter
>> (with pdumper_remember_scalar).
>
> Yeah, I think that's better.
>
> The above isn't correct anyway if we dump an Emacs that has a dump
> loaded. In that case the marker to be dumped could have a negative id
> already, and so on.
Like so, I think:
[0001-Don-t-use-negative-marker-ids.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 15:59:02 GMT)
Full text and
rfc822 format available.
Message #254 received at 79200 <at> debbugs.gnu.org (full text, mbox):
On Tue, Aug 12 2025, Gerd Möllmann wrote:
> Like so, I think:
I think the DEFVAR_INT is not needed. Something like this:
static ptrdiff_t next_marker_id;
static ptrdiff_t
next_marker_id (void)
{
return next_marker_id++;
}
and in syms_of_alloc
PDUMPER_REMEMBER_SCALAR(next_marker_id);
should also work.
Helmut
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 16:28:01 GMT)
Full text and
rfc822 format available.
Message #257 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Helmut Eller <eller.helmut <at> gmail.com> writes:
> On Tue, Aug 12 2025, Gerd Möllmann wrote:
>
>> Like so, I think:
>
> I think the DEFVAR_INT is not needed. Something like this:
>
> static ptrdiff_t next_marker_id;
>
> static ptrdiff_t
> next_marker_id (void)
> {
> return next_marker_id++;
> }
>
> and in syms_of_alloc
>
> PDUMPER_REMEMBER_SCALAR(next_marker_id);
>
> should also work.
That's true.
I've made it a DEFVAR mainly because I wanted to be able to see it
easily :-).
Don't know if the wrap-around check in next_marker_id is really
necessary; that's just paranoia, I guess, or maybe laziness, not wanting
to calculate :-).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 17:51:02 GMT)
Full text and
rfc822 format available.
Message #260 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Helmut Eller <eller.helmut <at> gmail.com> writes:
>
>> On Tue, Aug 12 2025, Gerd Möllmann wrote:
>>
>>> Like so, I think:
>>
>> I think the DEFVAR_INT is not needed. Something like this:
>>
>> static ptrdiff_t next_marker_id;
>>
>> static ptrdiff_t
>> next_marker_id (void)
>> {
>> return next_marker_id++;
>> }
>>
>> and in syms_of_alloc
>>
>> PDUMPER_REMEMBER_SCALAR(next_marker_id);
>>
>> should also work.
>
> That's true.
>
> I've made it a DEFVAR mainly because I wanted to be able to see it
> easily :-).
>
> Don't know if the wrap-around check in next_marker_id is really
> necessary; that's just paranoia, I guess, or maybe laziness, not wanting
> to calculate :-).
gmake -C test undo-tests
ELC src/undo-tests.elc
GEN src/undo-tests.log
Running 19 tests (2025-08-12 19:45:59+0200, selector `(not (or (tag :unstable) (tag :nativecomp)))')
Undo
passed 1/19 undo-test-buffer-modified (0.000154 sec)
passed 2/19 undo-test-combine-change-calls-1 (0.002497 sec)
passed 3/19 undo-test-combine-change-calls-2 (0.002259 sec)
passed 4/19 undo-test-combine-change-calls-3 (0.003523 sec)
Undo
passed 5/19 undo-test-file-modified (0.002142 sec)
Undo
passed 6/19 undo-test-marker-adjustment-moved (0.000036 sec)
Undo
passed 7/19 undo-test-marker-adjustment-nominal (0.000037 sec)
Undo in region
passed 8/19 undo-test-region-deletion (0.000045 sec)
Undo
Undo in region
passed 9/19 undo-test-region-eob (0.000045 sec)
Undo in region
Undo in region
passed 10/19 undo-test-region-example (0.000053 sec)
Undo
Undo in region
passed 11/19 undo-test-region-mark-adjustment (0.000053 sec)
Undo in region
passed 12/19 undo-test-region-not-most-recent (0.000038 sec)
Undo in region
passed 13/19 undo-test-region-t-marker (0.000035 sec)
Undo
passed 14/19 undo-test-skip-invalidated-markers (0.000083 sec)
Undo
passed 15/19 undo-test0 (0.000069 sec)
Undo
Undo
passed 16/19 undo-test1 (0.000045 sec)
Undo
Undo
passed 17/19 undo-test2 (0.000047 sec)
Undo
Undo
passed 18/19 undo-test4 (0.435426 sec)
Undo
passed 19/19 undo-test5 (0.000120 sec)
Ran 19 tests, 19 results as expected, 0 unexpected (2025-08-12 19:46:00+0200, 0.447184 sec)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Tue, 12 Aug 2025 18:23:02 GMT)
Full text and
rfc822 format available.
Message #263 received at 79200 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
Please find a port to feature/igc attached, for testing if you like.
I'll run with these changes in my Emacs and see what happens.
[0001-Use-adjust-marker-entries-in-undo-lists.patch (text/x-patch, attachment)]
[0002-Fix-DEFSYM.patch (text/x-patch, attachment)]
[0003-Don-t-use-negative-marker-ids.patch (text/x-patch, attachment)]
[0004-Port-marker-with-id.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Wed, 13 Aug 2025 03:30:02 GMT)
Full text and
rfc822 format available.
Message #266 received at 79200 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
> Please find a port to feature/igc attached, for testing if you like.
> I'll run with these changes in my Emacs and see what happens.
Forfot to compact the undo list:
[0001-Compact-undo-list.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Wed, 13 Aug 2025 06:40:01 GMT)
Full text and
rfc822 format available.
Message #269 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Helmut Eller <eller.helmut <at> gmail.com> writes:
>
>> On Tue, Aug 12 2025, Gerd Möllmann wrote:
>>
>>> Like so, I think:
>>
>> I think the DEFVAR_INT is not needed. Something like this:
>>
>> static ptrdiff_t next_marker_id;
>>
>> static ptrdiff_t
>> next_marker_id (void)
>> {
>> return next_marker_id++;
>> }
>>
>> and in syms_of_alloc
>>
>> PDUMPER_REMEMBER_SCALAR(next_marker_id);
>>
>> should also work.
>
> That's true.
>
> I've made it a DEFVAR mainly because I wanted to be able to see it
> easily :-).
>
> Don't know if the wrap-around check in next_marker_id is really
> necessary; that's just paranoia, I guess, or maybe laziness, not wanting
> to calculate :-).
BTW, C-h v next--marker-id and 'g' to refresh is somwwhat interesting.
In my mac GUI session each 'g' shows 472 markers have been made.
Whatever that means.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Wed, 13 Aug 2025 08:20:02 GMT)
Full text and
rfc822 format available.
Message #272 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello, Gerd.
On Wed, Aug 13, 2025 at 08:39:11 +0200, Gerd Möllmann wrote:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> > Helmut Eller <eller.helmut <at> gmail.com> writes:
> >> On Tue, Aug 12 2025, Gerd Möllmann wrote:
> >>> Like so, I think:
> >> I think the DEFVAR_INT is not needed. Something like this:
> >> static ptrdiff_t next_marker_id;
> >> static ptrdiff_t
> >> next_marker_id (void)
> >> {
> >> return next_marker_id++;
> >> }
> >> and in syms_of_alloc
> >> PDUMPER_REMEMBER_SCALAR(next_marker_id);
> >> should also work.
> > That's true.
> > I've made it a DEFVAR mainly because I wanted to be able to see it
> > easily :-).
> > Don't know if the wrap-around check in next_marker_id is really
> > necessary; that's just paranoia, I guess, or maybe laziness, not wanting
> > to calculate :-).
> BTW, C-h v next--marker-id and 'g' to refresh is somwwhat interesting.
> In my mac GUI session each 'g' shows 472 markers have been made.
> Whatever that means.
That sounds a lot, but .... many of these markers will have a short
lifetime, being rapidly terminated with (set-marker foo nil) or the like.
What matters more is surely the number of markers which persist and can
get into buffer-undo-list. In your current version, have you built my
function buffer-marker-list into it? M-: (length (buffer-marker-list))
is revealing. Currently when I run that form repeatedly, I'm getting an
extra 3 markers per repetition. That's in my version which takes care to
eliminate markers as soon as possible after they're not needed.
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Wed, 13 Aug 2025 08:39:02 GMT)
Full text and
rfc822 format available.
Message #275 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
>> BTW, C-h v next--marker-id and 'g' to refresh is somwwhat interesting.
>> In my mac GUI session each 'g' shows 472 markers have been made.
>> Whatever that means.
Hi Alan.
> That sounds a lot, but .... many of these markers will have a short
> lifetime, being rapidly terminated with (set-marker foo nil) or the
> like.
One would hope so, yes :-).
> What matters more is surely the number of markers which persist and can
> get into buffer-undo-list. In your current version, have you built my
> function buffer-marker-list into it? M-: (length (buffer-marker-list))
> is revealing. Currently when I run that form repeatedly, I'm getting an
> extra 3 markers per repetition. That's in my version which takes care to
> eliminate markers as soon as possible after they're not needed.
No, I don't have your function. Reason is that there are currently 3
implementations of BUF_MARKERS, and porting to all the variants was to
much for me, ATM.
(1) in mainstream BUF_MARKERS is a list
(2) in igc it's a "marker array"
(3) in my Emacs it's a different kind of marker array. That's because
Stef asked if I could port the marker array from (2) to mainstream,
and that ended up also with a different marker implementation. That
I ported back to mainstream in feature/text-index, text-index.[ch]
and marker-array.[ch]. Don't know what Stef's plans are wrt to that.
It's complicated ;-).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Wed, 13 Aug 2025 13:12:02 GMT)
Full text and
rfc822 format available.
Message #278 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello, Gerd.
On Wed, Aug 13, 2025 at 10:37:49 +0200, Gerd Möllmann wrote:
> Alan Mackenzie <acm <at> muc.de> writes:
> >> BTW, C-h v next--marker-id and 'g' to refresh is somwwhat interesting.
> >> In my mac GUI session each 'g' shows 472 markers have been made.
> >> Whatever that means.
> Hi Alan.
> > That sounds a lot, but .... many of these markers will have a short
> > lifetime, being rapidly terminated with (set-marker foo nil) or the
> > like.
> One would hope so, yes :-).
> > What matters more is surely the number of markers which persist and can
> > get into buffer-undo-list. In your current version, have you built my
> > function buffer-marker-list into it? M-: (length (buffer-marker-list))
> > is revealing. Currently when I run that form repeatedly, I'm getting an
> > extra 3 markers per repetition. That's in my version which takes care to
> > eliminate markers as soon as possible after they're not needed.
> No, I don't have your function. Reason is that there are currently 3
> implementations of BUF_MARKERS, and porting to all the variants was to
> much for me, ATM.
> (1) in mainstream BUF_MARKERS is a list
> (2) in igc it's a "marker array"
> (3) in my Emacs it's a different kind of marker array. That's because
> Stef asked if I could port the marker array from (2) to mainstream,
> and that ended up also with a different marker implementation. That
> I ported back to mainstream in feature/text-index, text-index.[ch]
> and marker-array.[ch]. Don't know what Stef's plans are wrt to that.
> It's complicated ;-).
For what it's worth, I put next--marker-id into my Emacs, just as a
counter, nothing else.
In my emacs -Q, I do C-h v next--marker-id like you did, and a repeated
g to refresh it. I get just 76 markers made at each iteration.
That makes your 472 look high indeed. Might it possibly be there's a
bug with DEFVAR_INT somewhere, and that 472 = 8 * 59 has wrongly got the
3 type bits in it, and is really just 59? Just a suggestion.
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Wed, 13 Aug 2025 13:21:01 GMT)
Full text and
rfc822 format available.
Message #281 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
> For what it's worth, I put next--marker-id into my Emacs, just as a
> counter, nothing else.
>
> In my emacs -Q, I do C-h v next--marker-id like you did, and a repeated
> g to refresh it. I get just 76 markers made at each iteration.
Also interesting. With emacs -Q -nw, I get a delta of ca. 140, and in
the GUI (mac) I get 270.
> That makes your 472 look high indeed. Might it possibly be there's a
> bug with DEFVAR_INT somewhere, and that 472 = 8 * 59 has wrongly got the
> 3 type bits in it, and is really just 59? Just a suggestion.
I think that's unlikely. There are a lot such defvar, and I think
someone would have noticed such a bug.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 05:21:01 GMT)
Full text and
rfc822 format available.
Message #284 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Alan Mackenzie <acm <at> muc.de> writes:
>
>> For what it's worth, I put next--marker-id into my Emacs, just as a
>> counter, nothing else.
>>
>> In my emacs -Q, I do C-h v next--marker-id like you did, and a repeated
>> g to refresh it. I get just 76 markers made at each iteration.
>
> Also interesting. With emacs -Q -nw, I get a delta of ca. 140, and in
> the GUI (mac) I get 270.
>
>> That makes your 472 look high indeed. Might it possibly be there's a
>> bug with DEFVAR_INT somewhere, and that 472 = 8 * 59 has wrongly got the
>> 3 type bits in it, and is really just 59? Just a suggestion.
>
> I think that's unlikely. There are a lot such defvar, and I think
> someone would have noticed such a bug.
So, with the patches I sent, plus a variable I've added, I can see that
compact_undo_list now removes entries from the undo-list. Question is is
it enough to be practical?
I'm afraid I can't answer that - it took me 4 months and a port of igc
to mac to notice the problem to begin with.
@Oscar: can you perhaps give it a try in the real world?
modified src/alloc.c
@@ -5832,7 +5832,10 @@ compact_undo_list (Lisp_Object buffer)
Lisp_Object marker = Fmarker_with_id (id, buffer);
#ifdef HAVE_MPS
if (NILP (marker))
- *prev = XCDR (tail);
+ {
+ ++n_compacted;
+ *prev = XCDR (tail);
+ }
else
prev = xcdr_addr (tail);
#else
@@ -7709,6 +7712,9 @@ init_alloc (void)
void
syms_of_alloc (void)
{
+ DEFVAR_INT ("n-compacted", n_compacted, doc : /**/);
+ n_compacted = 0;
+
DEFVAR_INT ("gc-cons-threshold", gc_cons_threshold,
doc: /* Number of bytes of consing between garbage collections.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 05:22:02 GMT)
Full text and
rfc822 format available.
Message #287 received at 79200 <at> debbugs.gnu.org (full text, mbox):
> I'm afraid I can't answer that - it took me 4 months and a port of igc
4 months after the commit that made the marker in the mode-line display
a problem so to speark.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 05:46:02 GMT)
Full text and
rfc822 format available.
Message #290 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>> I'm afraid I can't answer that - it took me 4 months and a port of igc
>
> 4 months after the commit that made the marker in the mode-line display
> a problem so to speark.
@Oscar: I've put feature/igc + the patches here:
https://github.com/gerd-moellmann/emacs-with-cl-packages.git
Guess that's more convenient :-).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 09:54:01 GMT)
Full text and
rfc822 format available.
Message #293 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Alan Mackenzie <acm <at> muc.de> writes:
>
>> For what it's worth, I put next--marker-id into my Emacs, just as a
>> counter, nothing else.
>>
>> In my emacs -Q, I do C-h v next--marker-id like you did, and a repeated
>> g to refresh it. I get just 76 markers made at each iteration.
>
> Also interesting. With emacs -Q -nw, I get a delta of ca. 140, and in
> the GUI (mac) I get 270.
>
>> That makes your 472 look high indeed. Might it possibly be there's a
>> bug with DEFVAR_INT somewhere, and that 472 = 8 * 59 has wrongly got the
>> 3 type bits in it, and is really just 59? Just a suggestion.
>
> I think that's unlikely. There are a lot such defvar, and I think
> someone would have noticed such a bug.
Another interesting detail that I didn't remember are the values of
undo-limit and undo-strong-limit. I don't understand why they are so
high (160000/240000). With 1 undo/s, I could undo for 2 days.
Whatever, Maybe I'm overlooking something here.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 10:05:02 GMT)
Full text and
rfc822 format available.
Message #296 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> Alan Mackenzie <acm <at> muc.de> writes:
>>
>>> For what it's worth, I put next--marker-id into my Emacs, just as a
>>> counter, nothing else.
>>>
>>> In my emacs -Q, I do C-h v next--marker-id like you did, and a repeated
>>> g to refresh it. I get just 76 markers made at each iteration.
>>
>> Also interesting. With emacs -Q -nw, I get a delta of ca. 140, and in
>> the GUI (mac) I get 270.
>>
>>> That makes your 472 look high indeed. Might it possibly be there's a
>>> bug with DEFVAR_INT somewhere, and that 472 = 8 * 59 has wrongly got the
>>> 3 type bits in it, and is really just 59? Just a suggestion.
>>
>> I think that's unlikely. There are a lot such defvar, and I think
>> someone would have noticed such a bug.
>
> Another interesting detail that I didn't remember are the values of
> undo-limit and undo-strong-limit. I don't understand why they are so
> high (160000/240000). With 1 undo/s, I could undo for 2 days.
>
> Whatever, Maybe I'm overlooking something here.
Maybe undo in a region that one has modified longer ago. Hm.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 10:28:01 GMT)
Full text and
rfc822 format available.
Message #299 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Hello, Gerd.
On Thu, Aug 14, 2025 at 11:53:40 +0200, Gerd Möllmann wrote:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> > Alan Mackenzie <acm <at> muc.de> writes:
> >> For what it's worth, I put next--marker-id into my Emacs, just as a
> >> counter, nothing else.
> >> In my emacs -Q, I do C-h v next--marker-id like you did, and a repeated
> >> g to refresh it. I get just 76 markers made at each iteration.
> > Also interesting. With emacs -Q -nw, I get a delta of ca. 140, and in
> > the GUI (mac) I get 270.
> >> That makes your 472 look high indeed. Might it possibly be there's a
> >> bug with DEFVAR_INT somewhere, and that 472 = 8 * 59 has wrongly got the
> >> 3 type bits in it, and is really just 59? Just a suggestion.
> > I think that's unlikely. There are a lot such defvar, and I think
> > someone would have noticed such a bug.
> Another interesting detail that I didn't remember are the values of
> undo-limit and undo-strong-limit. I don't understand why they are so
> high (160000/240000). With 1 undo/s, I could undo for 2 days.
> Whatever, Maybe I'm overlooking something here.
I think those limits are numbers of bytes, not numbers of undo
operations. A single kill command in a big buffer could easily fill
these numbers of bytes.
I more wonder why those limits are so low. It's a long time since PCs'
RAM capacity was measured in mere megabytes.
--
Alan Mackenzie (Nuremberg, Germany).
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 10:35:01 GMT)
Full text and
rfc822 format available.
Message #302 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
> Hello, Gerd.
>
> On Thu, Aug 14, 2025 at 11:53:40 +0200, Gerd Möllmann wrote:
>> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
>> > Alan Mackenzie <acm <at> muc.de> writes:
>
>> >> For what it's worth, I put next--marker-id into my Emacs, just as a
>> >> counter, nothing else.
>
>> >> In my emacs -Q, I do C-h v next--marker-id like you did, and a repeated
>> >> g to refresh it. I get just 76 markers made at each iteration.
>
>> > Also interesting. With emacs -Q -nw, I get a delta of ca. 140, and in
>> > the GUI (mac) I get 270.
>
>> >> That makes your 472 look high indeed. Might it possibly be there's a
>> >> bug with DEFVAR_INT somewhere, and that 472 = 8 * 59 has wrongly got the
>> >> 3 type bits in it, and is really just 59? Just a suggestion.
>
>> > I think that's unlikely. There are a lot such defvar, and I think
>> > someone would have noticed such a bug.
>
>> Another interesting detail that I didn't remember are the values of
>> undo-limit and undo-strong-limit. I don't understand why they are so
>> high (160000/240000). With 1 undo/s, I could undo for 2 days.
>
>> Whatever, Maybe I'm overlooking something here.
>
> I think those limits are numbers of bytes, not numbers of undo
> operations. A single kill command in a big buffer could easily fill
> these numbers of bytes.
Ah, you're right. I had only read upto
Don’t keep more than this much size of undo information.
and it later says
The size is counted as the number of bytes occupied,
which includes both saved text and other data.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 11:06:01 GMT)
Full text and
rfc822 format available.
Message #305 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Alan Mackenzie <acm <at> muc.de> writes:
> I more wonder why those limits are so low. It's a long time since PCs'
> RAM capacity was measured in mere megabytes.
That, and then the fact that I can produce very long undo list, as long
as they don't exceed the size in bytes limits. And these lists can
contain a lot of markers.
(defun my-test-undo-list ()
(interactive)
(with-current-buffer (get-buffer-create "undo-list-test.txt")
(erase-buffer)
(setf buffer-undo-list nil)
(dotimes (i 1000)
(dotimes (j 10)
(insert "abcd")
(dotimes (i 5) (point-marker))
(backward-delete-char 1)
(undo-boundary)
(insert "\n")))
'(igc-collect)
(message "undo-list length %d (%d)" (length buffer-undo-list) n-compacted)
'(kill-buffer (current-buffer))))
The above produces an undo list with length 80000.
I think it might make sense to limit that to some reasonable number.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 11:26:02 GMT)
Full text and
rfc822 format available.
Message #308 received at 79200 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
> Alan Mackenzie <acm <at> muc.de> writes:
>
>> I more wonder why those limits are so low. It's a long time since PCs'
>> RAM capacity was measured in mere megabytes.
>
> That, and then the fact that I can produce very long undo list, as long
> as they don't exceed the size in bytes limits. And these lists can
> contain a lot of markers.
>
> (defun my-test-undo-list ()
> (interactive)
> (with-current-buffer (get-buffer-create "undo-list-test.txt")
> (erase-buffer)
> (setf buffer-undo-list nil)
> (dotimes (i 1000)
> (dotimes (j 10)
> (insert "abcd")
> (dotimes (i 5) (point-marker))
> (backward-delete-char 1)
> (undo-boundary)
> (insert "\n")))
> '(igc-collect)
> (message "undo-list length %d (%d)" (length buffer-undo-list) n-compacted)
> '(kill-buffer (current-buffer))))
>
> The above produces an undo list with length 80000.
>
> I think it might make sense to limit that to some reasonable number.
@Oscar: the patch below adds such a variable. My gut feeling is that
might well resolve the whole problem, without the other stuff, i.e.
applied directly to feature/igc. Sorry for the back and forth.
[0001-New-variable-undo-group-limit.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 13:50:02 GMT)
Full text and
rfc822 format available.
Message #311 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Taking a step back:
We may want to rethink whether storing that undo information is worth
the trouble at all. It's hard to know for sure, but we do have one data
point: in Emacs-28, overlays' end-points used those marker-offset undo
elements to better preserve overlays' end-points across undo, whereas
this was lost with emacs-29's new overlays.
AFAIK nobody noticed/complained.
Stefan
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 14:15:01 GMT)
Full text and
rfc822 format available.
Message #314 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
> Taking a step back:
>
> We may want to rethink whether storing that undo information is worth
> the trouble at all. It's hard to know for sure, but we do have one data
> point: in Emacs-28, overlays' end-points used those marker-offset undo
> elements to better preserve overlays' end-points across undo, whereas
> this was lost with emacs-29's new overlays.
>
> AFAIK nobody noticed/complained.
Here I'm working with an idle timer that simply removes those marker
elements every few seconds. Five days of intensive use and Emacs behaves
normally from my POV. Maybe my usage is too restrictive, dunno (I never
use undo-in-region, for instance.)
OTOH, Emacs is using much less memory than usual (rigth now at 1.1 GB
when 2.5 was normal.)
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 14:23:01 GMT)
Full text and
rfc822 format available.
Message #317 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
Hi Gerd.
>> The above produces an undo list with length 80000.
>>
>> I think it might make sense to limit that to some reasonable number.
>
> @Oscar: the patch below adds such a variable. My gut feeling is that
> might well resolve the whole problem, without the other stuff, i.e.
> applied directly to feature/igc. Sorry for the back and forth.
Is this really addresset at me? Do you want me to try your patch? This
patch alone or on top of the previous ones?
Your discussion with Alan is way beyond my knowledge, but if the patch
just keeps the list under a certain length, as it seems, I don't see how
it can be a fix, as AFAIK the problem consists on the size of the new
undo info increasing as a function of the size of the previous one, so
at some point recording a new undo just overflows the capacity.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 15:05:01 GMT)
Full text and
rfc822 format available.
Message #320 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
> Hi Gerd.
>
>>> The above produces an undo list with length 80000.
>>>
>>> I think it might make sense to limit that to some reasonable number.
>>
>> @Oscar: the patch below adds such a variable. My gut feeling is that
>> might well resolve the whole problem, without the other stuff, i.e.
>> applied directly to feature/igc. Sorry for the back and forth.
>
> Is this really addresset at me?
Yes please, that would be very nice, because you seem to do something in
the real world that produces the problem with markers+igc, while I
apparently don't encounter that normally.
> Do you want me to try your patch? This patch alone or on top of the
> previous ones?
On top of the original feature/igc with no other changes. The maximum
depth of undo is then 200, which is an arbitrary number.
> Your discussion with Alan is way beyond my knowledge, but if the patch
> just keeps the list under a certain length, as it seems, I don't see how
> it can be a fix, as AFAIK the problem consists on the size of the new
> undo info increasing as a function of the size of the previous one, so
> at some point recording a new undo just overflows the capacity.
Let me try to explain what I'm seeing, conjecturing, have learned etc.:
The whole problem occurs because we have lots and lots of
marker-adjustment records in undo lists. The old GC gets rid of them by
cleaning them up during GC, That's compact_undo_list. IGC can't do that
in the same way because it's completely different, so the marker entries
basically pile up and up and up.
Secondly, we have undo-limit and undo-strong-limit which is fine, but we
don't have something that limits the number of possible undos
themselves. As long as the size limits aren't reaches, undo lists
happily grow into the thousands of undo-boundaries, i.e. individually
undoable operations. So much that I think it makes no sense any more. No
one would do 1000 undos. That's why I think limiting that to some number
makes sense. I'm using 100 in my Emacs ATM. That is the change in
truncate_undo_list.
Thirdly, by discarding undo entries after the nth undo-boundary, we of
course reduce the marker-adjustment entries which are part of text
entries of the discarded list elements. This should reduce the whole
problem to something that's fine, at least my gut feeling is that it
does.
And fourth, igc already calls compact_buffer, which calls
truncate_undo_list in igc_on_Idle. That's why this should work in the
end.
And fifth, if that is "good enough" in the real world it is of course
much less complex and whatnot than everything else.
Something like that. Hope it's more or less understandable.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 16:58:01 GMT)
Full text and
rfc822 format available.
Message #323 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
* src/undo.c (truncate_undo_list): Use undo_group_limit.
(syms_of_undo): Add DEFVAR_INT.
[snip]
Thank you for the detailed explanation. I'm running it now on one of the
two machines that I use daily. Apart from reporting obvious problems, do
you want other info that requires inspecting buffer-undo-list or
anything else from time to time?
BTW, saying "No one would do 1000 undos" sounds very sensible. But on
some circunstances I've seen how almost every character produced an undo
boundary (time ago with Evil, now it seems better.) Also, some packages
allow you to navigate the undo history on a way that is easy to restore
the state of the buffer when its content's met certain criteria, like
some text was added or removed, which could happened long time ago on
the session. Having a limit of 200 (or 2000) undo steps may be
constraining for the users of those packages. Also, it would be
interesting to see how much memory the average undo step consumes
(without the pathological marker adjustment elements.) That way we could
know if your change is significantly reducing the amount of undo info
that Emacs traditionally stored.
While writing this e-mail the associated buffer-undo-list grew to 6000+
elements, almost all of them marker adjustments. Executing igc-collect
made no difference, but IIUC this is expected, the effects of your patch
should begin after exceeding undo-group-limit. While writing English
prose I make *lots* of corrections, maybe that's one of the main reasons
why the problem affects me on a larger way.
Just before finishing this e-mail, buffer-undo-list went down to 3000+
elements, almost all of them markers.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 17:54:01 GMT)
Full text and
rfc822 format available.
Message #326 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:
>
> * src/undo.c (truncate_undo_list): Use undo_group_limit.
> (syms_of_undo): Add DEFVAR_INT.
>
> [snip]
>
> Thank you for the detailed explanation. I'm running it now on one of the
> two machines that I use daily.
Thanks!
> Apart from reporting obvious problems, do you want other info that
> requires inspecting buffer-undo-list or anything else from time to
> time?
Can't think of something specific at the moment. For me, a general
impression of how it is doing with the undo-group-limit would suffice.
> BTW, saying "No one would do 1000 undos" sounds very sensible. But on
> some circunstances I've seen how almost every character produced an undo
> boundary (time ago with Evil, now it seems better.) Also, some packages
> allow you to navigate the undo history on a way that is easy to restore
> the state of the buffer when its content's met certain criteria, like
> some text was added or removed, which could happened long time ago on
> the session. Having a limit of 200 (or 2000) undo steps may be
> constraining for the users of those packages.
I guess you are thinking of vundo for example. I tried it once and it
was nice, but since I never used it after installation, I removed it
again. YMMV. And they could set the value to something higher. Don't
know if they require a lot of undos. For vundo, it seems it needed only
few because it displayed the states as graphical nodes and so on. And
there is only limited space for that. But I can't really say much about
that.
> Also, it would be interesting to see how much memory the average undo
> step consumes (without the pathological marker adjustment elements.)
> That way we could know if your change is significantly reducing the
> amount of undo info that Emacs traditionally stored.
Hm.
> While writing this e-mail the associated buffer-undo-list grew to 6000+
> elements, almost all of them marker adjustments. Executing igc-collect
> made no difference, but IIUC this is expected, the effects of your patch
> should begin after exceeding undo-group-limit.
Right. The groups would be the nil list elements if I'm not mistaken.
> While writing English prose I make *lots* of corrections, maybe that's
> one of the main reasons why the problem affects me on a larger way.
>
Could be something like that. Or ispell maybe?
> Just before finishing this e-mail, buffer-undo-list went down to 3000+
> elements, almost all of them markers.
That sounds promising 👍
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#79200
; Package
emacs
.
(Thu, 14 Aug 2025 17:58:01 GMT)
Full text and
rfc822 format available.
Message #329 received at 79200 <at> debbugs.gnu.org (full text, mbox):
Óscar Fuentes <oscarfv <at> eclipso.eu> writes:
> While writing this e-mail the associated buffer-undo-list grew to 6000+
> elements, almost all of them marker adjustments. Executing igc-collect
> made no difference, but IIUC this is expected,
And again forgotten something, as usual :-/.
Yes that's expected without the other patches. I'd go with without these
patches though if the simple solution sufifcces, at least in my Emacs,
feature/igc is another story.
This bug report was last modified today.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.