Conversation
3e0d256 to
6df5cde
Compare
Upstream commit: https://webrtc.googlesource.com/src/+/fe210de7215dc375cba88a42df2715e4a4d6706f Let dav1d retain references to wrapped bitstream buffers. (cherry picked from commit fcea1cf20ab03a15d2ca702629208e965edb3990) Bug: chromium:486421953 Change-Id: I855616d8206711b371df05a306730468ec8d23e7 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/453200 Commit-Queue: Philip Eliasson <philipel@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Cr-Original-Commit-Position: refs/heads/main@{#47051} Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/454341 Reviewed-by: Johannes Kron <kron@webrtc.org> Cr-Commit-Position: refs/branch-heads/7680@{#1} Cr-Branched-From: d1972add2a63b2a528a6471d447f82e0010b5215-refs/heads/main@{#46853}
4bc3c4e to
3458b07
Compare
Upstream commit: https://webrtc.googlesource.com/src/+/de817d4ccf67a457e310c6a1eca6eafcd9c2977e [M147] Revert^3 "Default enable WebRTC-HeaderExtensionNegotiateMemory" Original change's description: > Revert^3 "Default enable WebRTC-HeaderExtensionNegotiateMemory" > > This reverts commit 2f069781037ac1f9965d39152c6c97ea98ce6aff. > > Reland "Default enable WebRTC-HeaderExtensionNegotiateMemory" > > This reverts commit 2f069781037ac1f9965d39152c6c97ea98ce6aff. > > Reason for revert: Abundance of caution - want more canary time. > > Original change's description: > > Revert^2 "Default enable WebRTC-HeaderExtensionNegotiateMemory" > > > > This reverts commit 74d988fd57f8f1b6722d8ac6f49c686b9f2bc196. > > > > Reland "Default enable WebRTC-HeaderExtensionNegotiateMemory" > > > > This reverts commit 74d988fd57f8f1b6722d8ac6f49c686b9f2bc196. > > > > Reason for revert: Added code to skip stopped transceivers > > > > Original change's description: > > > Revert "Default enable WebRTC-HeaderExtensionNegotiateMemory" > > > > > > This reverts commit 4ecf297a4c0af68ff8af8c3a8e6b0832bddd14d5. > > > > > > Reason for revert: Impacted unexpected application usages > > > > > > Original change's description: > > > > Default enable WebRTC-HeaderExtensionNegotiateMemory > > > > > > > > Spec change: w3c/webrtc-extensions#238 > > > > > > > > Chromestatus entry for change: https://chromestatus.com/feature/5135528638939136 > > > > > > > > Bug: webrtc:439514253 > > > > Change-Id: I296f2f06dd69b4e30be419b44c926acfd2722e2d > > > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/407821 > > > > Commit-Queue: Harald Alvestrand <hta@webrtc.org> > > > > Reviewed-by: Guido Urdaneta <guidou@webrtc.org> > > > > Cr-Commit-Position: refs/heads/main@{#45993} > > > > > > Bug: webrtc:439514253, chromium:467164231 > > > Change-Id: I95dbc8cbaf1b769ffaea291801684bc26e4b9ccb > > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/433102 > > > Reviewed-by: Guido Urdaneta <guidou@webrtc.org> > > > Commit-Queue: Harald Alvestrand <hta@webrtc.org> > > > Cr-Commit-Position: refs/heads/main@{#46456} > > > > Bug: webrtc:439514253, chromium:467164231 > > Change-Id: I2df85ba25016374a52abb13037cdca74fb1a395d > > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/453240 > > Reviewed-by: Guido Urdaneta <guidou@webrtc.org> > > Commit-Queue: Guido Urdaneta <guidou@webrtc.org> > > Cr-Commit-Position: refs/heads/main@{#47038} > > No-Try: True > Bug: webrtc:439514253, chromium:467164231, webrtc:489813847 > Change-Id: Id2151293ffe14d2238a1363dd7df679c8a27c42f > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/453820 > Commit-Queue: Harald Alvestrand <hta@webrtc.org> > Reviewed-by: Guido Urdaneta <guidou@webrtc.org> > Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> > Cr-Commit-Position: refs/heads/main@{#47093} (cherry picked from commit 5f9534d9205a870d40aff649967a38fbde7d7653) Bug: chromium:491748676,webrtc:439514253,chromium:467164231,webrtc:489813847 Change-Id: Id2151293ffe14d2238a1363dd7df679c8a27c42f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/455980 Auto-Submit: Chrome Cherry Picker <chrome-cherry-picker@chops-service-accounts.iam.gserviceaccount.com> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Cr-Commit-Position: refs/branch-heads/7727@{#1} Cr-Branched-From: 5788235ac856f62f1522d1491c4a8b00dba10c82-refs/heads/main@{#47086}
|
@classilla @carlosgonz0 @chmeeedalf please feel free to give this PR a try. I have tried to hand test it as much as possible but I am sure I might have missed some edge cases |
The four call sites of xxinsertw in MacroAssembler-ppc64-inl.h were
emitted unconditionally:
- replaceLaneInt32x4 (line 3523)
- replaceLaneFloat32x4 (line 3532)
- convertFloat64x2ToFloat32x4 (lines 4716, 4720, both lanes)
xxinsertw is POWER9 (ISA 3.0) only; binutils confirms `as -mpower8
xxinsertw 0,1,0` rejects the opcode. On real POWER8 silicon these
helpers would SIGILL the first time a wasm SIMD program reaches them
(replaceLane / demote / lane-load fast paths). The "POWER8 forced"
mode (MOZ_PPC64_FORCE_POWER8=1) only flips runtime gating, so our
POWER9 dev box never caught this — the silicon executes the
unconditional xxinsertw fine regardless of what HasPOWER9() returns.
Wrap each helper in `if (HasPOWER9()) { /* original 2-insn path */ }
else { /* POWER8 fallback */ }`. The fallbacks:
replaceLaneInt32x4 (~5 insns) — mirrors the existing replaceLaneInt16x8
POWER8-compatible pattern: extract the relevant doubleword to a GPR
(mfvsrd or xxpermdi+mfvsrd), rldimi rhs into the right 32-bit slot,
mtvsrd back, xxpermdi to recombine. Lane → (dword, wordInDword)
mapping: dword = lane / 2, wordInDword = lane % 2.
replaceLaneFloat32x4 (~8 insns) — convert the f64 rhs to single via
xscvdpspn (lands in BE bits 0..31 of an FPR), extract bits to a GPR
via mfvsrd + srdi 32, then run the same int-insert sequence as above.
convertFloat64x2ToFloat32x4 (~14 insns) — per-lane extract to GPR
(swap halves with xxpermdi DM=2 for lane 0, then xscvdpsp + mfvsrd +
srdi/rldicr to place each single in low/high 32 bits of a GPR),
combine via or, then mtvsrd + xxpermdi DM=0 to place in LE dw0 with
LE dw1 zeroed.
Aliasing matrix considered for each helper:
- replaceLaneInt32x4: rhs is GPR, lhsDest is FPR — no FPR/GPR aliasing.
- replaceLaneFloat32x4: rhs is FPR. If rhs == lhsDest, the initial
xscvdpspn snapshots rhs into scratch before any write to lhsDest.
- convertFloat64x2ToFloat32x4: pre-existing VR2 stash already handles
dest == src.
Verified:
- 191/191 wasm/simd jit-tests on POWER9 default AND POWER8 forced.
- 13572/13572 full jit-test suite on POWER9 default AND POWER8 forced
(zero failures on either run).
- Argon2 reference hash 60c920340f5dbf67... matches under default,
baseline, and optimizing tier on both micro-archs.
POWER9 path code-size and runtime are unchanged; the new branches are
emitted only when HasPOWER9() returns false at compile time of each
JIT function.
Move the xxinsertw / replaceLane / convertFloat64x2ToFloat32x4 entry out of the open punch list. Document the three new POWER8 fallback shapes, instruction-count costs, aliasing analysis, and verification results on both micro-arch gating modes. Note the remaining gap that real POWER8 silicon validation is still recommended.
Update the Status section to capture the POWER8-forced JetStream 3.0 result alongside the POWER9 default score: POWER9 default : 36.82 pts POWER8 forced : 35.50 pts (~3.6% slower) This is the first full POWER8-fallback run after the xxinsertw fallbacks landed (Tier C #1, commit 065161b), and confirms the POWER8 paths execute end-to-end without crashes. The ~3.6% gap is within the expected envelope given the POWER8 fallback cost (VR-staged abs/neg, inline FP constant loads, rldimi-based replaceLane).
b5618d4 to
788c91c
Compare
Upstream commit: https://webrtc.googlesource.com/src/+/1822467bec1c91b8d782e9c7f24342d1d65f01f2 [Merge-148] Cherry pick "Move the NullVideoDecoder into a separate file and target." Original change's description: > Move the NullVideoDecoder into a separate file and target. > > This is necessary because the Chromium video decoder factory needs to > be able to instantiate it for fallback purposes (e.g. Decode error > causing the HW to no longer be available). > > Bug: chromium:500960863 > Change-Id: I724a5f28aa0a0a615972dd49eebde701c3b7ec90 > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/462243 > Reviewed-by: Evan Shrubsole <eshr@webrtc.org> > Commit-Queue: Henrik Boström <hbos@webrtc.org> > Cr-Commit-Position: refs/heads/main@{#47366} Bug: chromium:500960863 Change-Id: I724a5f28aa0a0a615972dd49eebde701c3b7ec90 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/464521 Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org> Commit-Queue: Evan Shrubsole <eshr@webrtc.org> Cr-Commit-Position: refs/branch-heads/7778@{#1} Cr-Branched-From: ca896b7ffef011bbf6957c99d413c5aac602c99f-refs/heads/main@{#47319}
… list) Same outcome as audit #1: nothing's actually wrong. All three threads are either identical to a reference backend's well-tested pattern or match the documented PPC64 convention (32-bit ops = sign-extended canonical int32). Notes in PLAN.md so a future reader doesn't re-open these.
a363036 to
9108914
Compare
| "st.d %1,%0,0;\n" // Write the line number to the crashing address | ||
| : // no output registers | ||
| : "r"(aAddress), "r"(aLine)); | ||
| # elif defined(__powerpc64__) |
There was a problem hiding this comment.
…eeper mystery Adds probe_vrsave_p9.c (transient) — tests whether Linux PPC64LE honors VRSAVE for context-switch save/restore decisions. Both phases PASS: VRs are preserved across sched_yield+usleep regardless of VRSAVE value (default 0xffffffff or forced 0). Kernel saves all VRs unconditionally. Hypothesis #1 (Mozilla not maintaining VRSAVE) ruled out. Extends WasmSignalHandlers.cpp [lc1-vr] patch to also dump key GPRs (r1, r4, r11, r24) from ucontext alongside VRs. Captured GPRs are sane and consistent (r24 = wasm base, r1 = sp matches startWasmTrap's sp, r11 = r4 + 304). ucontext reads ARE reliable. Hypothesis mozilla-firefox#4 (misreading ucontext) ruled out. That leaves a gap between static disasm (predicts non-negative trunc_sat output via pmax→pmin chain) and runtime captured VRs (vr6 lane 0 = 0xFF000000 = -16M). Strongest remaining: gdb's PowerPC disassembler misinterprets an instruction in the chain, so we're reading code that's not actually executing. Math at trap is fully consistent with captured values: vr6 * 18 (mod 2^32) + vr8 = vr1 → produces {0xEE000000, 0xFFFFFFF7, 5, 7} vr1 + vr2 = vr16 → produces {1.13e9, 1.08e9, 7.29e8, 3.75e8} lane0(vr16) << 4 + base produces r4 = 0x41A29110 → OOB at base+1.1GB Bug is real, captured, and corruption is in v6 (X coords) coming out of the trunc_sat chain at JIT 0x4afc despite static analysis saying the chain produces non-negative output.
…duce
Built probe_lc1_chain_p9.c — bare-minimum C+inline-asm replay of
the trunc_sat → 300-op filler → vmuluwm pattern. 0 corruptions in
10M iterations on P9. So the bug is NOT a generic "long VSU dep
chain" silicon issue; it requires specific lc.wasm chain context
the synthetic doesn't capture.
Captured today's actual JIT disasm via [lc1-bytes] hook, saved to
artifacts/lc-trap-2026-05-07.{bin,disasm.txt} (gitignored). Today's
chain matches the May 5 layout structurally: vs33 (=v1) trunc_sat
at 0x4bb0, multiply at 0x50f0, no intermediate writes to vs33 in
between. The architectural register that gets corrupted varies per
run (vr5 in May 5; vr1 today), confirming the bug is a regalloc/
rename-routing event, not register-specific.
A faithful 515-instruction-window standalone reproducer would
require careful state setup; not undertaken this session.
|
FWIW it seems |
@sharkcz that's ALOT of RAM you have. It's good to know it does work, let me update the notes |
|
@sharkcz I believe you have POWER8 hardware, wondering if you could help run full jit-test and jstests for me and let me know the results? Many thanks |
Updates the POWER8 status block + "Truly open" item #1 to reflect the 2026-05-08 result: full jit-test sweep clean on the architected-P8 KVM guest after Cluster A (commit 0e92b3e) and Cluster B (commit 3dcf4a1). Cluster B's real codegen fix remains open as a follow-up tracking with upstream Bug 1666747.
yes, I should be able to run the tests on a P8 system. What is the procedure you are using? |
@sharkcz you need to build the software on your P8 first, check the |
|
@sharkcz @kth5 FYI https://github.com/runlevel5/firefox-ppc64/releases/tag/FIREFOX_152_0_5_RELEASE_PPC64 can be cleanly applied with |
84a9b76 to
38af16d
Compare
3183f45 to
43989b5
Compare
|
Could someone with better Debian skills than I have build a Debian package, or tell me how to build one? I tried following the Build instructions in the PR description and it threw a very helpful "Error 2" with no visible reason. |
@chmeeedalf FYI I have submitted a patch for Debian downstream package, but that's for Firefox 152. Debian has not yet bumped theirs to 153 or newer. Could you please let me know which Debian distribution version you are using? |
|
@chmeeedalf I've just updated the PR with full instructions for Debian. I got it compile successfully on Debian 13.5 |
|
@runlevel5 great, thanks. I was hoping I could build a .deb package for 14/testing, but probably not going to happen, because the Debian firefox-esr is 140. |
@chmeeedalf I strongly believe Debian team will soon cut a dedicated git branch for the esr-153. While waiting, nothing stop you from building your own local Debian package. I highly encourage you to chime in https://salsa.debian.org/mozilla-team/firefox/-/merge_requests/17 to bring that work to the attention of the Debian team. |
Adapted from work done by Raptor Engineering for chromium's vendored SKIA. Gated to little-endian: the SSE-derived swizzle and permute helpers assume the ppc64le vector-register byte order, so big-endian falls back to the portable paths. Co-authored-by: Timothy Pearson <tpearson@raptorengineering.com>
Gated to little-endian: the VSX kernels assume the ppc64le vector-register byte order, so big-endian falls back to the portable C paths. Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com>
Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com> Assisted-by: James Zern <jzern@google.com>
|
@sharkcz is there anything left to do to get the patch officially adopted downstream with Fedora? |
Based on the work done by Cameron Kaiser and Justin Hibbits https://github.com/chmeeedalf/gecko-dev Co-authored-by: Cameron Kaiser <classilla@floodgap.com> Co-authored-by: Justin Hibbits <chmeeedalf@gmail.com> Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com> Assisted-by: Timothy Pearson <tpearson@solidsilicon.com> Assisted-by: Dan Horák <dan@danny.cz> Assisted-by: Hiếu Lê <modology@gmail.com> Assisted-by: Claude Fable 5 <noreply@anthropic.com>
Enable the SpiderMonkey JIT and WebAssembly on big-endian PPC64 (ELFv1 and ELFv2). Co-authored-by: Cameron Kaiser <classilla@floodgap.com> Co-authored-by: Justin Hibbits <chmeeedalf@gmail.com> Assisted-by: Lance Albertson <lance@osuosl.org> Assisted-by: Thushan Fernando <thushan@thushanfernando.com> Assisted-by: Timothy Pearson <tpearson@solidsilicon.com> Assisted-by: Dan Horák <dan@danny.cz> Assisted-by: Hiếu Lê <modology@gmail.com> Assisted-by: Claude Fable 5 <noreply@anthropic.com> Assisted-by: Alexander Baldeck <alex.bldck@gmail.com>
The build system defines HAVE_PLATFORM_GHASH for both PPC64 endians, but the POWER8 vpmsumd GHASH implementation was compiled out on big-endian, leaving platform_ghash_support, gcm_HashInit_hw, gcm_HashWrite_hw and gcm_HashZeroX_hw unresolved and freebl failing to link. Make ghash-ppc.c endian-correct instead of stubbing it out. GNU C vector element indexing follows memory order, so the doubleword element reads, the pair constructors and the vec_splat index of the most-significant byte must mirror on big-endian, while vec_xl_be, vec_xst_be and the whole-register operations (vpmsumd, vec_sll, vec_rl, xor) already produce identical register values on both endians. The new USE_PPC_CRYPTO_GHASH define drops the little-endian restriction for ghash-ppc.c only; the other USE_PPC_CRYPTO consumers remain little-endian. Also give gcm.c the same -mcrypto/-maltivec cflags as ghash-ppc.c in gcm.gyp. gcmHashContext's vec_u64 x/h fields are gated on __ALTIVEC__/__VSX__, so without this gcm.c and ghash-ppc.c disagree on sizeof(gcmHashContext) and every field after x/h -- including the ghash_mul function pointer -- lands at a different offset in each translation unit, corrupting the hardware GHASH dispatch. This is not endian-specific: it affects ppc64le the same way whenever disable_crypto_vsx doesn't already imply matching flags elsewhere. Found by crashing on a real TLS 1.3 handshake (AES-GCM record decrypt) in a full browser build, not just the isolated GHASH unit tests. Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=2027768
Big-endian used to flip the OS_RGBA surface format synonyms to the
A8R8G8B8 memory layout, which Skia has no color type for, so surface
creation hit MOZ_DIAGNOSTIC_CRASH("A8R8G8B8 unsupported by Skia") as
soon as anything was drawn. Keep the synonyms pinned to the B8G8R8A8
memory layout on both endians so the whole pixel pipeline operates on
one layout, and convert for the display server at the compositor
boundary instead.
Skia's SkPMColor channel shifts describe a little-endian uint32_t
view of that layout, so on big-endian a packed color value and the
in-memory destination pixels disagree on byte order. Introduce
BE_CONVERT (a no-op on little-endian) and apply it at the scalar
blitter load/store boundaries: solid fills, the blit_row_color32
kernel, A8 glyph masks, LCD16 subpixel text, BW masks, the black
blitter, and the direct-blit fill value. Alpha extraction always uses
the unconverted value. The SurfaceFormatBit shifts mirror on
big-endian so channel accessors keep addressing the same bytes, and
kARGBAlphaOffset moves to byte 0 for the RGBX verification.
Software WebRender resolves frames in the B8G8R8A8 memory layout, but
X11 consumes native-endian 32-bit pixel values, so swizzle the dirty
region to the A8R8G8B8 layout when handing the buffer to the widget.
Skia-drawn image surfaces get the inverse reorder in imgFrame before
they enter the surface cache.
Known gap: SkRasterPipeline's load/store stages and the headless
screenshot readback still assume little-endian and are unchanged.
Define GP_PLAT_ppc64_linux so the profiler uses the real Linux sampler instead of platform-noop.cpp, and capture PC/SP/FP/LR from the signal ucontext (NIA, r1, r31, LR). A new UNWINDING_REGS_HAVE_LR register-set variant forwards LR to JS::ProfilingFrameIterator, whose PPC64 support already landed with the wasm profiling work. Native stack walking uses a dedicated backchain walker: the PPC64 ELF ABIs require every function that allocates a stack frame to store the caller's stack pointer at *(sp) and its return address at caller_sp + 16, at every optimization level, so the native call stack can be recovered without unwind tables or LUL support. The walk is bounds- and alignment-checked against the sampled thread's stack and stops at JIT frames, which are covered by the JS frame merging instead. The walker needs no initialization, so it also serves the fast-init path used for backtrace samples. shared-libraries-linux.cc is enabled for symbolication, and the sysfs-based CPU-frequency counter compiles on the no-LUL branch.
PPC64 JIT support for Firefox 154+
Brings JIT compilation to PPC64 — both little-endian (ppc64le) and big-endian (ppc64/ppc64be, ELFv1 and ELFv2) — targeting POWER8+ (ISA v2.07+) with POWER9 (ISA v3.0) / POWER10 (ISA 3.1) optimizations. Enables SpiderMonkey's Baseline interpreter, Baseline and Ion JIT compilers, the native regexp JIT, plus full WebAssembly support — tiering, SIMD, huge memory, JSPI, tail calls, and atomics.
This PR revives the JIT port https://github.com/chmeeedalf/gecko-dev by Cameron Kaiser (@classilla) and Justin Hibbits (@chmeeedalf).
This PR would always track against the latest upstream. If you are a packager, please find downstream patches in Releases, if the version you are after are not there, please simply leave a comment in this PR and I will prepare the patches for you.
If you are after the ESR 153 support, please check out #2
Test results
Real little-endian POWER8 hardware (SpiderMonkey with debug, GCC 14, sponsored by Oregon State University):
--jitflags=all)jstests(JSPI on)Real little-endian POWER9 hardware (SpiderMonkey with debug, GCC 16, sponsored by Raptor Computing System):
MOZ_PPC64_FORCE_POWER8=1--jitflags=all)jstests(JSPI on)Real little-endian POWER10 hardware (SpiderMonkey with debug, GCC 14, sponsored by Oregon State University):
MOZ_PPC64_FORCE_POWER9=1MOZ_PPC64_FORCE_POWER8=1--jitflags=all)jstests(JSPI on)ARM64-host simulator for ppc64le:
FORCE_POWER8=1FORCE_POWER9=1FORCE_POWER10=1jstests(JSPI on)†
shell/os.js("killed process should not have exitStatus") was a parallel-load flake on slower hosts — the test sent SIGINT to asleep 60child and could lose the signal-delivery race under heavy concurrent jstests load, then waitpid blocked until the child exited normally and the assertion failed. Fixed 2026-05-08 by switching to SIGKILL (which is uncatchable, atomic, and works under any load). Patch in this PR.FORCE_POWER10=1impliesFORCE_POWER9=1(matches what real-P10 silicon advertises inhwcap2— bothARCH_3_00andARCH_3_1). Six clean sweeps total — zero hard FAIL, zero TIMEOUT.Real big-endian POWER9 hardware — ELFv1 (Debian ppc64) and ELFv2 (Arch POWER ppc64), SpiderMonkey debug shell:
--jitflags=all)jstestsMOZ_PPC64_FORCE_POWER8=1MOZ_PPC64_FORCE_POWER8=1‡ Same small set of legitimately slow tests under
--jitflags=all's heaviest combinations (e.g.--no-blinterp --no-baseline --no-ion --more-compartments,gc/bug-2049401.js) exceeding the harness's default timeout under shared-host CPU contention — both boxes are VMs sharing hardware with other work. The identical test/flag combination also times out on real little-endian POWER10, confirming host-load noise rather than an endianness or correctness issue; every affected test passes cleanly when re-run in isolation.Big-endian (ppc64be) support
The same backend runs big-endian, on both the ELFv1 and ELFv2 ABIs, across POWER8/9/10:
_CALL_ELF, not byte order — big-endian ELFv2 shares the little-endian call paths (no function descriptors), while ELFv1 uses{entry, TOC, env}descriptors for the JIT / regexp / wasm entry trampolines and symbolic-address calls.mozilla::Resultnarrow storage. jit-test and wasm spec-harness cases that hard-coded little-endian byte order are made endian-neutral.Big-endian rendering (full browser)
Firefox on big-endian renders correctly — confirmed on real X11, pixel-verified (correct chrome, page background, link colors, text, and DevTools UI) — via a fourth layer of endian work beyond the JIT itself:
vpmsumd-based GHASH (AES-GCM) is made endian-correct rather than stubbed out on big-endian, plus a companion fix for a real (both-endian, not just BE)gcm.c/ghash-ppc.cstruct-layout mismatch that corrupted the hardware GHASH dispatch and crashed on the first real TLS 1.3 handshake.WMERGEH/WMERGELwidening-merge fix, same underlying issue class as the GHASH fix: GNU C vector element indexing is memory-order, so a widening merge lands in the opposite half on big-endian.OS_RGBAsurface-format synonym to a memory layout (A8R8G8B8) that Skia has no color type for, hittingMOZ_DIAGNOSTIC_CRASH("A8R8G8B8 unsupported by Skia")on the first paint. Fixed by keeping the whole pixel pipeline on one layout (Skia's little-endian value convention) and converting only at the two real boundaries: Skia's scalar blitters (fills, AA text, LCD subpixel text, glyph masks — via aBE_CONVERTmacro, no-op on little-endian) and the software-WebRender→X11 handoff (dirty-region swizzle inRenderCompositorSWGL).SkRasterPipeline's load/store stages (used for gradients and image sampling through Skia) are unchanged and still assume little-endian — content exercising that path may still show incorrect colors on big-endian. Not yet hit by the JS/DOM-heavy jit-test and jstests suites above, which is why it wasn't caught by that matrix; flagging here rather than leaving it silently uncovered.Scope
js/src/jit/ppc64/— ~17,500 lines.What's new vs the old chmeeedalf/gecko-dev Firefox-86 port
Inherited:
Architecture-ppc64.hregister/ABI constants, theAssembler-ppc64.h/cppinstruction-encoding skeleton, some basic MacroAssembler patterns.New in this port:
js/moz.configure, dispatch headers,js/src/jit/moz.build).CodeGenerator, Lowering visitors, LIR-ppc64 (old fork predated Warp).CompareExchange/AtomicExchange/AtomicFetchOp.getauxval(AT_HWCAP2), with fallback sequences for every POWER9-only instruction and POWER10 fast paths gated onHasPOWER10().addpcisFP-constant path, POWER10 prefix-instruction fast paths (see below), GCC-stylelis+ori+rldimi64-bit load (~37 % smaller than abcl-based stanza).FlushICache.Key architecture-specific features
Runtime POWER8/POWER9/POWER10 selection
Detection via
getauxval(AT_HWCAP2)—PPC_FEATURE2_ARCH_3_00for POWER9,PPC_FEATURE2_ARCH_3_1for POWER10.cnttzd/w,xxbrd,mtvsrws,mcrxrx,addpcis,modsw/u/d/du,vinsert{b,h}(lane insert from VR + immediate byte position),xxinsertw,mfvsrld,mtvsrdd,xs{min,max}jdp,xxspltib,vcmpne{b,h,w},vneg{w,d},isel,xscvdphp/xscvhpdp(FP16 scalar conversion),xsxexpdp(P9 exponent extract fornearbyIntDouble).replaceLaneInt{8x16,16x8}on POWER9 emits the 2-insnmtvsrd + vinsert{b,h}sequence (down from 5 insns).clampDoubleToUint8is fully branchless on P9 viaxsmaxjdp + isel— the canonical JS clamp shape collapses to a 4-insn straight-line sequence.HasPOWER10()):Addressoperands when displacement exceeds 16 bits):loadPtr→pld,loadDouble→plfd,loadFloat32→plfs,loadUnalignedSimd128→plxv. Replaces the prioraddis + ori + ldx-style two-insn stanzas with one prefixed insn.storePtr→pstd,storeDouble→pstfd,storeFloat32→pstfs,storeUnalignedSimd128→pstxv.loadConstantSimd1283 +xxpermdi→ 1plxv;loadConstantDouble/Float322 → 1plfd/plfs;movePtr(ImmWord)33–34-bit signed 5 → 1paddi.brdcollapsesbyteSwap643 → 1 + drops the GPR↔FPR round-trip;brh/brwcollapsebyteSwap16{Sign,Zero}Extend/byteSwap32from 3-4 → 2;vinsw/vinsdcollapsereplaceLaneInt{32x4,64x2}from 2 → 1 (no scratch VSR);vinsbrx/vinshrxcover the same byte/halfword replaceLane on POWER10;vextract{b,h,w,d}mcollapses bitmask to 1 insn;vmulldcollapsesmulInt64x2from 9-11 insns to 1.setbc/setbcr: 1-insnma_cmp_set, 1-insnallTrueInt*CR6.EQ extract, and 5 → 3 insnanyTrueSimd128. Replaces the oldermfocrf + rlwinm + andi.extraction pattern across the boolean-reduction family.Test with
MOZ_PPC64_FORCE_POWER8=1(downgrade),MOZ_PPC64_FORCE_POWER9=1(force P9 on, useful under sim), orMOZ_PPC64_FORCE_POWER10=1(which impliesFORCE_POWER9=1— matches real-P10 silicon detection). All three configurations PASS the full jit-test + jstests sweeps end-to-end on the simulator.POWER10 prefix-instruction support
Power ISA v3.1 prefixed instructions are 8 bytes (4-byte prefix word with primary opcode 1 + 4-byte suffix word) and must not straddle a 64-byte aligned block at runtime. The assembler emits them via
as_paddi/as_pld/as_plxv/as_plfd/as_plfs, with an automatic leading-nop guard when the prefix would otherwise cross the boundary.The original guard checked
(currentOffset() & 63) == 60— a buffer-relative test that's only correct when the JitCode allocator base is 64-byte aligned. The allocator only guarantees 16-byte alignment, so across the four base-mod-64 classes {0, 16, 32, 48} the unsafe straddle is exactly(currentOffset() & 15) == 12. The same fix shape applies to the inline-emit path (ensurePrefixedAlignment, commit8ae818d0fcab) and the constant-pool patcher (PatchConstantPoolLoad, commitaea233e21209). The simulator's POWER10 model doesn't trap misaligned prefixes, which is why these only surfaced when real-P10 silicon came online.The simulator decodes prefixed instructions, validated against
as -mpower10+objdumpon Fedora 44 / binutils 2.46. Encoding details (MLS Type=2 vs 8LS Type=0 vs 8RR Type=1, R-bit at LE position 20,plxv5-bit suffix opcode + TX bit at suffix bit 26) live inSimulator-ppc64.cppsource comments andPLAN.md's engineering-lessons section.WASM SIMD
Full VMX/VSX implementation using PPC64 AltiVec. All 10 tiers — load/store/splat/lane, bitwise, arithmetic, cmp/shift, float, conversions, shuffle/swizzle, extmul/pairwise/dot, relaxed SIMD (FMA/FNMA). NaN semantics correct (min/max propagation, truncSat NaN→zero, promote NaN-quieting). P8 uses
lxvd2x/stxvd2xwith byte-swap; P9 uses nativelxvx/stxvx; P10 collapses the constant-pool variant to a singleplxv.WASM JSPI
WebAssembly.Suspending/WebAssembly.promisingviajavascript.options.wasm_js_promise_integration. Addppc64to the JSPI whitelists injs/moz.configure(both thedefault_wasm_jspisimulator allowlist and thewasm_jspisimulator-guard die-list — extending the original target.cpu enable to cover sim builds too), and roundContRedZoneSizeup to a page-size multiple so the bottom guard page lands on a page boundary under PPC64LE's 64 KiB pages. No arch-specific stack-switch code required.WASM huge memory
4 GB + 32 MB virtual reservation per wasm memory, bounds-check elimination via SIGSEGV → wasm trap. Signal-handler context indices:
gp_regs[32]=NIA,gp_regs[1]=SP,gp_regs[31]=FP,gp_regs[36]=LR.Simulator (ARM64-host)
A full PPC64 simulator is included so CI can run the JIT on non-PPC64 hosts. Both jit-test and jstests sweeps pass under
FORCE_POWER8=1,FORCE_POWER9=1, andFORCE_POWER10=1configurations (zero hard FAIL, zero TIMEOUT). The sim received many ISA-correctness fixes during development (VMX/VSX decoding, LE lane ordering, FP NaN-payload preservation across f32↔f64, ELFv1 FP-arg shadow slots, single-step profiling for tail calls and non-leaf epilogues), and now decodes:addpcis,mods*/modu*,mtvsrws,xxspltib,xxinsertw,xscvdpsp(n)HW-conformance fix,xs{max,min}jdp,xscvdphp/xscvhpdp(FP16),xsxexpdp. Closes the historical "~40 wasm/simd tests fail under FORCE_POWER9 on the sim" coverage gap.paddi/pld/plxv/plfd/plfs), plus the new instruction-count-reduction ops (brd,brh,brw,vinsw,vinsd,vinsbrx,vinshrx,vextract*m,setbc/setbcr,vmulld).setXEROV()fix that mirrors OV→OV32 — the JIT'sbranchMulPtrOverflow path uses POWER9'smcrxrx+bcwhich reads OV32, and the original sim only set OV. Surfaced as silent BigInt fast-path-mul wrap-around inwasm/regress/bug1836708.js.Build
Complete from-scratch walkthrough — little-endian (Debian / Ubuntu / Fedora, ppc64le)
Mozilla's
./mach bootstrapcannot download prebuilt toolchains for ppc64, soeverything comes from your distro plus rustup. These steps take a fresh
ppc64le machine to a running browser. Big-endian Debian has its own section
right after this one.
1. Install build dependencies.
Debian / Ubuntu — let apt resolve the whole Firefox dependency tree, then add
the handful of pieces it misses:
Fedora:
2. Install Rust and cbindgen via rustup. Distro packages are almost
always too old — this tree requires Rust >= 1.90 and cbindgen >= 0.29.4
(node only needs >= 12, any current distro package is fine):
Make sure
~/.cargo/binstays onPATHfor every build shell.3. Clone this repository and branch.
git clone --branch ppc64 https://github.com/runlevel5/firefox-ppc64.git cd firefox-ppc64(For ESR 153 use
--branch esr153-ppc64, see PR #2. Packagers who preferpatch files over a git checkout: apply the numbered patches from
Releases on top of the
matching Mozilla release tarball instead.)
4. Write a
mozconfig. Create a file namedmozconfigin the tree rootwith one of the configurations below (JS shell, full Firefox GCC, or full
Firefox Clang+LTO). Two lines matter on ppc64 no matter which you pick:
5. Build and run.
Hardware/RAM notes: linking
libxul.sowithlldpeaks around 8 GB;16 GB RAM is a comfortable minimum for the full browser (the JS shell builds
on much less). On bigger machines cap parallelism (
mk_add_options MOZ_PARALLEL_BUILD=20) rather than letting mach use every core — widelldlinks can OOM the box.
Troubleshooting:
machfails creating its virtualenv →sudo apt install python3-venv.rustc --version(>= 1.90) and
cbindgen --version(>= 0.29.4); the rustup/cargo copies in~/.cargo/binmust precede any distro copies onPATH.libclang→ installlibclang-dev(Debian) /clang-devel(Fedora) and point--with-libclang-pathat the directorycontaining
libclang.so(llvm-config --libdir).MOZ_PARALLEL_BUILD, ensure the linkeris
lld(--enable-linker=lld), add swap/zram.Complete walkthrough — big-endian Debian (ppc64, ELFv1)
Big-endian Debian is an unofficial port living in
debian-ports(sid only),and the ELFv1 ABI changes the toolchain rules:
lldcannot link ELFv1 atall, and Debian's clang forces
lld— so the build must use GCC with GNUld(bfd) for both target and host. Steps 2, 3 and 5 from thelittle-endian walkthrough apply unchanged (rustup supports big-endian
powerpc64-unknown-linux-gnu); the differences:1. Dependencies. On a debian-ports sid system:
sudo apt update sudo apt build-dep firefox-esr # if firefox-esr is unavailable in ports, use: sudo apt install build-essential git curl ccache python3-venv python3-pip \ pkg-config nasm m4 unzip zip \ libgtk-3-dev libdbus-glib-1-dev libpulse-dev libasound2-dev \ libxt-dev libx11-xcb-dev libpixman-1-dev \ nodejs npm libclang-dev4. mozconfig for big-endian ELFv1:
Big-endian caveats:
bfdneeds substantially more RAM thanlldto linklibxul.so(community reports ~20 GB resident); on smaller machines build the JS shell
(
--enable-application=js), which links fine everywhere.nodejscurrently segfaults on it — see the dedicated Node.jsbootstrap section below for the two workarounds (DevTools-server-only
build, or forwarding
nodeto a little-endian helper host).cargo install cbindgen— the ports archiveversion is too old.
ELFv1 constraint origin — but clang's forced
lldstill applies on Debianderivatives, so GCC +
bfdremains the safe choice on any big-endiansystem.
mozconfig reference
SpiderMonkey (standalone JS shell):
(On the PPC64 box, cap parallelism at
-j20; the auto-detected-j32saturates the box duringlldlinking.)Full Firefox:
Full Firefox with Clang + LTO (ppc64le):
A Clang + ThinLTO build works on ppc64le and is measurably faster on
DOM/layout-heavy workloads than the plain GCC
-O2build. Two things make itwork: Clang with the LLVM linker (
lld), and system NSS — the bundledNSS
ppc-gcm.suses GAS-style semicolon statement separators that Clang'sintegrated assembler rejects, so building against the distro's NSS
(
--with-system-nss) sidesteps that entirely. This is exactly what the Fedorapackage build does.
For RPM packagers: the Fedora spec builds this with
rpmbuild --with build_with_clang --with build_with_lto.Big-endian (ppc64be): Node.js bootstrap
The full browser build runs Node.js at build time to transform the DevTools
debugger modules (
devtools/client/*viamozbuild/action/node.py). NothingNode produces ships in the binary — it is a build-time tool only — but the
build cannot finish without it, and Node on big-endian ppc64 is currently a
problem:
system Node.
nodejsis an unofficial port frozen at 20.19.5 andits
libnodesegfaults during a V8 conservative-stack-scan GC(
heap::base::Stack::IteratePointersImpl) when running the DevToolstransform — an endianness-specific V8/Node bug, unrelated to this port.
Two ways to get past it:
1. Skip the DevTools client (simplest). Set the DevTools build to
serverinstead ofall. This drops the browser-side debugger UI but keepsthe DevTools server (remote debugging still works) and needs no Node:
MOZ_DEVTOOLScannot be set frommozconfig(it is animply_option), sochange
imply_option("MOZ_DEVTOOLS", "all")to"server"inbrowser/moz.configure, or wait for a proper--disable-devtools-style knob.2. Offload Node to a working host (full DevTools). If you have a
little-endian ppc64le box (or any box with a working Node), run only the Node
steps there while the compile stays on the BE machine. Node just reads/writes
files in the source and object trees, so share the tree and forward
node:sshfs) and confirm itsNode runs
devtools/client/shared/build/build.jswithout crashing.nodewrapper first onPATHthatsshes the commandto the helper, rewriting the tree-path prefix (BE mountpoint ↔ helper
mountpoint) in both the arguments and in the
dep:lines Node prints back(the build system consumes those for incremental rebuilds):
Longer term the clean fix is a Node that does not crash on ppc64 BE (e.g.
building Node from source — Arch POWER's
nodejs-lts-ironrecipe builds20.20.0 for
powerpc64with--with-intl=system-icu).Known limitations
--with-system-nss+lld(see the Clang + LTO build recipe above). Only the bundled NSS is a problem — itsppc-gcm.suses GAS-style semicolons that Clang's integrated assembler rejects — so building against the distro NSS avoids it. PGO is still unavailable on ppc64le (GCC ICE / Clang runtime crash); LTO-only.ld.bfd: does linklibxul.sosuccessfully on ppc64le, but needs substantially more RAM during the link than lld (community reports ~20+ GiB resident, putting it out of reach for hosts with under ~24 GiB total). The P10 box uses BFD as a workaround for an LLDR_PPC64_TOC16_HAbug; lld stays the practical default everywhere else for speed.TODO