-
Notifications
You must be signed in to change notification settings - Fork 30k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
worker: use engine-provided deleter for
SharedArrayBuffer
s
Store the full information we have on a given `SharedArrayBuffer`, and use the deleter provided by the JS engine to free the memory when that is needed. This fixes memory lifetime management for WASM buffers that are passed through a `MessageChannel` (e.g. between threads). PR-URL: #25307 Reviewed-By: Gus Caplan <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]>
- Loading branch information
Showing
5 changed files
with
62 additions
and
9 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Binary file not shown.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
(module | ||
(memory $mem 1 2 shared) | ||
(export "memory" (memory $mem)) | ||
) |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Flags: --experimental-worker --experimental-wasm-threads | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const { MessageChannel, Worker } = require('worker_threads'); | ||
|
||
// Test that SharedArrayBuffer instances created from WASM are transferrable | ||
// through MessageChannels (without crashing). | ||
|
||
const fixtures = require('../common/fixtures'); | ||
const wasmSource = fixtures.readSync('wasm-threads-shared-memory.wasm'); | ||
const wasmModule = new WebAssembly.Module(wasmSource); | ||
const instance = new WebAssembly.Instance(wasmModule); | ||
|
||
const { buffer } = instance.exports.memory; | ||
assert(buffer instanceof SharedArrayBuffer); | ||
|
||
{ | ||
const { port1, port2 } = new MessageChannel(); | ||
port1.postMessage(buffer); | ||
port2.once('message', common.mustCall((buffer2) => { | ||
// Make sure serialized + deserialized buffer refer to the same memory. | ||
const expected = 'Hello, world!'; | ||
const bytes = Buffer.from(buffer).write(expected); | ||
const deserialized = Buffer.from(buffer2).toString('utf8', 0, bytes); | ||
assert.deepStrictEqual(deserialized, expected); | ||
})); | ||
} | ||
|
||
{ | ||
// Make sure we can free WASM memory originating from a thread that already | ||
// stopped when we exit. | ||
const worker = new Worker(` | ||
const { parentPort } = require('worker_threads'); | ||
const wasmSource = new Uint8Array([${wasmSource.join(',')}]); | ||
const wasmModule = new WebAssembly.Module(wasmSource); | ||
const instance = new WebAssembly.Instance(wasmModule); | ||
parentPort.postMessage(instance.exports.memory); | ||
`, { eval: true }); | ||
worker.once('message', common.mustCall(({ buffer }) => { | ||
assert(buffer instanceof SharedArrayBuffer); | ||
worker.buf = buffer; // Basically just keep the reference to buffer alive. | ||
})); | ||
worker.once('exit', common.mustCall()); | ||
worker.postMessage({ wasmModule }); | ||
} |