Discussion:
How to deal with temporary pointer in the precise garbage collection
(too old to reply)
xiao mei
2023-07-25 01:45:52 UTC
Permalink
A register may contain value of a pointer. When calling a function, that
value is saved automatically, so there's more pointer values in the
stack apart from params and locals. How to deal with that in a precise
garbage collection using stack map?
George Neuner
2023-07-30 00:08:56 UTC
Permalink
Post by xiao mei
A register may contain value of a pointer. When calling a function, that
value is saved automatically, so there's more pointer values in the
stack apart from params and locals. How to deal with that in a precise
garbage collection using stack map?
In most GC systems, the only way to trigger a collection is to call a
function - to allocate memory, or to directly invoke the collection.
So although you *don't* know that a collection will happen, you *do*
know when it *might* happen ... in a function call.

In threaded systems, typically mutator threads collect their own
private spaces unsynchronized, and dedicated threads collect shared
spaces, synchronizing with the mutators when necessary.



The simplest way to handle temporaries is to allocate (hidden) local
variables in the frame and save all the registers to their respective
variables prior to making a function call.

Since the compiler knows the layout of the frame, it can create at
compile time a static map or enumeration function enabling the GC to
find pointers in the frame and bind that directly into the executable.
A pointer to the map or function then can be saved at a known offset
in the frame for the GC to use (typically adjacent to the frame's own
set of saved registers).

[An alternate (more complex) method is to have the GC look at the
return address in the frame, examine the (code) call site and get the
address of the function, and use the function's address to look up the
map of its frame. But this can be difficult or impossible if the CPU
supports indirect calling through a register.]



If you don't want to allocate extra space for saving temporaries in
the function's own frame, then you can't [easily] use a static map for
them. Instead the compiler has to keep track of which registers
contain pointers, and generate code to create a bitmap showing which
saved registers in the *callee* frame contain caller frame pointers,
and save that bitmap into the callee's frame as well. This can be
simplified somewhat if the register set can be partitioned such that
only certain registers are used to hold pointers [easy with general
registers, not so easy with, e.g., x86 where certain registers have
dedicated functions].



Recall that a static map or enumeration function will be needed anyway
for the frames of complex functions that can't keep everything in
registers, so some compilers just generate a frame map for every
function.

It's hard to predict whether saving temporaries deliberately or
creating a runtime map of saved values will be more performant. It
depends on how many pointers, caller-save vs callee-save, etc.

13 of one, baker's dozen of the other.

Hope this helps.
George

Loading...