How the GC distinguishes code from data

Steven Schveighoffer schveiguy at yahoo.com
Fri Jan 7 13:47:48 PST 2011


On Fri, 07 Jan 2011 16:39:20 -0500, %u <wfunction at hotmail.com> wrote:

>> None what so ever.
>
> Huh.. then what about what is said in this link?
> http://d.puremagic.com/issues/show_bug.cgi?id=5326#c1
>
> I was told that void[] could contain references, but that ubyte[] would  
> not, and
> that the GC would need to scan the former but not the latter. Is that  
> wrong?

First, you should understand that the GC does not know what data is in a  
memory block.  It has no idea that the block is a void[] or a ubyte[] or a  
class instance or whatever it is.  All it knows is that it's data.  What  
makes it scan a block is a bit set on the block indicating that it  
contains pointers.  This bit is set by the higher-level runtime routines  
(like the ones that create an array) which use the TypeInfo to determine  
whether to set the NO_SCAN bit or not.

Second, memory that is not part of D's allocation is *not* scanned or  
marked, no matter where it is.  Essentially the mark routine goes like  
this (pseudocode):

foreach(root; roots)
   if(root.hasPointers)  // notice this has nothing to do with type
      foreach(pointer; root)
         if(pointer.pointsAt.GCHeapBlock)
            pointer.heapBlock.mark = true;

while(changesWereMade)
    foreach(heapBlock; heap)
       if(heapBlock.hasPointers)
          foreach(pointer; heapBlock)
             if(pointer.pointsAt.GCHeapBlock)
             {
                pointer.heapBlock.mark = true;
                changesWereMade = true;
             }

// free memory
foreach(heapBlock; heap)
    if(!heapBlock.mark)
       free(heapBlock)

So essentially, you can see if you allocated memory for example with  
malloc, and you didn't add it as a root, it's neither scanned nor marked.   
It does not participate whatsoever with the collection cycle, no matter  
what the type of the data is.

Now, you should also realize that just because an array is a void[]  
doesn't necessarily make it marked as containing pointers.  It is quite  
possible to implicitly cast a ubyte[] to a void[], and this does not  
change the NO_SCAN bit in the memory block.  Data *allocated* as a void[]  
(which I highly recommend *not* doing) will be conservatively marked as  
containing pointers.  This is probably where you get the notion that  
void[] contains pointers.

-Steve


More information about the Digitalmars-d-learn mailing list