Skip to content

Filter AllocCheck jl_get_pgcstack_fallback false positive on aarch64#68

Draft
ChrisRackauckas-Claude wants to merge 1 commit into
SciML:mainfrom
ChrisRackauckas-Claude:fix-alloccheck-pgcstack-fallback-aarch64
Draft

Filter AllocCheck jl_get_pgcstack_fallback false positive on aarch64#68
ChrisRackauckas-Claude wants to merge 1 commit into
SciML:mainfrom
ChrisRackauckas-Claude:fix-alloccheck-pgcstack-fallback-aarch64

Conversation

@ChrisRackauckas-Claude

Copy link
Copy Markdown
Contributor

The julia pre / macos-latest (aarch64 / Apple Silicon) CI job fails the zero-allocation tests in test/alloc_tests.jl on Julia 1.13.0-rc1, while every other platform (x86_64 ubuntu/windows, all other Julia versions) passes.

Root cause

On aarch64 the per-task GC stack pointer is fetched through jl_get_pgcstack_fallback rather than a TLS/register fast path. AllocCheck already treats the fast-path variants jl_get_pgcstack and jl_get_pgcstack_static as non-allocating (see classify.jl fn_may_allocate), but its whitelist omits the _fallback variant. As a result check_allocs conservatively reports it as an AllocatingRuntimeCall, producing a false positive. The call does not actually allocate; this is purely an artifact of AllocCheck's incomplete whitelist (still present in the latest AllocCheck 0.2.5).

This is why the CI log shows, only on macos aarch64:

Allocating runtime call to "jl_get_pgcstack_fallback" in unknown location

Fix

Add a small real_allocs helper that strips only the jl_get_pgcstack_fallback AllocatingRuntimeCall from the check_allocs results before asserting emptiness. Every other result (a real AllocationSite, a DynamicDispatch, or any other allocating runtime call) still fails the test, so the zero-allocation invariant is fully preserved -- no test is weakened, skipped, or broadened. This only removes one documented tool false positive.

Verification (local)

  • Ran test/alloc_tests.jl on Julia 1.13.0-rc1 (x86_64 linux): 11/11 pass (matches the green CI jobs), confirming the change does not regress the passing path.
  • Unit-tested the real_allocs filter against synthetic AllocCheck results:
    • [jl_get_pgcstack_fallback] -> empty (the exact aarch64 case becomes green).
    • [jl_get_pgcstack_fallback, AllocationSite] -> still non-empty (real allocation still caught).
    • [jl_get_pgcstack_fallback, other AllocatingRuntimeCall] -> still non-empty (other runtime allocs still caught).

The proper long-term fix is upstream in AllocCheck (add get_pgcstack_fallback to the non-allocating whitelist in classify.jl); this PR makes the test robust in the meantime.

Please ignore until reviewed by @ChrisRackauckas.

…rch64

On aarch64 (Apple Silicon, e.g. macos-latest) Julia 1.13 fetches the per-task
GC stack pointer via jl_get_pgcstack_fallback instead of a TLS/register fast
path. AllocCheck's whitelist (classify.jl) already treats the fast-path variants
jl_get_pgcstack and jl_get_pgcstack_static as non-allocating, but omits the
_fallback variant, so check_allocs conservatively reports it as an
AllocatingRuntimeCall. This is a false positive: that call does not allocate.

This caused the zero-allocation tests to fail only on the julia-pre / macos-latest
(aarch64) CI job while passing on x86_64. Filter out only the
jl_get_pgcstack_fallback AllocatingRuntimeCall before asserting emptiness; every
other result (real AllocationSite, DynamicDispatch, or other allocating runtime
call) still fails the test, so the zero-allocation invariant is fully preserved.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants