Skip to content

False positive: jl_get_pgcstack_fallback reported as an AllocatingRuntimeCall on aarch64 #104

Description

@ChrisRackauckas-Claude

Summary

On aarch64 (Apple Silicon), check_allocs reports a spurious AllocatingRuntimeCall for allocation-free functions. The culprit is the never-allocates whitelist in src/classify.jl: it lists "get_pgcstack" and "get_pgcstack_static" but omits "get_pgcstack_fallback" — the variant aarch64 codegen emits to fetch the per-task GC stack pointer.

Root cause

In fn_may_allocate (src/classify.jl, ~L64-71):

function fn_may_allocate(name::AbstractString; ignore_throw::Bool)
    if name in ("egal__unboxed", ...,
                "gc_safepoint", "gc_collect", "genericmemory_owner", "get_pgcstack", "get_pgcstack_static") || occursin(r"^unbox_.*", name)
        return false # these functions never allocate
    ...

get_pgcstack_fallback is not in the tuple, so fn_may_allocate("get_pgcstack_fallback") returns true, and classify_runtime_fn("jl_get_pgcstack_fallback") therefore returns (:runtime, true). On aarch64, codegen emits a call to jl_get_pgcstack_fallback (rather than jl_get_pgcstack / jl_get_pgcstack_static) to obtain the per-task GC stack pointer, so genuinely allocation-free functions are flagged with a spurious AllocatingRuntimeCall.

MWE

julia> using AllocCheck

# BEFORE the fix (v0.2.5):
julia> AllocCheck.classify_runtime_fn("jl_get_pgcstack_fallback"; ignore_throw=true)
(:runtime, true)      # spurious: claims it may allocate

# the already-fixed sibling, for comparison:
julia> AllocCheck.classify_runtime_fn("jl_get_pgcstack_static"; ignore_throw=true)
(:runtime, false)

Actual: (:runtime, true)jl_get_pgcstack_fallback is treated as possibly-allocating.
Expected: (:runtime, false) — it never allocates, exactly like jl_get_pgcstack and jl_get_pgcstack_static.

After the fix:

julia> AllocCheck.classify_runtime_fn("jl_get_pgcstack_fallback"; ignore_throw=true)
(:runtime, false)

Fix

Add "get_pgcstack_fallback" to the never-allocates tuple in fn_may_allocate, right next to "get_pgcstack_static":

                "gc_safepoint", "gc_collect", "genericmemory_owner", "get_pgcstack", "get_pgcstack_static",
                "get_pgcstack_fallback") || occursin(r"^unbox_.*", name)

Precedent

This is the same class of fix as e44be86 ("fix: add get_pgcstack_static to non-allocating allowlist"), which added the _static variant for the same reason. get_pgcstack_fallback is simply a third pgcstack-fetch variant that the whitelist missed.

Downstream report

SciML/FastAlmostBandedMatrices.jl#68 — that package's zero-allocation tests fail only on macOS/aarch64, traced to this false positive.

PR with the one-line fix to follow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions