GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — gh-149800: Generate the perf trampoline .eh_frame from the compiled assembly by stratakis · Pull Request #157246 · python/cpython

Conversation

@stratakis

@stratakis stratakis commented Sep 10, 2026 •
edited by bedevere-app Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

The trampoline's unwind information has been a hand-maintained DWARF block per architecture in Python/jit_unwind.c.

Now all of this can be changed :)

The perf trampoline's unwind information is now produced by the assembler from .cfi directives in the trampoline assembly and extracted into a header at build time, so no architecture needs hand-written DWARF anymore.

Building the perf trampoline now needs a host Python (PYTHON_FOR_REGEN, 3.7 or newer. Wanted 3.9 for the stock Mac interpreter but 3.7 was compatible so why not). Without one, configure disables the trampoline.

Tested on Linux x86_64 (gcc, clang, CET, JIT, tail-call interpreter, free-threaded, LTO, PGO, BOLT, shared, debug, no frame pointers, out-of-tree)

Linux aarch64 (default, PAC, shared, debug, no frame pointers)

macOS arm64 (native, framework, universal2 on both slices), end to end with perf (fp and DWARF call graphs) and samply.

Plus the test suite ofc which was passing for me (let's see what the CI says though).

This can also be backported into 3.15 together with #149894 and #150364 if needed.

Fixes: #149800

THe PR and testing has been assisted by various frontier models, mainly by Fable 5.1 but also each each iteration reviewed in addition by the gpt 6 astra model.

Making it a draft for now, I believe it's ready but I'd also like to test an rpm build first, plus adding another architecture such as s390x or ppc64le to verify things work as intended.

  • Issue: Refactor perf trampoline proposal: split the assembly per architecture, auto-generate DWARF unwind data #149800

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@stratakis
stratakis requested review from AA-Turner, brandtbucher, corona10, diegorusso, emmatyping, erlend-aasland, itamaro and savannahostrowski as code owners September 10, 2026 01:45
@python-cla-bot

python-cla-bot Bot commented Sep 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot mentioned this pull request Sep 10, 2026
Refactor perf trampoline proposal: split the assembly per architecture, auto-generate DWARF unwind data #149800
Open
@bedevere-app bedevere-app Bot added the awaiting review label Sep 10, 2026
@stratakis
stratakis marked this pull request as draft September 10, 2026 01:45
@bedevere-app bedevere-app Bot removed the awaiting review label Sep 10, 2026
@read-the-docs-community

read-the-docs-community Bot commented Sep 10, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #34551618 | 📁 Comparing 1010690 against main (69a6612)

  🔍 Preview build  

57 files changed · + 8 added · ± 48 modified · - 1 deleted

+ Added

  • builtins/constants.html
  • builtins/exceptions.html
  • builtins/functions.html
  • builtins/index.html
  • builtins/stdtypes.html
  • builtins/threadsafety.html
  • builtins/time-complexity.html
  • library/tkinter.dialogs.html

± Modified

  • glossary.html
  • index.html
  • c-api/bytes.html
  • c-api/complex.html
  • c-api/typeobj.html
  • extending/index.html
  • faq/general.html
  • howto/functional.html
  • howto/perf_profiling.html
  • library/bz2.html
  • and 38 more...

- Deleted

  • library/dialog.html
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@stratakis stratakis mentioned this pull request Sep 10, 2026
perf_jit activated from a subinterpreter publishes JIT executors with the trampoline's unwind info #157247
Closed
@stratakis
stratakis marked this pull request as ready for review September 10, 2026 22:48
@bedevere-app bedevere-app Bot added the awaiting review label Sep 10, 2026
@stratakis

stratakis commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

Undrafting, this should be ready. The failed CI jobs must be flakiness as they passed on the previous commit, the last one just skips a specific test on BOLT builds.

Did some extra verification here:

A Fedora Rawhide RPM build of python3.15 with this on top of the split and the macOS fix (so basically a 3.15 backport), which contains the multitude of Fedora compiler flags.

Tested on aarch64 and x86_64 the main, debug, free-threading and free-threading-debug interpreters . On all eight the trampoline is enabled, the jitdumps written by -X perf_jit have correctly patched FDEs, test_perf_profiler and test_perfmaps pass, and perf unwinds through every trampoline in both fp and DWARF mode.

Also I've tested with adding ppc64le support and deployed it on the ppc64le Rawhide buildbot (source build not RPM). Granted the non-fp path is not exercised on ppc64le but nontheless it works if I add this patch on top:

ppc64le patch

diff --git a/Makefile.pre.in b/Makefile.pre.in
index f9f9a5db5d4..07f494e38c5 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -3133,6 +3133,9 @@ Python/asm_trampoline_aarch64.o: $(srcdir)/Python/asm_trampoline_aarch64.S
 Python/asm_trampoline_riscv64.o: $(srcdir)/Python/asm_trampoline_riscv64.S
 	$(CC) -c $(PY_CORE_CFLAGS) -o $@ $<
 
+Python/asm_trampoline_ppc64le.o: $(srcdir)/Python/asm_trampoline_ppc64le.S
+	$(CC) -c $(PY_CORE_CFLAGS) -o $@ $<
+
 # On macOS universal2 builds, $(PY_CORE_CFLAGS) contains "-arch arm64 -arch x86_64",
 # which would produce fat .o files containing both architectures for each .S input.
 # lipo -create then refuses to combine them because they share architectures.
diff --git a/Python/asm_trampoline_ppc64le.S b/Python/asm_trampoline_ppc64le.S
new file mode 100644
index 00000000000..c85e6b59b31
--- /dev/null
+++ b/Python/asm_trampoline_ppc64le.S
@@ -0,0 +1,27 @@
+    .text
+#if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
+    .abiversion 2
+    .globl  _Py_trampoline_func_start
+_Py_trampoline_func_start:
+    .cfi_startproc
+    mflr    0
+    std     0, 16(1)
+    stdu    1, -32(1)
+    .cfi_def_cfa_offset 32
+    .cfi_offset 65, 16
+    mr      12, 6
+    mtctr   6
+    std     2, 24(1)
+    bctrl
+    ld      2, 24(1)
+    addi    1, 1, 32
+    .cfi_def_cfa_offset 0
+    ld      0, 16(1)
+    mtlr    0
+    .cfi_restore 65
+    blr
+    .cfi_endproc
+    .globl  _Py_trampoline_func_end
+_Py_trampoline_func_end:
+#endif
+    .section .note.GNU-stack,"",@progbits
diff --git a/Python/perf_jit_trampoline.c b/Python/perf_jit_trampoline.c
index 21beead742a..1709fda8681 100644
--- a/Python/perf_jit_trampoline.c
+++ b/Python/perf_jit_trampoline.c
@@ -124,6 +124,8 @@
 #    define EM_AARCH64  183
 #  elif defined(__riscv)
 #    define EM_RISCV    243
+#  elif defined(__powerpc64__)
+#    define EM_PPC64    21
 #  endif
 #endif
 
@@ -158,6 +160,8 @@ static uint64_t GetElfMachineArchitecture(void) {
     return EM_ARM;
 #elif defined(__riscv)
     return EM_RISCV;
+#elif defined(__powerpc64__)
+    return EM_PPC64;
 #else
     Py_UNREACHABLE();  // Unsupported architecture - should never reach here
     return 0;
diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c
index fa1cb785b41..620196ab81b 100644
--- a/Python/perf_trampoline.c
+++ b/Python/perf_trampoline.c
@@ -147,7 +147,8 @@ any DWARF information available for them).
 #include <sys/time.h>           // gettimeofday()
 
 
-#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) \
+    || defined(__powerpc64__)
 #define PY_HAVE_INVALIDATE_ICACHE
 
 #if defined(__clang__) || defined(__GNUC__)
diff --git a/Tools/jit/_trampoline_ehframe.py b/Tools/jit/_trampoline_ehframe.py
index a87488bde25..135dae1146f 100644
--- a/Tools/jit/_trampoline_ehframe.py
+++ b/Tools/jit/_trampoline_ehframe.py
@@ -24,6 +24,7 @@
 _SHT_NOBITS = 8
 _EM_X86_64 = 62
 _EM_AARCH64 = 183
+_EM_PPC64 = 21
 
 # Mach-O constants, see llvm/BinaryFormat/MachO.h.
 _MH_MAGIC_64 = 0xFEEDFACF
@@ -62,6 +63,7 @@
 _ELF_ARCH_MACROS = {
     _EM_X86_64: "__x86_64__",
     _EM_AARCH64: "__aarch64__",
+    _EM_PPC64: "__powerpc64__",
 }
 _MACHO_ARCH_MACROS = {
     _CPU_TYPE_X86_64: "__x86_64__",
diff --git a/configure b/configure
index 1ebf1f795b0..109f2e962c0 100755
--- a/configure
+++ b/configure
@@ -14636,6 +14636,9 @@ case $PLATFORM_TRIPLET in #(
   aarch64-linux-musl) :
     perf_trampoline=yes
                          PERF_TRAMPOLINE_OBJ=Python/asm_trampoline_aarch64.o ;; #(
+  powerpc64le-linux-gnu) :
+    perf_trampoline=yes
+                            PERF_TRAMPOLINE_OBJ=Python/asm_trampoline_ppc64le.o ;; #(
   darwin) :
     case $MACOSX_DEPLOYMENT_TARGET in #(
   10.[0-9]|10.1[0-1]) :
diff --git a/configure.ac b/configure.ac
index b44c7d931d3..d21a05565d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3922,6 +3922,8 @@ AS_CASE([$PLATFORM_TRIPLET],
                          PERF_TRAMPOLINE_OBJ=Python/asm_trampoline_aarch64.o],
   [aarch64-linux-musl], [perf_trampoline=yes
                          PERF_TRAMPOLINE_OBJ=Python/asm_trampoline_aarch64.o],
+  [powerpc64le-linux-gnu], [perf_trampoline=yes
+                            PERF_TRAMPOLINE_OBJ=Python/asm_trampoline_ppc64le.o],
   [darwin], [AS_CASE([$MACOSX_DEPLOYMENT_TARGET],
                 [[10.[0-9]|10.1[0-1]]], [perf_trampoline=no],
                 [perf_trampoline=yes

builds, tests pass, perf back-chain and DWARF mode both unwind through the trampolines.

Did also a s390x compilation (with the relevant code added similarly as the ppc64le one) on RHEL10 (no access to Fedora s390x for now), builds with and without -mbackchain, tests pass on both, DWARF mode unwinds through the trampolines on both. Frame pointer mode doesn't work due to a kernel bug there but overall I think this covers a wider area of testing that functionality.

So if that approach seems sound, it should be fairly easy to add s390x, ppc64le, RISC-V support.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@stratakis

stratakis commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

cc @diegorusso @pablogsal

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@diegorusso

diegorusso commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Thanks for the change, this is great. Two point of discussions, although very low priority:

  • I was exploring the idea to use the _bootstrap_python instead of requiring an existent python installation in order to run _trampoline_ehframe.py‎ but I'm not sure if it works. This could be an improvement of the current implementation
  • when building the unwinding information for the JIT shim, the build system uses llvm-dwarfdump. I was wondering if we could reuse part of the infrastructure of this PR to do the same job. Again, this could be a future improvement.

The first skim of the PR looks OK to me, I might need a second look to it. Also please fix the errors in the CI.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal
pablogsal self-requested a review September 11, 2026 21:26
@pablogsal

pablogsal commented Sep 11, 2026

Copy link
Copy Markdown
Member
  • when building the unwinding information for the JIT shim, the build system uses llvm-dwarfdump. I was wondering if we could reuse part of the infrastructure of this PR to do the same job. Again, this could be a future improvement.

I would prefer to not depend on llvm for non-optional parts of CPython at least for now

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal

pablogsal commented Sep 11, 2026

Copy link
Copy Markdown
Member

Will review this soon :)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@diegorusso

diegorusso commented Sep 11, 2026

Copy link
Copy Markdown
Contributor
  • when building the unwinding information for the JIT shim, the build system uses llvm-dwarfdump. I was wondering if we could reuse part of the infrastructure of this PR to do the same job. Again, this could be a future improvement.

I would prefer to not depend on llvm for non-optional parts of CPython at least for now

Re reading my message I realised that I didn't express well what I meant. I meant that we could reuse the work in this PR to drop the llvm-dwarfdump when building the JIT.
At this stage it is still OK because the JIT requires llvm, hence llvm-dwarfdump is present. I wasn't suggesting to use llvm for this PR :)

pablogsal reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

stratakis added 5 commits September 12, 2026 00:34
@stratakis
pythongh-149800: Add CFI directives to the perf trampoline assembly
30241aa
Let the assembler emit an .eh_frame for the trampoline, matching the
frame layout jit_unwind.c describes.
@stratakis
pythongh-149800: Declare the perf trampoline template labels as char …
4439b52
…symbols
@stratakis
pythongh-149800: Generate the perf trampoline .eh_frame from the comp…
b63f0d1
…iled assembly

Extract the .eh_frame the assembler emits for the trampoline object at
build time into trampoline_ehframe.h and patch only the FDE address
fields at runtime. Building with the perf trampoline now needs a host
Python, and configure disables the trampoline with a warning when none
is usable.
@stratakis
pythongh-149800: Test the generated perf trampoline unwind data
5534711
Check the FDEs in jitdump files against their code load records, cover
the generator's parsers, and validate the header structure from C.
@stratakis
Skip the jitdump test on BOLT builds
0f6b805
@stratakis
stratakis force-pushed the trampoline_ehframe branch from 99dbd73 to 0f6b805 Compare September 11, 2026 22:37
@stratakis

stratakis commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Force pushed the get the latest changes from main, the commits are the same, I don't see how the CI could be failing so it might need something else, couldn't reproduce it.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@stratakis

stratakis commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author
* I was exploring the idea to use the _bootstrap_python instead of requiring an existent python installation in order to run _trampoline_ehframe.py‎ but I'm not sure if it works. This could be an improvement of the current implementation

I'll take a jab on that, it certainly sounds like a better design. I could send another PR with it as alternative or do a followup, whatever works best.

* when building the unwinding information for the JIT shim, the build system uses `llvm-dwarfdump`. I was wondering if we could reuse part of the infrastructure of this PR to do the same job. Again, this could be a future improvement.

Sharing would mean adding a CFA program interpreter in Python, which sounds great if it's gonna start reducing the llvm dependency area of the JIT. I'd be happy to take a look at it but since I deal with the JIT as adjacent to these Perf issues I don't have the best overview of the possible impact.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@stratakis

stratakis commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

The CI on Mac fails on the llvm installation phase

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

pablogsal
pablogsal reviewed Sep 12, 2026
View reviewed changes
Comment thread Makefile.pre.in Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Modules/_testinternalcapi.c Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread configure.ac Resolved

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal
small reorganization to trampoline unwind generation
48c7945
@stratakis

stratakis commented Sep 12, 2026

Copy link
Copy Markdown
Contributor Author
* I was exploring the idea to use the _bootstrap_python instead of requiring an existent python installation in order to run _trampoline_ehframe.py‎ but I'm not sure if it works. This could be an improvement of the current implementation

A branch with some extra commits on top of this PR implementing that to see if it makes sense: main...stratakis:cpython:trampoline_bootstrap

However it's mostly Fable generated with a small review by gpt6, haven't checked the code much or done any rigorous testing apart from a simple build and tests. If it makes sense I can expand on this.

I'll check out the review comments the next days (or feel free to amend as you see fit :) )

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal

pablogsal commented Sep 12, 2026

Copy link
Copy Markdown
Member

I pushed a commit with some small cleanup for the main file to parse the debug info

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

stratakis added 3 commits September 12, 2026 12:41
@stratakis
Require Python 3.9 or newer to build the perf trampoline
0449701
@stratakis
Move the trampoline unwind generator to Tools/build
c9813b1
@stratakis
Drop the C checks
fecb1db
@stratakis
stratakis requested review from JacobCoffee, ezio-melotti, hugovk and webknjaz as code owners September 12, 2026 10:54
pablogsal
pablogsal reviewed Sep 13, 2026
View reviewed changes
Comment thread Lib/test/test_tools/test_trampoline_ehframe.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Lib/test/test_perf_profiler.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Tools/build/generate_trampoline_ehframe.py Resolved

Uh oh!

There was an error while loading. Please reload this page.

stratakis and others added 2 commits September 14, 2026 13:24
@stratakis
Address review
7b518cb
@hugovk
Merge branch 'main' into trampoline_ehframe
1010690
@hugovk

hugovk commented Sep 14, 2026

Copy link
Copy Markdown
Member

(I updated the branch from main to fix KeyError: 'soft-deprecated' in the docs CI.)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@pablogsal pablogsal pablogsal left review comments
@brandtbucher brandtbucher Awaiting requested review from brandtbucher
@savannahostrowski savannahostrowski Awaiting requested review from savannahostrowski
@diegorusso diegorusso Awaiting requested review from diegorusso
@erlend-aasland erlend-aasland Awaiting requested review from erlend-aasland erlend-aasland is a code owner
@AA-Turner AA-Turner Awaiting requested review from AA-Turner AA-Turner is a code owner
@emmatyping emmatyping Awaiting requested review from emmatyping emmatyping is a code owner
@itamaro itamaro Awaiting requested review from itamaro itamaro is a code owner
@corona10 corona10 Awaiting requested review from corona10 corona10 is a code owner
@ezio-melotti ezio-melotti Awaiting requested review from ezio-melotti ezio-melotti is a code owner
@hugovk hugovk Awaiting requested review from hugovk hugovk is a code owner
@webknjaz webknjaz Awaiting requested review from webknjaz webknjaz is a code owner
@JacobCoffee JacobCoffee Awaiting requested review from JacobCoffee JacobCoffee is a code owner

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

awaiting review

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Refactor perf trampoline proposal: split the assembly per architecture, auto-generate DWARF unwind data

Uh oh!

There was an error while loading. Please reload this page.

4 participants

@stratakis @diegorusso @pablogsal @hugovk
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.