I've got a memory pool type called mfile. A postscript execution
context contains pointers to a global mfile and a local mfile. Since
the stacks (operand, execution,, dictionary) are part of the "local"
state I decided to put them into the local mfile.
Then as part of the garbage collector, each mfile has a range of
special entities at the beginning of it's internal memory table (mtab)
which contain the addresses of the stacks for use as the "root set" of
the collector.
But when I allocate systemdict in global vm and push the systemdict
object on the dictstack, it's getting garbage-collected before it's
even built because collecting global vm doesn't have access to local
vm, so it can't find the stacks!
Would it be a terrible idea to put the stacks in a third mfile? The
collector would need to check an external root set; but it would need
to do that anyway if the stacks stay in local vm!
I suppose I should look ahead to my Display Postscript books to see
how contexts get inherited by 'fork'. That should give some guidance
on how they need to be structured.
Any thoughts appreciated! Even wild speculation and unbridled rants.
--
Josh "luser-droog" Ryan
I'm having difficultly organizing the execution context for my Display
Postscript clone (whip out your 2ed's!).
Section 7.1.1 of PLRM2 describes three configurations:
1. Local and global VM are completely private to the context.
(job-server mode)
2. Local VM is private to the context, but global VM is shared with
some other context.
(shared space is accessed through globaldict)
3. Local and global VM are shared with some other context.
And Programming the Display Postscript System with X, Client-
Library-17 says:
A context is created in a space. The space is either shared with a
previously created context or is created when a new context is
created. Multiple contexts in the same space share all data. Contexts
in different spaces can operate more or less independently and still
share data by using shared VM.
This "shared VM" is presumably the globaldict method from option 2,
above.
All of this seems to suggest that it is appropriate to put the stacks
in local VM. But the issue of garbage collection appears to complicate
things. It seems like a really circular mess.
Consider, to garbage collect a local VM space with multiple contexts
in it, the mark phase will have to run through all the dicts and
arrays in all the stacks. To collect global VM, one must do this for
all associated local VMs.
So context needs a link to global and local.
global needs a list of all contexts that link to it.
local needs a list of all contexts it contains.
I'd like to avoid specialized behavior for the two kinds of space, but
I'm having trouble imagining a nice data abstraction.
From the postscript level, garbage collection is controlled by
vmreclaim:
int vmreclaim -
controls the garbage collection machinery as specified by int:
-2 Disable automatic collection in both local and global VM
[I suppose this would solve my immediate crisis of systemdict getting
collected before it's built.]
-1 Disable automatic collection in local VM.
[This still leaves the more expensive global collections enabled.]
0 Enable automatic collection.
1 Perform immediate collection in local VM.
2 Perform immediate collection in local and global VM: This can
take a long time, because it must consult the local VMs of all
execution contexts.
I've got automatic mode running the collector periodically: every 10
times the allocator fails to find space on the free list and falls
back to expanding the memory, it triggers and collection and restarts
the countdown. This has forced me to tackle the issue early!
Any comments or anecdotes would be greatly appreciated.