Repository: electron/electron
Pull request: build: enable V8 builtins PGO

#### Description of Change

Re-enables V8 builtins PGO, which was disabled in #38252 due to profile references breaking the shipped `mksnapshot_args`. The CI-side mitigation for that has existed since the GHA migration (sed stripping in `build-electron/action.yml`), but the build-side disable was never reverted.

**What this does:**
- Removes `v8_builtins_profiling_log_file = ""` from `all.gn` so V8's default auto-selection kicks in (picks `tools/builtins-pgo/profiles/x64.profile` when `chrome_pgo_phase == 2`, i.e. release builds only)
- Adds a small V8 patch changing `--abort-on-bad-builtin-profile-data` to `--warn-about-builtin-profile-data` in mksnapshot invocation
- Extends CI's `mksnapshot_args` stripping to also remove the orphaned `--reorder-builtins` / `--warn-about-builtin-profile-data` flags (which crash/no-op without profile input)

**Why the warn flag is safe:**

Electron sets `v8_enable_javascript_promise_hooks = true`, which adds `#ifdef` branches in `builtins-microtask-queue-gen.cc` and `promise-misc.tq`. This changes the control-flow graph hash of 11 Promise/async builtins, so they mismatch V8's pre-generated profile (built with Chrome defaults). With `--abort`, this fails the build; with `--warn`, per [`pipeline.cc:ValidateProfileData`](https://source.chromium.org/chromium/chromium/src/+/main:v8/src/compiler/pipeline.cc), the builtin's profile data is set to `nullptr` and it compiles without PGO — identical to today's behavior for that builtin. No correctness risk.

The 11 skipped builtins: `RunMicrotasks`, `AsyncFunctionEnter/Await`, `AsyncGeneratorYieldWithAwait/PrototypeNext/Await`, `FulfillPromise`, `NewPromiseCapability`, `PromiseConstructor/Resolve/PrototypeThen`. The remaining ~490 builtins (Array, String, RegExp, Map/Set, TypedArray, iterators, etc.) all receive PGO.

**Validated:** Release build succeeds, `mksnapshot.zip` extracted to an isolated directory runs standalone and generates `snapshot_blob.bin` after CI stripping is applied.

**Future work:** For full coverage of the 11 Promise/async builtins, we could generate Electron-specific profiles by running `v8/tools/builtins-pgo/generate.py` with our V8 gn args against JetStream2 — roughly a 15-20 min CI job per arch that could trigger on Chromium rolls.

#### Checklist

- [x] PR description included and stakeholders cc'd
- [ ] `npm test` passes
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers

#### Release Notes

Notes: Enabled profile-guided optimization for V8 builtins in release builds, improving JavaScript builtin performance (Array, String, RegExp, etc.).

Changed files:
filename: .github/actions/build-electron/action.yml
patch: @@ -128,6 +128,9 @@ runs:
         fi
         sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args
         sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args
+        sed $SEDOPTION '/--reorder-builtins/d' out/Default/mksnapshot_args
+        sed $SEDOPTION '/--warn-about-builtin-profile-data/d' out/Default/mksnapshot_args
+        sed $SEDOPTION '/--abort-on-bad-builtin-profile-data/d' out/Default/mksnapshot_args
 
         if [ "${{ inputs.target-platform }}" = "win" ]; then
           cd out/Default

filename: build/args/all.gn
patch: @@ -51,9 +51,6 @@ is_cfi = false
 use_qt5 = false
 use_qt6 = false
 
-# Disables the builtins PGO for V8
-v8_builtins_profiling_log_file = ""
-
 # https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md
 # TODO(vertedinde): hunt down dangling pointers on Linux
 enable_dangling_raw_ptr_checks = false

filename: patches/v8/.patches
patch: @@ -1 +1,2 @@
 chore_allow_customizing_microtask_policy_per_context.patch
+build_warn_instead_of_abort_on_builtin_pgo_profile_mismatch.patch

filename: patches/v8/build_warn_instead_of_abort_on_builtin_pgo_profile_mismatch.patch
patch: @@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Sam Attard <sattard@anthropic.com>
+Date: Sun, 22 Mar 2026 10:51:26 +0000
+Subject: build: warn instead of abort on builtin PGO profile mismatch
+
+Electron sets v8_enable_javascript_promise_hooks = true to support
+Node.js async_hooks (see node/src/env.cc SetPromiseHooks usage:
+https://github.com/nodejs/node/blob/abff716eaccd0c4f4949d1315cb057a45979649d/src/env.cc#L223-L236).
+This flag adds conditional branches to builtins-microtask-queue-gen.cc
+and promise-misc.tq, changing the control-flow graph hash of several
+Promise/async builtins. This invalidates V8's pre-generated PGO profile
+for those builtins (built with Chrome defaults where the flag is off).
+
+Rather than disabling builtins PGO entirely, warn and skip mismatched
+builtins so all other builtins still benefit from PGO.
+
+diff --git a/BUILD.gn b/BUILD.gn
+index 078b63b2bdbb3f952bd0f579e84fb691e308fb64..985f946d5f87b4e6eb32a011ac47a0073248e5f2 100644
+--- a/BUILD.gn
++++ b/BUILD.gn
+@@ -2803,9 +2803,11 @@ template("run_mksnapshot") {
+         "--turbo-profiling-input",
+         rebase_path(v8_builtins_profiling_log_file, root_build_dir),
+ 
+-        # Replace this with --warn-about-builtin-profile-data to see the full
+-        # list of builtins with incompatible profiles.
+-        "--abort-on-bad-builtin-profile-data",
++        # Electron: Use warn instead of abort so that builtins whose control
++        # flow is changed by Electron's build flags (e.g. RunMicrotasks via
++        # v8_enable_javascript_promise_hooks) are skipped rather than failing
++        # the build. All other builtins still receive PGO.
++        "--warn-about-builtin-profile-data",
+       ]
+ 
+       if (!v8_enable_builtins_profiling && v8_enable_builtins_reordering) {