You understand well, here some more comments:
Do you mean that for all symbols that evaluate/resolve to a usable function? Or just the builtin functions and imported C functions?
Yes, just builtin functions and imported C functions - and faked imports.
My experiments appear to show that for a symbol cell, the contents is a SYMBOL struct pointer. Inside this struct is a field containing a char * name field. This pointer appears to be copied to the aux field of the function cell that is stored within the symbol cell. Is this what you were getting at?
Yes, a symbol struct is pointed too by a symbol type lisp cell. The stuff assigned to the symbol is pointed to by the contents field of the symbols struct.
(println ((dump print) 3))
(println ((unpack {lu lu Lu} (address 'print)) 2))
Yes and:
Code: Select all
(get-string ((dump print) 3)) => "print”
So when this symbol is deleted, the memory allocated for the name gets reused for something else. And the function cell the symbol contained gets deleted as well? Otherwise the aux field would become a dangling pointer.
Yes, the function cell gets deleted as well.
It sounds like the memory containing the function is not reclaimed here.
Yes, the memory containing the code is not reclaimed. In the
fake import of the manual example, that memory would be held by foo-code and not be reclaimed until foo-code is reassigned or deleted.
Eh? How does this protect the contents of a symbol from deletion? You can change the contents of a constant symbol by another call to the constant function. If you did that, the original contents of the symbol may be left without any references.
Yes, using
constant for the holding symbol assignment is just a weak protection, but could be overwritten by an other
constant assignment.
For that matter, it sounds like the constant symbol can be deleted during runtime. It doesn't seem to work that way if you call the delete function.
The
delete function will
not work on protected symbols and return nil, but yes you can delete the contents - code memory - by re-assigning to foo-code using
constant.
If the symbol 'foo-code' loses the reference to this memory, it will be reclaimed if it was the last reference?
Yes and note that memory allocated by newLISP is always referenced only once in newLISP. When you normally
import a C-function from a library, that code memory sits somewhere in the library and is not controlled by newLISP.
As a result, the pointer to this memory would effectively become a dangling pointer? Thus, any function cell using it would become unusable?
Yes.
What happens then if I allocated this memory outside of newLISP? This is the case when using libtcc. The library or the programmer manages the memory used for storing the binary code compiled from the C function definition. I would assume that newLISP will not try to free it, as it was allocated outside of the scope of newLISP.
Yes and yes to all the rest too.
One last comment to reclaiming memory in newLISP. Only the following gets reclaimed (see void deleteList() in newlisp.c):
- lisp cell memory
- string memory pointed to by cell->contents in string type cells
- bigint memory pointed to by cell->contents in bigint type cells
- lists of cell memory pointed to by cell->contents in a list/expression type cell
- arrays of cell memory pointed to by cell->contents in a array type cell
- symbol memory of SYMBOL structs
- string memory pointed by symbol->name in SYMBOL structs
Each lisp cell is only referenced
once in the system but the same symbol struct may be referenced with its address by numerous symbol type cells. This is why deleting a symbol in newLISP requires a complete cell-memory walk. All references to the symbol are replaced with
nil or the symbol does not get deleted when references exist depending on the
delete flag used.