build: drop V8 pointer compression from the iOS lite flavor - #8
Merged
Conversation
24.19.0-1 turned on --experimental-enable-pointer-compression for both lite targets. Android is fine; iOS lite cannot start at all, on any physical device. V8 needs the 4GB cage to be 4GB-aligned as well as 4GB long, and gets the alignment by over-reserving and trimming: OS::Allocate requests size + (alignment - page_size), one PROT_NONE mmap of just under 8GB. An iOS process without the extended-virtual-addressing entitlement is capped well below that -- 7.375GB of usable address space on devices with more than 3GB of RAM, less below that, once PAGE_ZERO and the shared region are subtracted. The reservation is larger than the whole address space of the process, so InitReservation fails and IsolateGroup::Initialize calls FatalProcessOutOfMemory during Isolate init. The app aborts about a second into launch, before any embedder JS runs. The entitlement would lift the cap, but a runtime library cannot require it: it is a restricted capability each consuming app has to carry in its own provisioning profile, and it would still spend 4GB of address space per isolate. Nothing caught this because the flavor never runs on a physical iPhone: real-device-smoke-ios fetches the nodejs-mobile-ios artifact, which is the full flavor, and the lite legs are simulator-only. A simulator is a macOS process with no such cap, so it exercises none of this. iOS lite therefore goes back to the upstream-standard V8 ABI, and the -DV8_COMPRESS_POINTERS build note for addons now applies to Android lite alone. Android lite is untouched.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
24.19.0-1 turned on
--experimental-enable-pointer-compressionfor both lite targets. Android is fine. iOS lite cannot start at all — the app aborts about a second into launch, on every physical device, before any embedder JS runs. This drops the flag on iOS only; Android lite is untouched.Why it cannot work on iOS
V8 needs the cage to be 4 GB-aligned as well as 4 GB long, and it gets the alignment by over-reserving and trimming.
OS::Allocate(deps/v8/src/base/platform/platform-posix.cc) requestssize + (alignment - page_size)— a singlePROT_NONEmmapof just under 8 GB — then unmaps the misaligned head and tail.An iOS process does not have 8 GB of address space to give. Without the
com.apple.developer.kernel.extended-virtual-addressingentitlement the kernel caps a process at 7.375 GB usable on devices with more than 3 GB of RAM, and less below that, afterPAGE_ZEROand the shared region are subtracted (the arithmetic, with the kernel constants). The request is larger than the entire address space of the process, so it fails on every device — not marginally, and not only on small ones.VirtualMemoryCage::InitReservationreturns false andIsolateGroup::InitializecallsFatalProcessOutOfMemory(... "Failed to reserve virtual memory for process-wide V8 pointer compression cage"), which aborts duringIsolateinit.The entitlement would lift the cap, but a runtime library cannot require it: it is a restricted capability every consuming app would have to carry in its own provisioning profile, and it would still spend 4 GB of address space per isolate. Shipping iOS lite uncompressed is the cheaper trade.
I ruled out the two other candidates. Jitless means no
CodeRangeis ever created (Isolate::RequiresCodeRange()iskPlatformRequiresCodeRange && !jitless_), so the missing JIT entitlement is not involved; andv8_enable_sandboxis 0 in both builds, so the sandbox reservation is not either. Diffing theprocess.configembedded in the shippedios-arm64slices of 24.19.0-0 and 24.19.0-1, the only delta is pointer compression and its two implied knobs (v8_enable_31bit_smis_on_64bit_arch,v8_enable_external_code_space).How it showed up
Downstream, in
comapeo-core-react-native's BrowserStack e2e suite. Every flow failed at the first assertion on both an iPhone 15 (iOS 17.3) and an iPhone 17 (iOS 26.5), across three merge-queue attempts and their internal retries; BrowserStack reportsapp_crash: trueand the device log shows the kernel taking a corpse a second after launch. Android e2e passed on the same commits.Why CI was green
The lite flavor never runs on a physical iPhone.
real-device-smoke-iosfetches thenodejs-mobile-iosartifact — the full flavor — and the lite legs (curated-tests-ios) are simulator-only. A simulator is a macOS process with no such cap, so it exercises none of this and passes on a binary that cannot start on any device.Worth fixing separately: pointing the iOS device smoke at the lite artifact, or adding a lite leg, would have caught this at #6. I have not bundled that here to keep the revert reviewable.
Changes
tools/ios_framework_prepare.shdrops the flag fromLITE_FLAGS.BUILDING.mdrescopes the pointer-compression section to Android and documents the iOS constraint (including that iOS simulator green is no evidence about address-space behaviour). TheFAQ.mdaddon note — add-DV8_COMPRESS_POINTERS -DV8_31BIT_SMIS_ON_64BIT_ARCH— now applies to Android lite alone; iOS lite is back on the upstream-standard V8 ABI.expected-tree.txtre-anchored to7c521dbc, verified by a cleanscripts/prepare.shrun.