• Re: How to deal with temporary pointer in the precise garbage collection

    From George Neuner@gneuner2@comcast.net to comp.compilers on Sat Jul 29 20:08:56 2023
    From Newsgroup: comp.compilers

    On Mon, 24 Jul 2023 18:45:52 -0700, xiao mei <mxmxlwlw@gmail.com>
    wrote:

    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
    --- Synchronet 3.21b-Linux NewsLink 1.2