Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/build/deps/webkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* for local mode. Override via `--webkit-version=<hash>` to test a branch.
* From https://github.com/oven-sh/WebKit releases.
*/
export const WEBKIT_VERSION = "ddea71318fec9b923465c7c45ded8fa713ca3251";
export const WEBKIT_VERSION = "autobuild-preview-pr-395-8ec8fb6a";
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* WebKit (JavaScriptCore) — the JS engine.
Expand Down
49 changes: 49 additions & 0 deletions test/cli/run/cpu-prof.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,4 +444,53 @@ describe.concurrent("--cpu-prof", () => {
const mdContent = readFileSync(join(String(dir), mdFiles[0]), "utf-8");
expect(mdContent).toContain("# CPU Profile");
});

// The sampling profiler could segfault when a sample landed inside a VM
// entry/exit transition: vm.topEntryFrame is null there while vm.entryScope
// is already set, and a walked frame whose caller slot read null made the
// stack walker dereference vmEntryRecord(nullptr) (oven-sh/WebKit#395, seen
// as a crash at 0xFFFFFFFFFFFFFFC8 in test-cpu-prof-dir-worker.js on CI).
// The workload widens that window as far as JS can: a callback with a huge
// declared parameter count invoked from native spends most of its runtime in
// doVMEntry's argument pad loop, which runs before topEntryFrame is stored.
test("sampler survives VM entry churn from callbacks with huge parameter counts", async () => {
using dir = tempDir("cpu-prof-entry-churn", {
"churn.js": `
const params = Array.from({ length: 2000 }, (_, i) => "p" + i).join(",");
const f = new Function(params, "c.n++;");
globalThis.c = { n: 0 };
const { port1, port2 } = new MessageChannel();
port1.onmessage = f;
const deadline = performance.now() + 150;
function loop() {
if (performance.now() >= deadline) {
console.log("calls made:", c.n > 0);
port1.close();
port2.close();
return;
}
setImmediate(f);
Promise.resolve().then(f);
queueMicrotask(f);
process.nextTick(f);
port2.postMessage(1);
setImmediate(loop);
}
loop();
`,
});

await using proc = Bun.spawn({
cmd: [bunExe(), "--cpu-prof", "--cpu-prof-interval=50", "churn.js"],
cwd: String(dir),
env: bunEnv,
stdout: "pipe",
stderr: "inherit",
});

const [stdout, exitCode] = await Promise.all([proc.stdout.text(), proc.exited]);

expect(stdout).toContain("calls made: true");
expect(exitCode).toBe(0);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});
});
Loading