Skip to content

Using fp registers to store GC-managed pointers in AArch64 fibers makes GC collect mid-switch #23576

Description

@ljmf00-wekaio

This was an issue caught at Weka, as part of our added support for AArch64. The issue require specific conditions to trigger, briefly code that uses the affected registers and yields + gc collect in between switching back.


On ARM we have flags to enable aarch64 neoverse CPU extension flags that enables codegen with loop vectorization passes. As a consequence of supporting neoverse, any compiler is free to use v8 to v15 registers that are 128-bit that overlaps the d8 to d15 64-bit registers. Even for normal operations those specific floating-point registers could be used to store pointers, nothing prevents us from doing so, although, its more likely that those v8 to v15 registers vectorize code that split them into two a lower and higher part.

The ABI spec tells the lower 64-bit part of those v8 to v15, that coincides with d8 to d15, need to be saved, although druntime fibers switch code seem to intentionally and wrongly skip it from GC scans because they assume a user won't do that, where they are only used for floating-points, which is a blind assumption. Again, nothing prevents the user to inline assembly such code or actually, the compiler to lower code to use these 64-bit registers or the lower part (on vectorization code) to store actual pointers.

Because of all this, GC scans skip pointers stored in the affected registers, and, on collection, invalidate those pointers that are only referenced in them. If in between a call that uses these registers, a switch out of the context occurs plus a collection before switch back in, then, after switching back, the pointers that got saved by the switch code inside registers but not pointed by fibers stack gets wrongly collected by GC, since it doesn’t know of such pointer being live.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions