> > So you're saying that the calls to get memory during interpreter > > initialization are somehow guaranteed to not require more memory (and thus > > a dod or collection run)? Currently, this guarantee is not expressed in > > I don't understand the "thus." Nothing states that requesting memory > mandates a DOD/GC run.
If I call Parrot_allocate, it checks to see if it has enough allocated memory to provide the request. If not, it performs a collection run, and tries again. If not, it tries allocationg a new block of memory, and returns that. If that fails, it gives up. So if our initial allocation size for some reason isn't enough for all of the parrot initializations, it will cause a collection run. This in turn depends that the various *_pools were correctly initialized. If this is not the case (say, we're allocating memory for the pools in the first place), bad things happen. Likewise, the construction of a new PMC for the stash_hash could cause a DOD to occur if there aren't enough PMC headers available. Granted one won't cause this, or even a few. But the possibility exists, if say the stash_hash PMC initializes a bunch of default PMCs for its use, or somesuch. > > code, comments, or documentation, from what I can tell. And I personally > > hate implicit assumptions like these...they're the cause of all that magic > > voodo, far away from where it's obvious what the problem is. We have no > > idea of knowing how much is 'enough' for the GC to allocate at startup, > > aside from the following the code and tracking allocations, which can be > > a pain. > > I guess it depends on what you consider to be initialization. Little, if > any, of what the interpreter itself demands in memory - including memory for > the GC itself - is going to be reclaimable; it's all mostly persistent > throughout the life of the interpreter. Right. However, that's not to say that memory cannot grow. The interpreter allocates the various *_pools from the interpreter's memory_pool, and it gets copied with each collection run. This memory can grow and change in size as more memory for pools are needed. Currently, we use the GC's buffer system for tha. Alternately, we could use mem_sys_allocate, and manually free and allocate memory for them. The latter would then allow these pools to not be copied during collection runs, and would eliminate that particular element of unsafety. > If there's not enough memory to bootstrap the interpreter and the GC, then > even if the GC *could* reclaim enough to satisfy subsequent requests, > there's not going to be nearly enough memory left to do anything. So why > bother? Because if there's not enough memory, it can still allocate *more* memory. It just tries to reclaim enough memory before resorting to the 'extreme' of getting more system memory. I hope that makes things clear. > (Just) enough of the interpreter needs to start up to start up the memory > allocator and the GC subsystem. If it needs more memory to do so, it should > simply be given more memory. After the GC is up and running, the > interpreter/bootstrapping process can trigger a GC run to free up as much > memory as it can. The remainder of the interpreter can then start up, > running through the GC. You're, right, it should be given more memory to do so. But since it performs a collection run before getting more memory, and since it's not safe to perform a collection run during initialization, bad things happen. Mike Lambert