Subject: bug#17168: 24.3.50; Segfault at mark_object

From: Daniel Colascione <[email-masked]>
Date: Sun, 06 Apr 2014 13:13:39 -0700

On 04/06/2014 12:58 PM, Stefan Monnier wrote:
>> The pinned bit approach is exactly what I implemented, except that we
>> walk obarray, like we already do, instead of all symbols.
> 
> We already walk obarray during the mark phase, so I don't understand
> what you mean here.

I meant that, IIUC, you mean to "pin" symbols by adding a pinned bit to
Lisp_Symbol, then at sweep time, enumerating all symbols in all symbol
blocks and marking those with this bit set. My approach is similar,
except that instead of an explicit mark pass over the symbols, my patch
just relies on obarray to keep these symbols alive, then forbids
removing these symbols from obarray. This way, the existing walk over
obarray does the job of the all-symbols walk we'd need otherwise.

>> Your approach would require that we check for non-symbols in purecopy
>> and reject them,
> 
> Yes.

Well, we already do that for markers. Still, I don't like making general
mechanisms less general.

>> and it'd have a bigger performance impact, since we'd
>> then need to walk the entire symbol list essentially twice.
> 
> Indeed.  I don't expect it to be significant, tho.  As you point out we
> already walk that list once during gc_sweep, so doing it one more time
> should be very quick.  

Maybe. We might have tens of thousands of symbols. We don't GC that
often, sure, but the overhead isn't nothing.

On the other hand, if we're walking all symbols during marking, we can
avoid walking the initial obarray, since we already know which symbols
are interned there from the Lisp_Symbol interned field. (We can't use
the same approach for other obarrays because we want them to eventually
get GCed even if they have interned symbols.)

This approach still gives up generality and doesn't do much about the
complexity, but it does save us 350 words of pure storage.

> Also, I'd expect that a significant proportion of
> all symbols would be marked with that bit, so scanning all symbols won't
> take that much longer than the alternative of only scanning a vector of
> pinned symbols.  Also scanning all symbols like gc_sweep means that the
> scan is nicely sequential in memory.
> 
>> I'd strongly prefer the fully general approach in my patch. It isn't
>> *that* complicated.
> 
> But it requires more memory,

~350 machine words, all in pure storage.

> whereas we already have space for an extra
> bit in the Lisp_Symbol struct.  I guess the main difference resides in
> whether we want to allow uninterning pinned symbols.  If we do as you
> suggest and disallow it, then indeed, I expect there to be rather few
> uninterned pinned symbols so using a small auxiliary array makes sense.
> But I'd rather we don't pay attention to a symbol's interned status, so
> we can later unintern them.

Sure. But why would you ever want to unintern a symbol that pure storage
references?