Subject: Re: bug#75322: SAFE_ALLOCA assumed to root Lisp_Objects/SSDATA(string)

From: Gerd Möllmann <[email-masked]>
Date: Sun, 05 Jan 2025 19:17:37 +0100

Eli Zaretskii <[email-masked]> writes:

>> From: Gerd Möllmann <[email-masked]>
>> Cc: [email-masked],  [email-masked]
>> Date: Sun, 05 Jan 2025 15:11:08 +0100
>> 
>> Eli Zaretskii <[email-masked]> writes:
>> 
>> > And if GC _can_ happen,
>> > but we don't use the allocated block again, is that a problem? For
>> > example, in this fragment:
>> >
>> > 	    SAFE_NALLOCA (args2, 1, nargs + 1);
>> > 	    args2[0] = Qcall_process;
>> > 	    for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
>> > 	    coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
>> > 	    val = CONSP (coding_systems) ? XCDR (coding_systems) : Qnil;
>> >
>> > Let's say Ffind_operation_coding_system could trigger GC.  But we
>> > never again use the args2[] array after Ffind_operation_coding_system
>> > returns.  Is the above still unsafe?  If so, could you tell what
>> > could MPS do during GC to make this unsafe?
>> 
>> Let me first say why I find this unsafe in the old GC, in principle. If
>> we don't assume anything about the objects referenced from args2, then a
>> reference in args2 may well be the only one to some object. In this
>> case, the old GC would sweep it.
>
> OK, but in most, if not all of these cases, the objects are referenced
> from the stack.  For example, in the above fragment, the args[] array
> is on the stack.  Right?

That args is a parameter

  call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,

So just from this I see only args itself on the stack, not args[0],
args[1] and so on. I would have to look at all callers to determine
that. Not good enough in my book.

>
>> Not using arg2 after Ffind_operation_coding_system above is not enough.
>> It would have to be not using args2 after the GC has run. Maybe that's
>> _in_ Ffind_operation_coding_system.
>
> OK, agreed.
>
>> Additionally, objects might not die but may move, assuming that
>> SAFE_NALLOCA does not create an ambiguous root. So, using SAFE_NALLOCA
>> makes another assumption in the MPS case: that something else prevents
>> the objects from moving. Another proof or check required with my GCPRO
>> hat on.
>
> What does it mean in detail "the object may move"?  A Lisp object is a
> tagged pointer.  Do you mean the pointer should no point to a
> different address, i.e. the value of a Lisp object as a number should
> change to still be valid?  

Exactly. Unless an ambiguous reference prevents the copying that can
happen.

> And if so, is MPS supposed to find all the copies of that value
> everywhere in order to update them? So if I have several variables
> which were all assigned a value of the same Lisp object, they all need
> to be updated when the object moves?

Yes. MPS does that with the help of our dflt_scan and its subroutines
where we call MPS_FIX2 and update the reference.

>> > Also, in some other message you said SAFE_NALLOCA is unsafe if
>> > _pointers_ to Lisp objects are placed in the memory SAFE_NALLOCA
>> > allocates off the heap.  In call_process I see that we only ever put
>> > Lisp objects into the memory allocated by SAFE_NALLOCA.  If that is
>> > unsafe, could you tell what MPS does during GC which makes this
>> > unsafe?
>> 
>> Not sure, is the question why in MPS both pointers and Lisp_Object count
>> as "references"?
>
> Yes, if that's the situation.  Earlier you only mentioned pointers to
> Lisp objects, something that happens relatively rarely.

That's the case in MPS. Fixnums aside, Lisp_Object is basically also
only a pointer, with some tag bits added. In that sense it's the same
case.

And every string contains a pointer to it's data, which I consider part
of the Lisp data. And intervals are also Lisp data. The ones from enum
igc_obj_type.