Skip to content

runtime/jit: add user frame support for JIT compilers and VMs - #81237

Open
carli2 wants to merge 12 commits into
golang:masterfrom
launix-de:jit-foreign-frames-master
Open

runtime/jit: add user frame support for JIT compilers and VMs#81237
carli2 wants to merge 12 commits into
golang:masterfrom
launix-de:jit-foreign-frames-master

Conversation

@carli2

@carli2 carli2 commented Aug 31, 2026

Copy link
Copy Markdown

This implements proposal #78189 on the current master branch.

It adds an experimental runtime/jit API for cooperative dynamically
generated code. JIT compilers and VMs can register executable regions with
declarative unwind metadata, provide precise stack maps, preserve Go pointers
and caller frame pointers across stack growth, support panic and recover
across registered frames, participate in tracebacks, observe cooperative
preemption requests, and obtain the metadata needed to emit Go-compatible
split-stack checks. Consecutive generated frames are unwound, scanned, and
relocated as one chain.

The API also supports prepared, precisely typed allocations for objects with
repeated tails. MemCP uses this for variable-sized JIT closure environments.
It is included because raw byte allocations cannot describe their pointers to
the garbage collector. Reviewer feedback is welcome on whether this part
should remain here or move to a separate proposal and change.

The complete feature is gated behind GOEXPERIMENT=jit. The stack walker and
garbage collector consume copied declarative metadata and do not invoke
JIT-owned callbacks.

MemCP uses this implementation to JIT-compile Scheme and query-planner code.
A self-recursion microbenchmark improves by 30 to 33 times. Its complete
Scheme and SQL regression workload improved from approximately 11 to 13
minutes to 8 minutes 31 seconds when the integration was introduced. These
are consumer measurements, not Go project benchmarks.

The change covers registered return PCs, nested generated frames, precise GC
scanning, stack relocation, panic/recover, tracebacks, and forced stack
growth. Recoverable synchronous hardware faults whose interrupted PC itself
lies in generated code are not yet specified or tested; proposal discussion
should decide whether that belongs here or in a follow-up.

The implementation was rebased onto current master and built using the Go
1.27 JIT fork as bootstrap. On linux/amd64,
GOEXPERIMENT=jit go test runtime/jit, GOEXPERIMENT=jit go test runtime, and
GOEXPERIMENT=jit go test cmd/api pass. The default runtime test without the
experiment and the runtime/jit race test pass as well. The runtime/jit tests
cross-compile for every architecture covered by their Linux trampolines and
for 386, amd64, and arm64 on Windows.

The separate Go 1.27 branch in the organization fork remains a reproducible
downstream toolchain snapshot. This change intentionally targets master.

Updates #78189

@google-cla

google-cla Bot commented Aug 31, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@carli2
carli2 force-pushed the jit-foreign-frames-master branch from 7259e81 to fc9129b Compare September 2, 2026 08:53
@gopherbot

Copy link
Copy Markdown
Contributor

This PR (HEAD: fc9129b) has been imported to Gerrit for code review.

Please visit Gerrit at https://go-review.googlesource.com/c/go/+/826384.

Important tips:

  • Don't comment on this PR. All discussion takes place in Gerrit.
  • You need a Gmail or other Google account to log in to Gerrit.
  • To change your code in response to feedback:
    • Push a new commit to the branch used by your GitHub PR.
    • A new "patch set" will then appear in Gerrit.
    • Respond to each comment by marking as Done in Gerrit if implemented as suggested. You can alternatively write a reply.
    • Critical: you must click the blue Reply button near the top to publish your Gerrit responses.
    • Multiple commits in the PR will be squashed by GerritBot.
  • The title and description of the GitHub PR are used to construct the final commit message.
    • Edit these as needed via the GitHub web interface (not via Gerrit or git).
    • You should word wrap the PR description at ~76 characters unless you need longer lines (e.g., for tables or URLs).
  • See the Sending a change via GitHub and Reviews sections of the Contribution Guide as well as the FAQ for details.

@gopherbot

Copy link
Copy Markdown
Contributor

Message from Gopher Robot:

Patch Set 1:

(1 comment)


Please don’t reply on this GitHub thread. Visit golang.org/cl/826384.
After addressing review feedback, remember to publish your drafts!

@gopherbot

Copy link
Copy Markdown
Contributor

This PR (HEAD: ee6687e) has been imported to Gerrit for code review.

Please visit Gerrit at https://go-review.googlesource.com/c/go/+/826384.

Important tips:

  • Don't comment on this PR. All discussion takes place in Gerrit.
  • You need a Gmail or other Google account to log in to Gerrit.
  • To change your code in response to feedback:
    • Push a new commit to the branch used by your GitHub PR.
    • A new "patch set" will then appear in Gerrit.
    • Respond to each comment by marking as Done in Gerrit if implemented as suggested. You can alternatively write a reply.
    • Critical: you must click the blue Reply button near the top to publish your Gerrit responses.
    • Multiple commits in the PR will be squashed by GerritBot.
  • The title and description of the GitHub PR are used to construct the final commit message.
    • Edit these as needed via the GitHub web interface (not via Gerrit or git).
    • You should word wrap the PR description at ~76 characters unless you need longer lines (e.g., for tables or URLs).
  • See the Sending a change via GitHub and Reviews sections of the Contribution Guide as well as the FAQ for details.

@gopherbot

Copy link
Copy Markdown
Contributor

This PR (HEAD: 724544f) has been imported to Gerrit for code review.

Please visit Gerrit at https://go-review.googlesource.com/c/go/+/826384.

Important tips:

  • Don't comment on this PR. All discussion takes place in Gerrit.
  • You need a Gmail or other Google account to log in to Gerrit.
  • To change your code in response to feedback:
    • Push a new commit to the branch used by your GitHub PR.
    • A new "patch set" will then appear in Gerrit.
    • Respond to each comment by marking as Done in Gerrit if implemented as suggested. You can alternatively write a reply.
    • Critical: you must click the blue Reply button near the top to publish your Gerrit responses.
    • Multiple commits in the PR will be squashed by GerritBot.
  • The title and description of the GitHub PR are used to construct the final commit message.
    • Edit these as needed via the GitHub web interface (not via Gerrit or git).
    • You should word wrap the PR description at ~76 characters unless you need longer lines (e.g., for tables or URLs).
  • See the Sending a change via GitHub and Reviews sections of the Contribution Guide as well as the FAQ for details.

@gopherbot

Copy link
Copy Markdown
Contributor

This PR (HEAD: 946caf2) has been imported to Gerrit for code review.

Please visit Gerrit at https://go-review.googlesource.com/c/go/+/826384.

Important tips:

  • Don't comment on this PR. All discussion takes place in Gerrit.
  • You need a Gmail or other Google account to log in to Gerrit.
  • To change your code in response to feedback:
    • Push a new commit to the branch used by your GitHub PR.
    • A new "patch set" will then appear in Gerrit.
    • Respond to each comment by marking as Done in Gerrit if implemented as suggested. You can alternatively write a reply.
    • Critical: you must click the blue Reply button near the top to publish your Gerrit responses.
    • Multiple commits in the PR will be squashed by GerritBot.
  • The title and description of the GitHub PR are used to construct the final commit message.
    • Edit these as needed via the GitHub web interface (not via Gerrit or git).
    • You should word wrap the PR description at ~76 characters unless you need longer lines (e.g., for tables or URLs).
  • See the Sending a change via GitHub and Reviews sections of the Contribution Guide as well as the FAQ for details.

@gopherbot

Copy link
Copy Markdown
Contributor

Message from Carl-Philip Hänsch:

Patch Set 4:

(2 comments)


Please don’t reply on this GitHub thread. Visit golang.org/cl/826384.
After addressing review feedback, remember to publish your drafts!

@gopherbot

Copy link
Copy Markdown
Contributor

This PR (HEAD: c3e63e0) has been imported to Gerrit for code review.

Please visit Gerrit at https://go-review.googlesource.com/c/go/+/826384.

Important tips:

  • Don't comment on this PR. All discussion takes place in Gerrit.
  • You need a Gmail or other Google account to log in to Gerrit.
  • To change your code in response to feedback:
    • Push a new commit to the branch used by your GitHub PR.
    • A new "patch set" will then appear in Gerrit.
    • Respond to each comment by marking as Done in Gerrit if implemented as suggested. You can alternatively write a reply.
    • Critical: you must click the blue Reply button near the top to publish your Gerrit responses.
    • Multiple commits in the PR will be squashed by GerritBot.
  • The title and description of the GitHub PR are used to construct the final commit message.
    • Edit these as needed via the GitHub web interface (not via Gerrit or git).
    • You should word wrap the PR description at ~76 characters unless you need longer lines (e.g., for tables or URLs).
  • See the Sending a change via GitHub and Reviews sections of the Contribution Guide as well as the FAQ for details.

Add a new package runtime/jit that allows programs to register regions
of dynamically generated executable code with the Go runtime. This
enables the stack unwinder, panic/recover, and GC to handle frames
from JIT-compiled code, WASM engines, and embedded VMs gracefully
instead of crashing with "unknown pc".

The package provides:

  - Three unwind modes: UnwindStop (end traceback), UnwindSkip (skip
    user frames via Next callback), UnwindDeclare (skip + describe
    in tracebacks via Describe callback)
  - GC integration via ScanStack callback for marking Go pointers
    held in user code shadow stacks
  - Register/Unregister lifecycle with Handle type

Runtime internals:

  - Copy-on-write region registry with atomic pointer swap for
    lock-free reads from the unwinder (runs on system stack)
  - Unwinder patches in initAt() and next() to resolve user frame
    PCs via the Next callback before throwing on unknown PCs
  - traceback2() patch to call Describe for UnwindDeclare regions
  - markroot() fixed root to call ScanStack during GC mark phase

Gated behind GOEXPERIMENT=jit. Without the experiment, the runtime/jit
package is excluded from builds. The runtime-internal code has negligible
cost when no regions are registered (single atomic load returning nil).

Tests cover registration, concurrency, panic/recover through user frames,
runtime.Callers, runtime.Stack, GC, UnwindDeclare with Describe, and
ScanStack. ISA-specific JIT trampolines for all 13 Linux architectures.

Fixes golang#78189
Keep UnwindStop as a hard traceback boundary even when the region has an unwind recipe. Preserve trailing padding when a repeated tail has zero-sized elements.

Add coverage for the stack-check metadata and both boundary cases.

Updates golang#78189
@carli2
carli2 force-pushed the jit-foreign-frames-master branch from c3e63e0 to 1c0b2e3 Compare September 6, 2026 20:43
@gopherbot

Copy link
Copy Markdown
Contributor

This PR (HEAD: 1c0b2e3) has been imported to Gerrit for code review.

Please visit Gerrit at https://go-review.googlesource.com/c/go/+/826384.

Important tips:

  • Don't comment on this PR. All discussion takes place in Gerrit.
  • You need a Gmail or other Google account to log in to Gerrit.
  • To change your code in response to feedback:
    • Push a new commit to the branch used by your GitHub PR.
    • A new "patch set" will then appear in Gerrit.
    • Respond to each comment by marking as Done in Gerrit if implemented as suggested. You can alternatively write a reply.
    • Critical: you must click the blue Reply button near the top to publish your Gerrit responses.
    • Multiple commits in the PR will be squashed by GerritBot.
  • The title and description of the GitHub PR are used to construct the final commit message.
    • Edit these as needed via the GitHub web interface (not via Gerrit or git).
    • You should word wrap the PR description at ~76 characters unless you need longer lines (e.g., for tables or URLs).
  • See the Sending a change via GitHub and Reviews sections of the Contribution Guide as well as the FAQ for details.

@gopherbot

Copy link
Copy Markdown
Contributor

Message from Carl-Philip Hänsch:

Patch Set 6: Code-Review+1

(1 comment)


Please don’t reply on this GitHub thread. Visit golang.org/cl/826384.
After addressing review feedback, remember to publish your drafts!

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