[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Conservative GC isn't safe

From: Ken Raeburn
Subject: Re: Conservative GC isn't safe
Date: Mon, 28 Nov 2016 04:36:56 -0500

On Nov 27, 2016, at 11:15, Paul Eggert <address@hidden> wrote:
> Ken Raeburn wrote:
>>> > Indeed.  Hans Boehm's done a fair bit of research in this issue,
>>> > including discussing the underlying assumptions and arguing that
>>> > compilers should (and usually do) guarantee those assumptions.
>> I’d be surprised if that held reliably when the last use of a Lisp_Object in 
>> some function extracts an object pointer and then never references the 
>> Lisp_Object as such ever again.
> That's not a problem for Emacs, since the Emacs GC marks the object either 
> way.

Ah, sorry, I misunderstood the case Daniel was describing.  Yes, the case I was 
thinking of is in fact handled; stack slots holding either Lisp_Object values 
or pointers to the start of the Lisp data structures will be fine.

But we do use interior pointers sometimes; looking at Fsubstring’s handling of 
a vector object:

    res = Fvector (ito - ifrom, aref_addr (string, ifrom));

  return res;

… here we pass Fvector a pointer to somewhere within the “contents” array of 
the vector passed as argument “string”; it’s neither the Lisp_Object value, nor 
the start of the allocated structure.  Now, I don’t think this is a case that 
can trigger GC at the critical time.  But clearly we’ve got at least one case 
where we keep an interior pointer and — locally, at least; the caller could be 
another matter — don’t keep a live handle on the object itself.

And the compiler can do it too.  For example, if we did something like this:

  DEFUN (“frob-array-elts", Ffrob_array_elts, Sfrob_array_elts, 1, 1, 0,
         doc: /* Blah */ )
    (Lisp_Object obj)
    int i;
    for (i = 0; i < 30; i += 3)
        frob (AREF (obj, i));
    return Qnil;

I tried compiling this (“gcc version 4.9.2 (Debian 4.9.2-10)” on x86-64).  The 
generated code computes obj+3 (vector tag is 5, contents array starts at offset 
8) and obj+0xf3 (end of the iteration), and overwrites the register containing 
the original “obj” value with the argument to be passed to “frob”.

If, in this case, “frob” were something that could trigger GC, then stack 
scanning would not see “obj”, at least not in this stack frame.  And if the 
caller is doing something like:

  Ffrob_array_elts (get_vector_of_stuff ());

then the caller needn’t retain any other references to “obj” either.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]