Roll to V8 15.0.245.2; require &'static for CFunction overload storage - #1990
Conversation
Upstream crrev.com/c/7828135 (slated for V8 15) changes FunctionTemplateInfo to store the raw v8::CFunction pointers passed to NewWithCFunctionOverloads directly, rather than copying them into a Managed<CFunctionWithSignature> heap object. The pointed-to storage must therefore outlive every FunctionTemplate that references it - in practice this means it has to be 'static, since a FunctionTemplate can live until isolate disposal. Enforce the invariant at the Rust type level so embedders cannot pass stack-local overload storage: * FunctionBuilder::build_fast now requires &'static [CFunction]. * CFunction::new now requires &'static CFunctionInfo so the type_info pointer it caches cannot dangle. * CFunctionInfo::new now requires &'static [CTypeInfo] for arg_info for the same reason - the constructed CFunctionInfo caches arg_info.as_ptr(). The existing call sites in tests/test_api.rs and benches/function.rs already use the canonical pattern - const FAST: CFunction = ...; build_fast( scope, &[FAST]) - which Rust static-promotes to &'static [CFunction; 1], so no test changes are required. A new trybuild compile_fail test (tests/compile_fail/build_fast_local_overloads.rs) demonstrates that a runtime-built Vec<CFunction> is now rejected with E0597. Refs #1989 Closes denoland/orchid#160 Co-Authored-By: Divy Srivastava <me@littledivy.com>
|
|
|
@divybot Looks like lgkr was cut 2 days ago https://chromium.googlesource.com/v8/v8/+/refs/heads/15.0-lkgr Let's update bump v8 submodule (roll it in the repo) and use it here |
|
@littledivy I dug into rolling the submodule. Upstream I only have read access to
and push the roll onto this branch so the |
|
@divybot Go ahead with the roll on this branch:
then push so the |
|
Done — rolled in commit
CI is running now and will validate the |
|
Rolled in Root cause — the
What's needed: a The |
|
Yep please do that. Get this CI green |
|
Drove the
This fixes the Once #204 lands in |
Advance the build submodule from fffa45f2 to 2aeedfc1: the denoland chromium_build patches re-applied onto upstream build b787aa66 (the commit V8 15.0.245.2 pins in DEPS). b787aa66's BUILDCONFIG.gn uses //buildtools/third_party/libc++:all_modules instead of the removed :headers target, fixing the 'gn gen' unresolved-dependency failure on the build-from-source CI variants (ptrcomp / asan / Windows cross-compile). See denoland/chromium_build#204.
|
Bumped the Note: if #204 gets squash/rebase-merged (new SHA) rather than pushed as a branch, 2aeedfc1 could eventually be GC'd from the network — pushing it as a branch (or a normal merge) keeps the gitlink valid long-term. |
V8 15 ships Atomics.pause: Genesis::InitializeGlobal_js_atomics_pause now does a GetProperty(global, "Atomics") while bootstrapping every context. The security_token test installs a *masking* named-property interceptor on the child context's global that delegates all lookups to the parent global, so that bootstrap lookup returned the parent's Atomics (which already had pause), V8 reinstalled pause, and aborted with a duplicate-descriptor CHECK. Make the interceptor NON_MASKING so it only fires for properties absent on the global (just `variable`, which is all the test accesses). This skips already-present built-ins during bootstrap and avoids the collision while preserving the test's behavior.
|
Build-from-source CI is now healthy — Failure: Root cause: Fix: make the This is a test-only artifact — a real catch-all masking global interceptor that shadows built-ins is not something rusty_v8/Deno embedders do — so no library or V8-fork change is needed. CI is re-running now; I'll confirm green. |
|
✅ CI is green — run 27046401847 passed all 28 build/test jobs (debug+release × linux/macOS/Windows × simdutf/ptrcomp/asan). The previously-crashing The full V8 15 roll is now validated end-to-end against the
Only remaining check is |
|
Update title and desc |
|
Build dep is rolled up: |
|
Confirmed — no change needed. The This also clears the GC-reachability concern I raised earlier — the SHA is now anchored to a permanent dated branch instead of a closed PR's ref, so the gitlink stays valid long-term. CI is green (run 27046401847); only |
Review: looks good ✅Cross-checked against the prior major roll (#1940, 14.6→14.7) — conventions all match. Roll structure (matches #1940)
Code changes — correct and well-documented
CI: all 28 build/test jobs green (debug+release × linux/macOS/windows × simdutf/ptrcomp/asan). Only One non-blocking nit: the v8 submodule pin Nothing blocking — ship-ready once CLA clears. |
Same content as the previous pin 944a94aa (identical tree ff06e1a909291763a6f8526b44079551f037246a and byte-identical DEPS) — the denoland patch series was re-cherry-picked onto the same V8 15.0.245.2 base. Repinning to the branch tip so the submodule matches V8_TRACKING_BRANCH (15.0-lkgr-denoland) and tools/auto_update_v8.ts no longer sees the pin as diverged. No third_party changes.
|
Thanks for the review! Addressed the nit — repinned the Verified the repin is content-neutral before pushing:
CI is re-running against the tidied pin; I'll confirm it stays green. Only |
|
@divybot Open follow up orchid issue for upgrading this in Deno |
Summary
Rolls rusty_v8 to V8 15.0.245.2 and lands the type-level
&'static-lifetime fix for fast-APICFunctionoverload storage(#1989). The two go together: the V8 15 ABI is what makes
the lifetime fix necessary, and this PR validates that fix against real V8 15.
V8 15 roll
v8submodule →944a94aa(15.0-lkgr-denoland, V8 15.0.245.2,tag
15.0.245.2-denoland-944a94aa1735e029805d)V8_TRACKING_BRANCHintools/auto_update_v8.ts→15.0-lkgr-denolandv8/DEPS(buildtools, abseil-cpp,libc++/src, libunwind/src, llvm-libc/src, partition_alloc, rust, tools/clang,
tools/win)
buildsubmodule →2aeedfc1(Roll build patches onto upstream b787aa66 for V8 15 chromium_build#204): upstreamchromium
build@b787aa66(V8 15's DEPS pin) + the 6 denoland patches.Required because V8 15's buildtools dropped the
//buildtools/third_party/libc++:headerstarget that the oldbuildconfig injected into every GN target.
15.0.245.2fast_api: require
&'staticfor CFunction overload storageResolves #1989 by enforcing — at the Rust type level — the
storage-lifetime invariant introduced by upstream V8 change
crrev.com/c/7828135
(
[fastapi] Store v8::CFunction pointer directly in FunctionTemplateInfo,shipped in V8 15).
Before that V8 patch,
FunctionTemplate::NewWithCFunctionOverloadscopiedeach
v8::CFunctioninto aManaged<CFunctionWithSignature>heap object, sothe embedder's overload storage only needed to outlive the call. After it,
V8 retains the raw
v8::CFunction*directly insideFunctionTemplateInfoand reads it back on every fast-call dispatch, so the pointed-to storage
must outlive every
FunctionTemplatethat references it — which inpractice means
'static(templates can live until isolate disposal).Previously
FunctionBuilder::build_fastaccepted any&[CFunction]andforwarded
as_ptr()to V8, so a deno_core-style call shape likebuilder.build_fast(scope, &[fast_function])would silently dangle under theV8 15 ABI. This PR makes that misuse a compile error today instead of a
use-after-free tomorrow.
Changes
FunctionBuilder::build_fastnow takesoverloads: &'static [CFunction].fast_api::CFunction::newnow takestype_info: &'static CFunctionInfo,so the
type_info_pointer it caches cannot dangle either.fast_api::CFunctionInfo::newnow takesarg_info: &'static [CTypeInfo],same reason — the constructed
CFunctionInfocachesarg_info.as_ptr().static-promoted
constpattern.Tests
The existing fast-call call sites in
tests/test_api.rsandbenches/function.rsalready use the canonical pattern —— which Rust static-promotes to
&'static [CFunction; 1], so no fast-calltest changes are required.
A new trybuild compile_fail test
tests/compile_fail/build_fast_local_overloads.rsdemonstrates that a runtime-built
Vec<CFunction>is now rejected withE0597 — argument requires that 'overloads' is borrowed for 'static.One unrelated test needed a V8-15 adjustment:
security_token. V8 15 shipsAtomics.pause, whoseGenesis::InitializeGlobal_js_atomics_pauseinstallerruns
GetProperty(global, "Atomics")while bootstrapping every context. Thattest installed a masking named-property interceptor on the child context's
global delegating all lookups to the parent global, so the bootstrap lookup
returned the parent's
Atomics(already carryingpause); V8 reinstalledpauseand aborted with a duplicate-descriptor CHECK. Marking the interceptorNON_MASKING(so it only fires for properties absent on the global — just thevariablethe test reads) avoids the collision and preserves the test'sbehavior.
Context
buildsubmodule rebase: Roll build patches onto upstream b787aa66 for V8 15 chromium_build#204Closes denoland/divybot#160