How the Nasal GC works: Difference between revisions

Jump to navigation Jump to search
m
Line 234: Line 234:
</syntaxhighlight>
</syntaxhighlight>


== The pool manager ==
All high level type allocators (naNewString, naNewVector, naNewHash etc) make use of the naNew() call introduced earlier.
naNew() doesn't directly allocate new memory from the heap, but instead use the naGC_get() helper which manages memory from the global pools.
The interesting part is the naGC_get() function which isn't directly mapped to naAlloc() or malloc(), but instead manages the Nasal memory pools.
For each native Nasal data type (scalars, vectors, hashes, funcs etc) , there are separate memory pools in globals->pools[n]. The index (n) is one of T_VEC, T_HASH, T_FUNC etc.
The naGC_get() pool "manager" is located in gc.nas line 194: https://gitorious.org/fg/simgear/blobs/next/simgear/nasal/gc.c#line194
<syntaxhighlight lang="C">
struct naObj** naGC_get(struct naPool* p, int n, int* nout)
{
    struct naObj** result;
    naCheckBottleneck();
    LOCK();
    while(globals->allocCount < 0 || (p->nfree == 0 && p->freetop >= p->freesz)) {
        globals->needGC = 1;
        bottleneck();
    }
    if(p->nfree == 0)
        newBlock(p, poolsize(p)/8);
    n = p->nfree < n ? p->nfree : n;
    *nout = n;
    p->nfree -= n;
    globals->allocCount -= n;
    result = (struct naObj**)(p->free + p->nfree);
    UNLOCK();
    return result;
}
</syntaxhighlight>
As can be seen, the garbage collector itself is triggered by setting the global "needGC" flag to 1 in the globals structure and then calling the bottleneck() function: [https://gitorious.org/fg/simgear/blobs/next/simgear/nasal/gc.c#line199].
In line 209, the memory region from the global pool is cast back to a pointer (struct naObj**): https://gitorious.org/fg/simgear/blobs/next/simgear/nasal/gc.c#line209
the "nout" paramter is just there to update c->nfree[type] with the amount of free memory.


= The GC interface =
= The GC interface =

Navigation menu