Subject: bug#77924: 31.0.50; [Feature branch] Change marker implementation

From: Gerd Möllmann <[email-masked]>
Date: Thu, 24 Apr 2025 11:18:04 +0200

Gerd Möllmann <[email-masked]> writes:

> martin rudalics <[email-masked]> writes:
>
>>> BTW, during my rebasing I noticed the following incompatibility:
>>>
>>>      commit 89ad510b2ebd5ed3ed8477e4a45ada3402bcedca
>>>      Author: Gerd Möllmann <[email-masked]>
>>>      Date:   Thu Apr 17 08:42:52 2025 +0200
>>>
>>>          marker-vector.c: Move marker's position info to the array
>>>
>>> makes it "impossible" to implement `marker-last-position`.
>>
>> What would 'markerp' then return for a marker whose buffer has been
>> killed?  The idea of 'marker-last-position' is that if some agent (like
>> a tab bar entry) keeps a reference to a killed buffer, that buffer
>> cannot be collected and neither its markers, although the latter have
>> been unchained already.  ‘marker-position’ would always return nil for
>> such a marker but 'marker-last-position' would have worked in the past.
>>
>>> AFAICT this function is not used outside of Emacs at all (based on
>>> a search of all *ELPA packages), but it *is* used in
>>> `window--state-put-2`, since the following commit:
>>>
>>>      commit 912e37b811107768e0cb3bc95184177f817dbdb2
>>>      Author: Martin Rudalics <[email-masked]>
>>>      Date:   Mon Mar 4 10:33:49 2024 +0100
>>>
>>>          Fix 'set-window-configuration' and 'window-state-put'
>>>
>>> What's the impact of breaking `marker-last-position`?
>>
>> If 'window-restore-killed-buffer-windows' is a function that tries to
>> resurrect a killed buffer, it could not derive the position of the start
>> and point position of the buffer in that window.  So AFAICT the function
>> 'tab-bar-select-restore-windows' would be affected.  Juri can tell more.
>>
>> martin
>
> Hm, that might be an unsolvable problem with igc, actually. At least I
> don't know ATM how it could be solved.
>
> Let me try to explain. The function below is what igc uses to scan a
> marker vector and remove stale references (weak references). It's from
> my Emacs, not from feature/igc, but that doesn't play a role. the
> situation is the same here and there.
>
> igc.c:
>  2136 static mps_res_t
>  2137 fix_marker_vector (mps_ss_t ss, struct Lisp_Vector *v)
>  2138 {
>  2139   MPS_SCAN_BEGIN (ss)
>  2140   {
>  2141     const ptrdiff_t max_entry = XFIXNUM (v->contents[MARKER_VECTOR_MAX_ENTRY]);
>  2142     for (ptrdiff_t e = MARKER_VECTOR_HEADER_SIZE;
>  2143          e <= max_entry; e += MARKER_VECTOR_ENTRY_SIZE)
>  2144       {
>  2145         /* Note that we cannot access anything of a marker here because
>  2146            that is not allowed by MPS while scanning an unrelated
>  2147            object.  This includes MARKERP because that accesses the
>  2148            header of a marker.  */
>  2149         Lisp_Object *p = &v->contents[e + MARKER_VECTOR_OFFSET_MARKER];
>  2150         if (!NILP (*p) && !FIXNUMP (*p))
>  2151           {
>  2152             IGC_FIX12_OBJ (ss, p);
>  2153             if (NILP (*p))
>  2154               {
>  2155                 /* Changed to nil means the weak reference was to a dead
>  2156                    marker.  Put on free-list.  */
>  2157                 v->contents[e] = v->contents[MARKER_VECTOR_FREE];
>  2158                 v->contents[MARKER_VECTOR_FREE] = make_fixnum (e);
>  2159               }
>  2160           }
>  2161       }
>  2162   }
>  2163   MPS_SCAN_END (ss);
>  2164   return MPS_RES_OK;
>  2165 }
>
> The problem is that MPS doesn't allow accessing other MPS-managed
> objects while working on the marker vector. See the comment at line 2145.
>
> Markers are such MPS-managed objects, so we can't read or change members
> of a marker here, not the buffer, not something else.
>
> That restriction is very real, it suffices to add a MARKERP there to
> make things literally fall apart when a marker object happens to be
> behind a memory barrier, for example.
>
> Like I said, no idea. I've added Helmut and Pip in CC.

No wait, not a problem :-). If someone from Lisp has that marker in his
hands, it's of course not dead. So, sorry for the confusion.

So, one could, theoretically store the charpos in a field of a marker
when "unchaining" it. Ugly, but doable.