I've added a new ability to series, that they can free their data allocation even if references to them still exist:
>> foo: collect [loop 1000 [keep <x>]] >> bar: foo >> bar/100 == <x> >> free foo >> bar/100 ** Error: Series data has been freed
A small amount of memory (a series node) still hangs around. That's 8 pointers in size, and won't go away until all the references are gone. But the arbitrarily-large data allocation is freed up. If you have a BINARY! blob that was a megabyte in size, you will only have 32 bytes remaining once you FREE it (or 64 bytes on 64-bit platforms).
The flag controlling this... SERIES_INFO_INACCESSIBLE... already existed. It marked when a FRAME! for a function was no longer on the stack, so the data was gone. But it has been promoted to a general feature of any series. This means referencing data is a little slower because it has to check for the flag...however, I think that it is worth it.
I needed this right now for something specific--that is not going to actually be relevant in the future. But I think exposing it as a general purpose feature is useful. It can help work around bugs in people's code where they meant to tidy up all lingering references to large data blobs but missed some (maybe even in some debug logging that isn't critical)...so that not finding and clearing all those references doesn't imply indefinite memory usage. It also might be a way to reclaim memory faster than a GC can... so even if the garbage collector would wind up getting the memory anyway, you can do more allocations before waiting for it.