Skip to content

fix(ffi): double-free segfault with symbols object - #919

Merged
Jarred-Sumner merged 1 commit into
oven-sh:mainfrom
sno2:fix/ffi-segfault
Jul 30, 2022
Merged

Jarred-Sumner merged 1 commit into
oven-sh:mainfrom
sno2:fix/ffi-segfault

Conversation

@sno2

@sno2 sno2 commented Jul 30, 2022

Copy link
Copy Markdown
Contributor

I believe this might have been what was causing some people to face segfaults with FFI. I sadly didn't catch this one in #793

@sno2
sno2 requested a review from Jarred-Sumner July 30, 2022 00:42
@Jarred-Sumner
Jarred-Sumner merged commit 3d6d265 into oven-sh:main Jul 30, 2022
@sno2
sno2 deleted the fix/ffi-segfault branch July 30, 2022 00:44
sosukesuzuki pushed a commit that referenced this pull request Oct 30, 2026
Fixes #44697

### Problem
- Bun's JavaScriptCore is 360 upstream commits behind
WebKit/WebKit@e8f704815e94. 59 touch JavaScriptCore, WTF or bmalloc.
- `RegExp.lastMatch` after a `test()` that matched can end the process:
`panic(main thread): Segmentation fault at address 0x4`.
- Two results are wrong: `Math.sumPrecise([-1])` is
`-1.0000000000000002`, and an async function that awaits itself through
`Promise.all` repeats its frame in `Error.stack`.

### Fix
- `WEBKIT_VERSION` is a7b59e61de2e, the merge commit of
oven-sh/WebKit#923: the engine of `main` plus the upstream merge.
- Upstream deleted one builtin: in `test/aot/engine-tests`, 2,648
builtin numbers are one lower and 19 instance offsets eight bytes lower.
Loop bytecode changes, so `bundler_bytecode_portable.test.ts` has new
snapshots.
- **Two test bounds go up, which needs a maintainer's yes**: the
`--trim` size in `compile-aot-size.test.ts` and the function count of
one program (Notes).
- Verified, local debug build:
`test/js/bun/jsc/webkit-upgrade-e8f704815e.test.ts` (new, 17 cases, Bun
1.4.3-canary fails 4) and
`test/js/bun/jsc/regexp-legacy-static-properties.test.ts` (new, the
panic on Bun 1.4.3-canary). `test/aot/engine-tests` passes with a
release `testaot`.

### Background
- `WEBKIT_VERSION` (`scripts/build/deps/webkit.ts`) names the
oven-sh/WebKit release whose JavaScriptCore the build downloads.
- The ahead-of-time compiler numbers the engine's JavaScript builtins by
name order, and the instance of a compiled program has one word per
link-time constant.

### Downsides
- Size: hello world with `--aot --trim` maps 167,808 bytes more. A
compiled program that calls `Array.from` holds 22 functions, was 6.
- A thread that breaks the collector's stop-the-world protocol now
crashes a release build (Notes).
- The own keys of the `Proxy.revocable` revoke function now start with
`length` and `name`.

<details><summary>Notes</summary>

#### The WebKit side

oven-sh/WebKit#923 merges upstream `e8f704815e94` into the fork. Its
description lists the 16 conflicts and how each one is resolved.

The first CI run of that pull request built every lane and published a
preview release. Its test jobs failed for three reasons. None of them is
in the libraries that Bun links:

- Upstream now links its programs with `-z pack-relative-relocs`
(WebKit/WebKit@c47b7c073c). The `jsc` and `testFFI` programs of the
Linux lanes then need glibc 2.36. The arm64 test runner has glibc 2.35.
- One new upstream test
(`stress/regexp-legacy-static-properties-rematch-failure.js`) cannot
pass in two test modes that only the fork has.
- Upstream deleted one JavaScript builtin. The tests of the
ahead-of-time compiler name builtins by number, and the numbers behind
the deleted one moved.

That pull request has a commit for each of them. After that, the fork's
`main` got oven-sh/WebKit#914, #886 and #926, and Bun's `main` got the
ahead-of-time compiler (#45631) with that WebKit (#47125). Both are
merged in, over there and here.

A review of the merged head found one defect of the merge itself: with
the object loop of `JSON.parse` that upstream rewrote, `Bun.JSONL` could
give an object a Structure that a collection had freed. `bcd362b31e`
over there repairs it and adds a stress test. With the `jsc` of the
build before it, that test ends in `SIGSEGV` in 6 runs of 6.

The fork's `main` then moved three more times, and each time its Bun
side had to be on Bun's `main` before this branch could pin a build with
it:

| oven-sh/WebKit `main` | Bun side | merged into oven-sh/WebKit#923 at |
|---|---|---|
| #927 | #47129 | `be93e08e36` |
| #930 | #47129 | `35b64c4afb` |
| #919, #936 (ICU 79.1), #937 | #47281 | `b67a0b1a3a` |

- `780dc90982` over there turns upstream's fast path for `{ ...fn }` off
in builds with the ahead-of-time compiler (see "What Bun's CI showed").
- oven-sh/WebKit#923 is merged as `a7b59e61de`, and `WEBKIT_VERSION` is
that commit. It has the same tree as `b67a0b1a3a`, the head whose
preview build (`autobuild-preview-pr-923-b67a0b1a`) this branch pinned
before. That is `8c6c963e3c`, which `main` pins since #47281, plus the
upstream merge. The CI of oven-sh/WebKit#923 was green at that head: 84
jobs, with `testFFI`, `TestWTF`, `testaot` and
`run-javascriptcore-tests` on Linux x64 and arm64.
- A build of this branch against an engine whose Bun side is not on
`main` does not work. With the preview of `780dc90982` and `main` before
#47129, the build stopped at
`src/jsc/bindings/BunCompiledModules.cpp:756` (`too few arguments to
function call`, `JSC::AOT::tryReservePagesForNewThread`), and with that
call changed every `bun build --compile --aot` ended with
`IdOutOfRange`.

The release zip sizes of an earlier version of this description compared
builds 133970 and 133646: between -0.15% and +0.12% over the 12 release
zips (`bun-linux-x64.zip` -38,546 bytes).

#### What Bun's CI showed

The head is `e22cf6a525` now. On top of `3688162c4c` it has the pin of
the merge commit, the test for #44697 and one corrected comment. The
engine source is the same as in build 135015.

**Build 135015** ran `3688162c4c`, the head with the answers below. 184
of its 188 jobs passed and none failed: every build, and every test job
on Linux, Windows and macOS on ARM64. The four macOS x64 test jobs had
not started when this was written. No agent of that queue was free, and
three attempts of each job expired after an hour of waiting. Four tests
failed once and passed on a retry or alone (`bun-serve-html.test.ts`,
`no-leak-records-at-exit.test.ts`, `hot.test.ts`,
`process-stdin.test.ts`).

**Build 134977** ran the head before that, with `main` up to #47129 and
the preview of `35b64c4afb`. Three things failed that do not pass on a
retry. `3688162c4c` answers each:

| Test | Failure | Answer |
|---|---|---|
| `test/aot/engine/ir-1`, `ir-3`, `ir-5`, `ir-6` (nine `.ir` files,
Linux x64) | `lower-to-b3: output line 7 does not match: Int64 b@22 =
Load(b@10, offset = 8264, ..); nearest: .. offset = 8256 ..` | The
offsets are written anew (see "The engine tests") |
|
`test/aot/parallel/arrays/searches-folds-and-flat-maps-of-a-list-bring-in-only-the-functions-that-do-them.js`
| `ImageFunctionsEmitted <= 40, but the build counted 42` | The bound is
48. **A maintainer has to agree** |
| `test/bundler/compile-aot-size.test.ts` | hello world with `--trim`
maps 25,777,292 bytes, and the bound is 25,700,000 | The bound is
25,880,000. **A maintainer has to agree** |

Eight more tests failed and passed on a retry or alone
(`plugin-requests-run-ahead.test.ts`, `no-leak-records-at-exit.test.ts`,
`compile-aot-run-time.test.ts`, `43831.test.ts`, `filesink.test.ts`,
`process-stdin.test.ts`, `body.test.ts`, `test-cluster-shared-leak.js`).

**The function count.** The program calls `Array.from({ length: 16 })`
and six array methods. Its executable holds 24 functions with the canary
of `main` and 42 here.

- Upstream's `Array.from` (WebKit/WebKit@37aa2b5bd94d) steps an iterator
by a call of its `next` and closes it by a call of its `return`. The old
text was a `for-of` loop.
- One function of the library runs for every call of `Array.from`, so
the compiler keeps what that call of `next` can reach by name. The 18
more functions are the two helpers `iteratorGenericNext` and
`iteratorGenericClose`, one part of `Array.from` that is moved out of
line, and the `next`, `return` and `throw` of array iterators,
generators, iterator helpers and wrapped iterators.
- A one-line `console.log(Array.from([1, 2, 3], x => x + 1).join())`
holds 22 functions where `main` holds 6. Its bound is 24.
- #47316 expands the two helpers in line in the front end
(its engine half is oven-sh/WebKit#934). A release build of it keeps 25
functions for this program and 7 for the one-line program, so the bound
of 40 holds again once that pull request is on `main`. The bound of 48
is needed only until then.

**The size.** `test/bundler/compile-aot-size.test.ts`, Linux x64 with
glibc. Build 135015 is the commit of the canary plus this upgrade:

| hello world | canary of `main` (`081ace731d`) | build 135015 | bound |
|---|---|---|---|
| `--aot` | 68,138,180 | 68,305,988 | 68,440,000 |
| `--aot --trim` | 25,584,836 | 25,752,644 | 25,700,000, now 25,880,000
|

Both grow by 167,808 bytes. `.text` of `jsc` grows by 143,376 bytes with
the 360 upstream commits. The test says that its bounds only go down, so
this is a maintainer's call. The new bound has about the slack the old
one had (127,356 bytes, it was 115,164). The comment beside it says
183,000 bytes, which was measured on an older commit of `main`. The next
push corrects it to 168,000.

**Earlier runs** (builds 134164 and 134232, before #47129, with the test
names of that time) showed two more causes. Both are answered on the
WebKit side:

- A stack frame after `{ ...fn }`. Bun names a frame by the own property
`name` of the callee first, and by `displayName` after it. A copy that
looks every key up makes `name` a property of a function. Upstream
WebKit/WebKit@e04a6f9faecf copies from a function by its Structure and
leaves `name` alone, and the run time of compiled programs still looks
the keys up. Three programs printed another frame compiled than plain. A
maintainer chose to turn upstream's fast path off in builds with the
ahead-of-time compiler (`780dc90982` of oven-sh/WebKit#923). With a
local debug build of this branch,
`errors/frames-functions-display-name-statement.js`,
`errors/frames-functions-given-display-name-far.mjs` and
`errors/names-frames-new-function-objects-names.mjs` print the same
compiled and plain. The cost: `{ ...fn }` does not get upstream's
speedup (160 ms against 50 ms on
`JSTests/microbenchmarks/object-spread-function.js`).
- `Array.from` in a compiled program held 441 functions. The flow
analysis took the call of `next` inside the helper `iteratorGenericNext`
for a call of a value nobody knows. oven-sh/WebKit#930 changed that
rule, and 22 functions are left (above).

Build 134164 also showed a crash under collector stress (`SIGSEGV` at
address 0 in `WTF::findAtomBeforeAdding`). Its cause was on `main` too:
`AOT::nameOfBuiltin()` makes an atom while a collection ends, where
`Heap::pruneDeadReferences()` has set the atom table of the thread to
null.

#### The engine tests

`test/aot/engine-tests` has the IR text tests of the engine that need
entries of Bun's table of builtins (1,601 files since #47129).

- A test names a builtin that is written in JavaScript by its runtime
function number. Upstream WebKit/WebKit@37aa2b5bd94d deleted
`defaultAsyncFromAsyncIteratorWithNext`, which was number 23. Every
number from 24 on is one lower: 2,648 numbers in 371 files. `every` is
30 (was 31), `find` 34, `from` 46, `map` 64 and `some` 88. The numbers
of Bun's own functions start at 0x10000 and do not move. No file names a
number that the engine's list does not have.
- The instance of a compiled program holds one word for every link-time
constant of the engine, and the deleted builtin was one. Every field
behind that list is eight bytes lower. Nine tests check the B3 of a
function line by line and had such offsets in 19 lines (8040, 8168,
8192, 8216, 8264). `test/aot/tools/update-ir-tests.ts` wrote them anew
with a release `testaot` on Linux x64, and nothing else in those files
changed.
- With a release `testaot` and `jsc` built from this branch, `testaot
run test/aot/engine-tests` passes: 1,599 files, 2 todo.
- oven-sh/WebKit#923 makes the same change of numbers in the engine's
own tests.

#### The new test file

`test/js/bun/jsc/webkit-upgrade-e8f704815e.test.ts` has 17 cases. Four
of them fail on Bun 1.4.3-canary, because the engine changes there:

| Case | Old engine | New engine |
|---|---|---|
| `Math.sumPrecise([-1])` | `-1.0000000000000002` | `-1` |
| Own keys of the revoke function of `Proxy.revocable`, after `length`
is deleted and defined again, against those of an arrow function after
the same steps | another order (`name`, `length`) | the same order
(`length`, `name`) |
| `Error.stack` of an async function that awaits its own promise through
`Promise.all` | the frame repeats | one frame |
| `[x, y].sort(boundComparator)` when the comparator leaves optimized
code (the program of oven-sh/WebKit#885) | the caller gets
`Array.prototype.sort` itself | the caller gets the sorted array |

The other 13 cases pass on both engines. They cover the code that the
merge rewrote by hand: spread and rest of a function, the iterator
protocol of `Array.from`, `Object.groupBy`, `Map.groupBy` and the
iterator helpers, `Array.fromAsync`, `Array.prototype.join`,
`JSON.parse` of objects with the same keys (also `-0`, invalid input and
a reviver), `Bun.JSONL.parseChunk` cut at every position, loops that end
in a null test or a negated comparison, and an anchored RegExp and a
`switch` on a substring.

#### The bytecode snapshots

`test/bundler/bundler_bytecode_portable.test.ts` compares a hash of the
serialized bytecode. 22 entries come from a local debug build with the
merged engine. The entry `bun build --bytecode libraries.js` comes from
CI: the bundle of that entry differs on the machine the other values
come from. All ten test platforms of build 133970 reported the same
value for it, and accepted the other 22.

#### Bun's CI on the first preview build

Build 133970 ran this branch with `autobuild-preview-pr-923-b6e34894`.
One test failed on every platform: the snapshot entry above, which had
its old value then. Eight other tests failed and passed on a retry
(`bake.test.ts`, `hot.test.ts`, `no-orphans.test.ts`,
`spawn_waiter_thread.test.ts`, `test-zlib-invalid-input-memory.js`,
`nth-anplusb-ident.test.ts`, `process.test.js`, `bun.test.ts`).

The zip sizes in "The WebKit side" compare the release zips of that
build with those of build 133646, which is `main` at the commit this
branch started from. The range is over the 12 release zips. The unpacked
binaries were not measured: the artifact store of CI is not reachable
from the machine this was written on.

#### The crash of #44697

`test()` records only where the match is. A read of `RegExp.lastMatch`,
`RegExp.$1` or another legacy static property runs the match again for
the captures. That second run can need more stack than the first, and
when it failed, `RegExpGlobalData::getBackref` read through a null
pointer. Upstream WebKit/WebKit@191803bb2304, which is in this range,
throws a `RangeError` there.

```sh
BUN_JSC_maxRegExpStackSize=65536 bun -e '
  const re = new RegExp("^" + "(z)?".repeat(8) + "(?:a|b)+$");
  console.log(re.test(Buffer.alloc(100000, "a").toString()));
  console.log(RegExp.lastMatch.length);'
```

- Bun 1.4.3-canary: `true`, then `panic(main thread): Segmentation fault
at address 0x4`.
- A debug build of this branch: `true`, then `RangeError: Out of
memory`, also for `RegExp.$1`, `RegExp.$9`, `RegExp["$&"]` and
`RegExp.lastParen`.

`test/js/bun/jsc/regexp-legacy-static-properties.test.ts` runs the
program of upstream's stress test in a child with
`BUN_JSC_maxRegExpStackSize=65536` and compares every line that the
child prints: `matched: true` for the first `test()`, a `RangeError` for
each read and for an assignment to `RegExp.input`, and the values of the
properties after the next match. `USE_SYSTEM_BUN=1 bun test` fails it
with the panic, and `bun bd test` passes it. The test comes from #47160,
which had the upstream commit alone (oven-sh/WebKit#929, closed now).

#### What ran locally

- With the pin of the merge commit, a debug build with ASAN:
`webkit-upgrade-e8f704815e.test.ts` passes 17 of 17, and
`regexp-legacy-static-properties.test.ts` passes.
- `bun run build:local` against the merged WebKit (Debug, no ASAN). `-p
'42'` prints `42`.
- `test/js/bun/jsc`: 215 pass. Two `domjit.test.ts` cases pass their 20
s limit in this Debug build. The same two take 42 s on a debug build of
`main`.
- `test/js/bun/jsonl`, the worker tests, the GC tests and the heap
snapshot tests pass.
- `JSType.h`, `OptionsList.h`, the WebCore bindings scripts and the
structured clone sources have no upstream change in this range.
`src/jsc/JSType.rs` needs no change.

#### The three assertion commits

WebKit/WebKit@0bf94cf0c1, WebKit/WebKit@4bc9ad4d7f and
WebKit/WebKit@cf89f1571e check the bits of `Heap::m_worldState` with
`RELEASE_ASSERT`, in the functions through which a thread takes or gives
up its access to the heap. Bun gives up heap access while the event loop
waits (`Bun__JSC_onBeforeWait`) and takes it again after the wait. That
order is the one the assertions check.

#### Upstream changes

Range:
[`f59345e04a8d`](WebKit/WebKit@f59345e)
(2026-10-22) ..
[`e8f704815e94`](WebKit/WebKit@e8f7048)
(2026-10-27). **59** of the 360 upstream commits touch
`Source/JavaScriptCore`, `Source/WTF` or `Source/bmalloc`. 20 of the 59
change nothing that a JSCOnly build compiles: they touch a preferences
yaml, a sandbox profile, the Xcode project, or code for Swift, GLib or
Cocoa only.

### Highlights

- **`JSON.parse` reads the keys it already knows in a loop of their
own**
([`6f5f583b55`](WebKit/WebKit@6f5f583b55)). A
key found in `JSONCache`'s name table, and a value that is a cached
string or an integer of at most nine digits, are read through a local
cursor. The lexer is only used for the other values. Upstream measures
1.13x on its JSON benchmarks (geometric mean), up to 1.32x.
- **Object spread and rest of a function take the fast path**
([`e04a6f9fae`](WebKit/WebKit@e04a6f9fae)): `{
...fn }` and `let { a, ...rest } = fn` are 5x faster. PostCSS does this
once per `LazyResult`.
- **`Array.from`, `%TypedArray%.from`, `Object.groupBy`, `Map.groupBy`
and `Iterator.prototype.flatMap/some/every/find` drive the iterator
themselves**
([`37aa2b5bd9`](WebKit/WebKit@37aa2b5bd9)).
They no longer build a wrapper object for a `for-of` loop: 1.1x to 1.6x
on the `Array.from` microbenchmarks.
- **`Proxy.revocable` is 2.9x faster**
([`fad04e2527`](WebKit/WebKit@fad04e2527)).
The revoke function is a `JSFunctionWithFields` with a cached
executable, and the result object has a cached Structure. The class
`ProxyRevoke` is gone.
- **Loop conditions are one instruction more often**
([`bd50166362`](WebKit/WebKit@bd50166362)). A
null test or a negated compare that feeds a backward conditional jump is
fused into the jump (`jneq_null`, `jnless`, ...). No opcode is new, but
the bytecode of most loops changes.
- **The RegExp first-character filter reads substring ropes in place**
([`b92d6a6bea`](WebKit/WebKit@b92d6a6bea)),
and `String#match` with a constant anchored RegExp uses the filter in
the DFG. The same commit makes DFG/FTL `switch` on a substring rope read
the width of the base string, not the bit cached in the rope.
- **Two DFG/FTL and Wasm miscompile fixes**: an OSR exit in a bound
`Array#sort` comparator returned past the `sort` call
([`f274ef4c03`](WebKit/WebKit@f274ef4c03)),
and a cross-instance Wasm tail call copied its frame from one
`restoreFrameSize` too low
([`0927910cf9`](WebKit/WebKit@0927910cf9)).
- **The GC asserts its stop-the-world protocol in release builds**
([`0bf94cf0c1`](WebKit/WebKit@0bf94cf0c1),
[`4bc9ad4d7f`](WebKit/WebKit@4bc9ad4d7f),
[`cf89f1571e`](WebKit/WebKit@cf89f1571e)). A
mutator that takes or gives up heap access in a state the protocol does
not allow crashes now.
- **`Math.sumPrecise` is correct for negative sums**
([`8ee560d748`](WebKit/WebKit@8ee560d748)):
`Math.sumPrecise([-1])` was `-1.0000000000000002`.

### Runtime & builtins

- [`e04a6f9fae`](WebKit/WebKit@e04a6f9fae)
([328286](https://bugs.webkit.org/show_bug.cgi?id=328286)):
`@copyDataProperties` and `@cloneObject` accept a `JSFunction` source on
the path that reads the Structure, through the new
`JSFunction::canPerformFastEnumerablePropertyEnumeration(VM&)`. It needs
an unmodified `name` and `length`, no accessors and no own `__proto__`.
object-spread-function 4.99x, object-rest-function 5.54x.
- [`37aa2b5bd9`](WebKit/WebKit@37aa2b5bd9)
([328563](https://bugs.webkit.org/show_bug.cgi?id=328563)): Five builtin
files call `@iteratorGenericNext` in a `for (;;)` loop and close the
iterator with `@ifAbruptCloseIterator`. The link-time constant
`defaultAsyncFromAsyncIteratorWithNext` is removed, and
`defaultAsyncFromAsyncIterator` has its body now.
- [`fad04e2527`](WebKit/WebKit@fad04e2527)
([328635](https://bugs.webkit.org/show_bug.cgi?id=328635)):
`Proxy.revocable`: see Highlights. Removed: `ProxyRevoke.{h,cpp}`,
`ProxyRevokeInlines.h`, `proxyRevokeSpace`,
`JSGlobalObject::proxyRevokeStructure()`. Added:
`proxyRevocableResultStructure()`, `VM::proxyRevokeExecutable()`,
`JSFunctionWithFields::Field::RevocableProxy`, the identifiers `proxy`
and `revoke`. Observable: the own keys of the revoke function list
`length` and `name` first, like any function.
- [`e81441a5ec`](WebKit/WebKit@e81441a5ec)
([328769](https://bugs.webkit.org/show_bug.cgi?id=328769)):
`JSOnlyStringsAndInt32sJoiner` is renamed `JSExactLengthJoiner`.
`Array#join` keeps its exact-length path for arrays that also hold
booleans, `undefined` or `null`.
- [`8ee560d748`](WebKit/WebKit@8ee560d748)
([315450](https://bugs.webkit.org/show_bug.cgi?id=315450)):
`WTF::Xsum::XsumSmall::compute()` rounded a negative sum away from zero
when it must not. `Math.sumPrecise([-Number.MAX_VALUE])` was
`-Infinity`.
- [`071ce01fcb`](WebKit/WebKit@071ce01fcb)
([328147](https://bugs.webkit.org/show_bug.cgi?id=328147)):
`Interpreter::getAsyncStackTrace` stops at the second visit of a promise
combinator. An async function that awaits its own promise through
`Promise.all` no longer repeats its frame up to `Error.stackTraceLimit`,
or hangs.
- [`be583048f3`](WebKit/WebKit@be583048f3)
([328788](https://bugs.webkit.org/show_bug.cgi?id=328788)):
`Identifier::add` no longer does one atomic ref and one deref of the
`AtomStringImpl` it returns.
- [`ca48e0119c`](WebKit/WebKit@ca48e0119c)
([328786](https://bugs.webkit.org/show_bug.cgi?id=328786)): The last two
`USE(BIGINT32)` blocks are deleted. Dead code.

### Parser / bytecode generator

- [`bd50166362`](WebKit/WebKit@bd50166362)
([328623](https://bugs.webkit.org/show_bug.cgi?id=328623)):
`emitJumpIfTrue` and `emitJumpIfFalse` no longer require a forward
target for their fusions. `while (node != null)` and `do {} while (!(a <
b))` end in one fused jump. The subject names only the null tests. The
diff also covers the ten negated compares.
- [`4e5e850636`](WebKit/WebKit@4e5e850636)
([328770](https://bugs.webkit.org/show_bug.cgi?id=328770)):
`BytecodeGeneratorBase<Traits>` is folded into `BytecodeGenerator`.
`GenericLabel` and `GenericBoundLabel` are the plain classes `Label` and
`BoundLabel`, and `Label::bind` takes the instruction writer.
`BytecodeGeneratorBase.h` is deleted and
`BytecodeGeneratorBaseInlines.h` is renamed
`BytecodeGeneratorInlines.h`. `BytecodeList.rb` loses the unused type
`:WasmBoundLabel`, and no opcode.

### DFG / FTL

- [`f274ef4c03`](WebKit/WebKit@f274ef4c03)
([327983](https://bugs.webkit.org/show_bug.cgi?id=327983)): An inlined
bound function keeps the call kind of its caller.
`InlineCallFrame::BoundFunctionCall` and `BoundFunctionTailCall` are
removed. A bound comparator inlined into `Array#sort` is an
`ArraySortComparatorCall`, so an OSR exit inside it restarts the `sort`.
A recursive tail call through a bound function can become a jump in the
FTL.
- [`b92d6a6bea`](WebKit/WebKit@b92d6a6bea)
([328389](https://bugs.webkit.org/show_bug.cgi?id=328389)): See
Highlights. `compileRegExpMatchFast` (DFG) returns `null` without a call
when the first byte cannot start a match.

### RegExp

- [`59e81f3e12`](WebKit/WebKit@59e81f3e12)
([328828](https://bugs.webkit.org/show_bug.cgi?id=328828)): A match
array gets `index`, `input`, `groups` and `indices` written into its
butterfly before the array cell exists.
`tryCreateUninitializedRegExpMatchesArray` has a fifth parameter, and
`JSArray::tryCreateUninitializedRestrictedButterfly` is new.
- [`1984003fd9`](WebKit/WebKit@1984003fd9)
([328895](https://bugs.webkit.org/show_bug.cgi?id=328895)): On x86_64
the Yarr JIT copies fewer than 16 `ParenContext` frame slots with
straight-line code, and eight per loop iteration above that.
regexp-parencontext-frame-slots 1.80x.
- [`191803bb23`](WebKit/WebKit@191803bb23)
([328417](https://bugs.webkit.org/show_bug.cgi?id=328417)):
`RegExp.lastMatch`, `RegExp.$1` and the other legacy properties throw a
`RangeError` when the lazy re-match fails. Before, they read a null
array.

### JSON

- [`6f5f583b55`](WebKit/WebKit@6f5f583b55)
([328615](https://bugs.webkit.org/show_bug.cgi?id=328615)): See
Highlights. The object branch of `LiteralParser::parseRecursively` is
one loop with the lambdas `parseValue`, `putWithTransition` and
`finishObject`. `Lexer::skipWhitespaceBeforeKey()` is removed,
`Lexer::setPtr()` and `end()` are new, and `numberOfDigitsForSafeInt32`
moves to `ParseInt.h`.
- [`2dff3f1dbf`](WebKit/WebKit@2dff3f1dbf)
([329046](https://bugs.webkit.org/show_bug.cgi?id=329046)): Compile fix
for the commit above with clang 20: three lambdas capture `vm` by name.

### GC / heap

- [`0bf94cf0c1`](WebKit/WebKit@0bf94cf0c1)
([328987](https://bugs.webkit.org/show_bug.cgi?id=328987)):
`Heap::stopTheMutator` asserts that no mutator holds the conn, where it
had a branch that returned false.
- [`4bc9ad4d7f`](WebKit/WebKit@4bc9ad4d7f)
([329005](https://bugs.webkit.org/show_bug.cgi?id=329005)):
`Heap::resumeTheMutator` asserts that the mutator is stopped, has no
heap access and no conn. It returned early when the mutator was not
stopped.
- [`cf89f1571e`](WebKit/WebKit@cf89f1571e)
([329038](https://bugs.webkit.org/show_bug.cgi?id=329038)): Release
asserts on `Heap::m_worldState` in `acquireAccessSlow`,
`releaseAccessSlow`, `setNeedCollectionEpilogue`, `setMutatorWaiting`,
`clearMutatorWaiting`, `Collector::beginCollectionInEachHeap`,
`finishChangingPhase` and `stopThePeriphery`.
`Collector::requestCollection` gets two debug asserts.
`Heap::needCollectionEpilogue()` is new.

### WebAssembly

- [`0927910cf9`](WebKit/WebKit@0927910cf9)
([329002](https://bugs.webkit.org/show_bug.cgi?id=329002)):
`Wasm::emitRestoreInstanceFrameIfNeeded` starts its copy at the stack
pointer from before the adjustment.

### WTF

- [`45f193ae80`](WebKit/WebKit@45f193ae80)
([328940](https://bugs.webkit.org/show_bug.cgi?id=328940)):
`Thread::tryCreate()` returns null when the thread cannot be created.
`Thread::create()` calls it and still crashes. `$.agent.start` in the
`jsc` shell throws.
- [`e8f704815e`](WebKit/WebKit@e8f704815e)
([329066](https://bugs.webkit.org/show_bug.cgi?id=329066)): The defaults
of `LOG_DISABLED`, `ASSERT_MSG_DISABLED`, `ASSERT_ARG_DISABLED`,
`BACKTRACE_DISABLED`, `FATAL_DISABLED` and `ERROR_DISABLED` move from
`Assertions.h` to `PlatformEnable.h`.
- [`bbfbc41dc9`](WebKit/WebKit@bbfbc41dc9)
([327419](https://bugs.webkit.org/show_bug.cgi?id=327419)): The
`RELEASE_LOG*` macros are defined once, on top of a
`WTF_RELEASE_LOG_SEND` per backend. `LOGF`, `SD_JOURNAL_SEND` and
`LOG_ANDROID_SEND` are removed.
- [`3757158274`](WebKit/WebKit@3757158274)
([328861](https://bugs.webkit.org/show_bug.cgi?id=328861)):
`allowCompactPointers<T>()` looks at the `AllowCompactPointers<T*>`
specialization first.
`WTF_ALLOW_COMPACT_POINTERS_TO_INCOMPLETE_TYPE(JSC::JSCell)` moves from
`MicrotaskQueue.h` to `JSCJSValue.h`.
- [`2b85a5e547`](WebKit/WebKit@2b85a5e547)
([328859](https://bugs.webkit.org/show_bug.cgi?id=328859)):
`printInternal(PrintStream&, String&)` is defined in `PrintStream.cpp`,
not inline.
- [`38418ba096`](WebKit/WebKit@38418ba096)
([328643](https://bugs.webkit.org/show_bug.cgi?id=328643)):
`NeverDestroyed` and `LazyNeverDestroyed` read their storage through
`std::launder`.
- [`701620c269`](WebKit/WebKit@701620c269)
([328791](https://bugs.webkit.org/show_bug.cgi?id=328791)):
`Vector::appendRange(Range&&)` for a sized range. The rest of the commit
is WebCore.
- [`272972fe8c`](WebKit/WebKit@272972fe8c)
([328652](https://bugs.webkit.org/show_bug.cgi?id=328652)):
`WTF::initializeObjectIdentifierDomain()`. Only WebKit's GPU process
calls it.
- Fixes in headers that nothing in JavaScriptCore uses:
[`961981e9e8`](WebKit/WebKit@961981e9e8)
(`MediaTime` ordering),
[`2c813011e9`](WebKit/WebKit@2c813011e9)
(`WeakListHashSet` const iterator),
[`3e90cc907c`](WebKit/WebKit@3e90cc907c)
(`LoggingHashMap`),
[`474bb3fa62`](WebKit/WebKit@474bb3fa62)
(`BitSet::setEachNthBit` asserts `n`).

### bmalloc / libpas

Bun's JavaScriptCore allocates through mimalloc, and the ASAN builds
through the system allocator, so none of these changes what a shipped
`bun` does.

- [`c8ce68fbaa`](WebKit/WebKit@c8ce68fbaa)
([328247](https://bugs.webkit.org/show_bug.cgi?id=328247)): Each page
config of a heap has its own minimum of objects per page.
`PAS_MIN_OBJECTS_PER_PAGE` is renamed
`PAS_DEFAULT_MIN_OBJECTS_PER_PAGE`, and `PAS_MAX_OBJECT_SIZE` takes the
minimum as an argument.
- [`37e9021372`](WebKit/WebKit@37e9021372)
([328674](https://bugs.webkit.org/show_bug.cgi?id=328674)): Medium
segregated pages take objects up to 18432 bytes (from 11776).
- [`ad3ad2c6ea`](WebKit/WebKit@ad3ad2c6ea)
([328277](https://bugs.webkit.org/show_bug.cgi?id=328277)): Free small
segregated pages stay committed 450 ms longer (900 ms on macOS).
- [`1ae8574624`](WebKit/WebKit@1ae8574624)
([328282](https://bugs.webkit.org/show_bug.cgi?id=328282)): Four more
size classes in the designated intrinsic heap: 112, 144, 272 and 384
bytes.

### Build system

- [`9c5e8c5fc1`](WebKit/WebKit@9c5e8c5fc1)
([328481](https://bugs.webkit.org/show_bug.cgi?id=328481)): CMake Debug
builds compile bmalloc and `FastMalloc.cpp` with `-O3`, except with MSVC
and clang-cl.
- [`3c41f3fb2f`](WebKit/WebKit@3c41f3fb2f)
([329015](https://bugs.webkit.org/show_bug.cgi?id=329015)): Symbols that
only offlineasm output references get `REFERENCED_FROM_ASM`, for GCC
LTO.

### Nothing for a JSCOnly build (20)

`2fe794df22`, `a46f812bfd`, `0ae4c9d112`, `da8e478d08`, `1d91ff5512`,
`ac53330cbd`, `319a9b6c84`, `8655634bf3`, `e381818e3a`, `280384b995`,
`933708cada`, `3b48f12459`, `17d262face`, `4e2a07134b`, `d71f3d702b`,
`500be61de4`, `ad490a9bef`, `58ebe7bde3`, `8bd119f86f`, `48fd938fe4`:
web preferences, sandbox profiles, the Xcode project, Swift bridging,
GLib and GTK/WPE build files.

</details>

<!-- robobun:evidence:begin -->

---

**no test proof** · iteration 7 · platform-specific test(s) that do not
run on this machine, deferring to CI, which covers all platforms:
test/bundler/compile-aot-size.test.ts,
test/bundler/bundler_bytecode_portable.test.ts

<!-- robobun:evidence:end -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants