Skip to content

Commit c8ea77a

Browse files
separate worker data & lock buffers
1 parent 2a54826 commit c8ea77a

2 files changed

Lines changed: 27 additions & 24 deletions

File tree

lib/internal/modules/esm/hooks.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -446,23 +446,19 @@ ObjectSetPrototypeOf(Hooks.prototype, null);
446446

447447
class HooksProxy {
448448
/**
449-
* The communication vehicle constituting all memory shared between the main and the worker.
449+
* The request & response segment of the shared memory. TextEncoder/Decoder (needed to convert
450+
* requests & responses into a format supported by the comms channel) reads and writes with
451+
* Uint8Array.
450452
*/
451-
#commsChannel = new SharedArrayBuffer(2048); // maybe use buffer.constants.MAX_LENGTH ?
453+
#data;
452454
/**
453455
* The lock/unlock segment of the shared memory. Atomics require this to be a Int32Array. This
454456
* segment is used to tell the main to sleep when the worker is processing, and vice versa
455457
* (for the worker to sleep whilst the main thread is processing).
456458
* 0 -> main sleeps
457459
* 1 -> worker sleeps
458460
*/
459-
#lock = new Int32Array(this.#commsChannel, 0, 4);
460-
/**
461-
* The request & response segment of the shared memory. TextEncoder/Decoder (needed to convert
462-
* requests & responses into a format supported by the comms channel) reads and writes with
463-
* Uint8Array.
464-
*/
465-
#requestResponseData = new Uint8Array(this.#commsChannel, 4, 2044);
461+
#lock;
466462

467463
#isReady = false;
468464

@@ -472,12 +468,21 @@ class HooksProxy {
472468
*/
473469
constructor() {
474470
const { InternalWorker } = require('internal/worker');
471+
472+
const data = new SharedArrayBuffer(2048);
473+
const lock = new SharedArrayBuffer(4);
474+
this.#data = new Uint8Array(data);
475+
this.#lock = new Int32Array(lock);
476+
475477
const worker = this.worker = new InternalWorker('internal/modules/esm/worker', {
476478
stderr: false,
477479
stdin: false,
478480
stdout: false,
479481
trackUnmanagedFds: false,
480-
workerData: { commsChannel: this.#commsChannel },
482+
workerData: {
483+
data,
484+
lock,
485+
},
481486
});
482487
worker.unref(); // ! Allows the process to eventually exit when worker is in its final sleep.
483488
}
@@ -492,20 +497,20 @@ class HooksProxy {
492497
this.#isReady = true;
493498
}
494499

495-
TypedArrayPrototypeFill(this.#requestResponseData, 0); // Erase handled request/response data
500+
TypedArrayPrototypeFill(this.#data, 0); // Erase handled request/response data
496501

497502
const request = serialize({ method, args });
498-
TypedArrayPrototypeSet(this.#requestResponseData, request);
503+
TypedArrayPrototypeSet(this.#data, request);
499504

500505
Atomics.store(this.#lock, 0, 0); // Send request to worker
501506
Atomics.notify(this.#lock, 0); // Notify worker of new request
502507
Atomics.wait(this.#lock, 0, 0); // Sleep until worker responds
503508

504509
let response;
505510
try {
506-
response = deserialize(this.#requestResponseData);
511+
response = deserialize(this.#data);
507512
} catch (exception) {
508-
if (this.#requestResponseData.every((byte) => byte === 0)) {
513+
if (this.#data.every((byte) => byte === 0)) {
509514
throw new ERR_INVALID_RETURN_VALUE('an object', method, undefined);
510515
} else {
511516
throw exception;

lib/internal/modules/esm/worker.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@ internalBinding('module_wrap').callbackMap = new SafeWeakMap();
2121

2222
const { isMainThread, workerData } = require('worker_threads');
2323
if (isMainThread) { return; } // Needed to pass some tests that happen to load this file on the main thread
24-
const { commsChannel } = workerData;
2524

2625
// lock = 0 -> main sleeps
2726
// lock = 1 -> worker sleeps
28-
const lock = new Int32Array(commsChannel, 0, 4); // Required by Atomics
29-
const requestResponseDataSize = 2044;
30-
const requestResponseData = new Uint8Array(commsChannel, 4, requestResponseDataSize); // For v8.deserialize/serialize
27+
const lock = new Int32Array(workerData.lock); // Required by Atomics
28+
const data = new Uint8Array(workerData.data); // For v8.deserialize/serialize
3129

3230
function releaseLock() {
3331
Atomics.store(lock, 0, 1); // Send response to main
@@ -58,8 +56,8 @@ function releaseLock() {
5856
while (true) {
5957
Atomics.wait(lock, 0, 1); // This pauses the while loop
6058

61-
const { method, args } = deserialize(requestResponseData);
62-
TypedArrayPrototypeFill(requestResponseData, 0);
59+
const { method, args } = deserialize(data);
60+
TypedArrayPrototypeFill(data, 0);
6361

6462
// Each potential exception needs to be caught individually so that the correct error is sent to the main thread
6563
let response, serializedResponse;
@@ -78,19 +76,19 @@ function releaseLock() {
7876

7977
try {
8078
serializedResponse = serialize(response);
81-
if (serializedResponse.byteLength > requestResponseDataSize) {
82-
throw new ERR_OUT_OF_RANGE('serializedResponse.byteLength', `<= ${requestResponseDataSize}`, serializedResponse.byteLength);
79+
if (serializedResponse.byteLength > data.length) {
80+
throw new ERR_OUT_OF_RANGE('serializedResponse.byteLength', `<= ${data.length}`, serializedResponse.byteLength);
8381
}
8482
} catch (exception) {
8583
serializedResponse = serialize(exception);
8684
}
8785

8886
// Send the method response (or exception) to the main thread
8987
try {
90-
TypedArrayPrototypeSet(requestResponseData, serializedResponse);
88+
TypedArrayPrototypeSet(data, serializedResponse);
9189
} catch (exception) {
9290
// Or send the exception thrown when trying to send the response
93-
TypedArrayPrototypeSet(requestResponseData, serialize(exception));
91+
TypedArrayPrototypeSet(data, serialize(exception));
9492
}
9593
releaseLock();
9694
}

0 commit comments

Comments
 (0)