Skip to content

Commit a29f668

Browse files
authored
Add SHARED_MEMORY support. (#16419)
* Add SHARED_MEMORY support. * Add missing SHARED_MEMORY check. * Add missing SHARED_MEMORY check * Fix test run
1 parent 205c01a commit a29f668

18 files changed

+80
-34
lines changed

emcc.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ def setup_environment_settings():
308308
if not settings.ENVIRONMENT_MAY_BE_WORKER and settings.PROXY_TO_WORKER:
309309
exit_with_error('If you specify --proxy-to-worker and specify a "-s ENVIRONMENT=" directive, it must include "worker" as a target! (Try e.g. -s ENVIRONMENT=web,worker)')
310310

311-
if not settings.ENVIRONMENT_MAY_BE_WORKER and settings.USE_PTHREADS:
311+
if not settings.ENVIRONMENT_MAY_BE_WORKER and settings.SHARED_MEMORY:
312312
exit_with_error('When building with multithreading enabled and a "-s ENVIRONMENT=" directive is specified, it must include "worker" as a target! (Try e.g. -s ENVIRONMENT=web,worker)')
313313

314314

@@ -830,6 +830,9 @@ def get_cflags(user_args):
830830
if settings.EMSCRIPTEN_TRACING:
831831
cflags.append('-D__EMSCRIPTEN_TRACING__=1')
832832

833+
if settings.SHARED_MEMORY:
834+
cflags.append('-D__EMSCRIPTEN_SHARED_MEMORY__=1')
835+
833836
if not settings.STRICT:
834837
# The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code
835838
# in strict mode. Code should use the define __EMSCRIPTEN__ instead.
@@ -1432,7 +1435,10 @@ def phase_setup(options, state, newargs, user_settings):
14321435
if settings.MAIN_MODULE or settings.SIDE_MODULE:
14331436
settings.RELOCATABLE = 1
14341437

1435-
if settings.USE_PTHREADS and '-pthread' not in newargs:
1438+
if settings.USE_PTHREADS:
1439+
settings.SHARED_MEMORY = 1
1440+
1441+
if settings.SHARED_MEMORY and '-pthread' not in newargs:
14361442
newargs += ['-pthread']
14371443

14381444
if 'DISABLE_EXCEPTION_CATCHING' in user_settings and 'EXCEPTION_CATCHING_ALLOWED' in user_settings:
@@ -1687,7 +1693,7 @@ def phase_linker_setup(options, state, newargs, user_settings):
16871693
# https://github.com/whatwg/encoding/issues/172
16881694
# When supporting shell environments, do not do this as TextDecoder is not
16891695
# widely supported there.
1690-
if settings.SHRINK_LEVEL >= 2 and not settings.USE_PTHREADS and \
1696+
if settings.SHRINK_LEVEL >= 2 and not settings.SHARED_MEMORY and \
16911697
not settings.ENVIRONMENT_MAY_BE_SHELL:
16921698
default_setting(user_settings, 'TEXTDECODER', 2)
16931699

@@ -2214,7 +2220,7 @@ def check_memory_setting(setting):
22142220
settings.LEGALIZE_JS_FFI = 0
22152221

22162222
# TODO(sbc): Remove WASM2JS here once the size regression it would introduce has been fixed.
2217-
if settings.USE_PTHREADS or settings.RELOCATABLE or settings.ASYNCIFY_LAZY_LOAD_CODE or settings.WASM2JS:
2223+
if settings.SHARED_MEMORY or settings.RELOCATABLE or settings.ASYNCIFY_LAZY_LOAD_CODE or settings.WASM2JS:
22182224
settings.IMPORTED_MEMORY = 1
22192225

22202226
if settings.WASM_BIGINT:
@@ -2247,9 +2253,9 @@ def check_memory_setting(setting):
22472253
# can use a .mem file like asm.js used to.
22482254
# generally we follow what the options tell us to do (which is to use
22492255
# a .mem file in most cases, since it is binary & compact). however, for
2250-
# pthreads we must keep the memory segments in the wasm as they will be
2251-
# passive segments which the .mem format cannot handle.
2252-
settings.MEM_INIT_IN_WASM = not options.memory_init_file or settings.SINGLE_FILE or settings.USE_PTHREADS
2256+
# shared memory builds we must keep the memory segments in the wasm as
2257+
# they will be passive segments which the .mem format cannot handle.
2258+
settings.MEM_INIT_IN_WASM = not options.memory_init_file or settings.SINGLE_FILE or settings.SHARED_MEMORY
22532259
else:
22542260
# wasm includes the mem init in the wasm binary. The exception is
22552261
# wasm2js, which behaves more like js.

src/jsifier.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,18 +279,20 @@ function ${name}(${args}) {
279279
if (isFunction) {
280280
// Emit the body of a JS library function.
281281
const proxyingMode = LibraryManager.library[ident + '__proxy'];
282-
if (USE_PTHREADS && proxyingMode) {
282+
if (SHARED_MEMORY && proxyingMode) {
283283
if (proxyingMode !== 'sync' && proxyingMode !== 'async') {
284284
throw new Error(`Invalid proxyingMode ${ident}__proxy: '${proxyingMode}' specified!`);
285285
}
286286
const sync = proxyingMode === 'sync';
287287
assert(typeof original == 'function');
288-
contentText = modifyFunction(snippet, (name, args, body) => `
288+
if (USE_PTHREADS) {
289+
contentText = modifyFunction(snippet, (name, args, body) => `
289290
function ${name}(${args}) {
290291
if (ENVIRONMENT_IS_PTHREAD)
291292
return _emscripten_proxy_to_main_thread_js(${proxiedFunctionTable.length}, ${+sync}${args ? ', ' : ''}${args});
292293
${body}
293294
}\n`);
295+
}
294296
proxiedFunctionTable.push(finalName);
295297
} else if ((USE_ASAN || USE_LSAN || UBSAN_RUNTIME) && LibraryManager.library[ident + '__noleakcheck']) {
296298
contentText = modifyFunction(snippet, (name, args, body) => `

src/library.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ LibraryManager.library = {
163163
return false; // malloc will report failure
164164
#endif // ABORTING_MALLOC
165165
#else // ALLOW_MEMORY_GROWTH == 0
166-
// With pthreads, races can happen (another thread might increase the size
166+
// With multithreaded builds, races can happen (another thread might increase the size
167167
// in between), so return a failure, and let the caller retry.
168-
#if USE_PTHREADS
168+
#if SHARED_MEMORY
169169
if (requestedSize <= oldSize) {
170170
return false;
171171
}

src/library_exceptions.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ var LibraryExceptions = {
7474
}
7575

7676
this.add_ref = function() {
77-
#if USE_PTHREADS
77+
#if SHARED_MEMORY
7878
Atomics.add(HEAP32, (this.ptr + {{{ C_STRUCTS.__cxa_exception.referenceCount }}}) >> 2, 1);
7979
#else
8080
var value = {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'i32') }}};
@@ -84,7 +84,7 @@ var LibraryExceptions = {
8484

8585
// Returns true if last reference released.
8686
this.release_ref = function() {
87-
#if USE_PTHREADS
87+
#if SHARED_MEMORY
8888
var prev = Atomics.sub(HEAP32, (this.ptr + {{{ C_STRUCTS.__cxa_exception.referenceCount }}}) >> 2, 1);
8989
#else
9090
var prev = {{{ makeGetValue('this.ptr', C_STRUCTS.__cxa_exception.referenceCount, 'i32') }}};

src/preamble.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ if (typeof WebAssembly != 'object') {
4848

4949
var wasmMemory;
5050

51-
#if USE_PTHREADS
51+
#if SHARED_MEMORY
5252
// For sending to workers.
5353
var wasmModule;
54-
#endif // USE_PTHREADS
54+
#endif // SHARED_MEMORY
5555

5656
//========================================
5757
// Runtime essentials
@@ -1079,7 +1079,8 @@ function createWasm() {
10791079
// is in charge of programatically exporting them on the global object.
10801080
exportAsmFunctions(exports);
10811081
#endif
1082-
#if USE_PTHREADS
1082+
1083+
#if USE_PTHREADS// || WASM_WORKERS
10831084
// We now have the Wasm module loaded up, keep a reference to the compiled module so we can post it to the workers.
10841085
wasmModule = module;
10851086
// Instantiation is synchronous in pthreads and we assert on run dependencies.
@@ -1131,7 +1132,7 @@ function createWasm() {
11311132
assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
11321133
trueModule = null;
11331134
#endif
1134-
#if USE_PTHREADS || RELOCATABLE
1135+
#if SHARED_MEMORY || RELOCATABLE
11351136
receiveInstance(result['instance'], result['module']);
11361137
#else
11371138
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
@@ -1252,6 +1253,7 @@ function createWasm() {
12521253
// User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
12531254
// to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
12541255
// to any other async startup actions they are performing.
1256+
// Also pthreads and wasm workers initialize the wasm instance through this path.
12551257
if (Module['instantiateWasm']) {
12561258
#if USE_OFFSET_CONVERTER
12571259
#if ASSERTIONS && USE_PTHREADS

src/preamble_minimal.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ var HEAP8, HEAP16, HEAP32, HEAPU8, HEAPU16, HEAPU32, HEAPF32, HEAPF64,
5757

5858

5959
function updateGlobalBufferAndViews(b) {
60-
#if ASSERTIONS && USE_PTHREADS
60+
#if ASSERTIONS && SHARED_MEMORY
6161
assert(b instanceof SharedArrayBuffer, 'requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag');
6262
#endif
6363
buffer = b;
@@ -84,10 +84,10 @@ if (!ENVIRONMENT_IS_PTHREAD) {
8484
#endif
8585
wasmMemory = new WebAssembly.Memory({
8686
'initial': {{{ INITIAL_MEMORY >>> 16 }}}
87-
#if USE_PTHREADS || !ALLOW_MEMORY_GROWTH || MAXIMUM_MEMORY != FOUR_GB
87+
#if SHARED_MEMORY || !ALLOW_MEMORY_GROWTH || MAXIMUM_MEMORY != FOUR_GB
8888
, 'maximum': {{{ (ALLOW_MEMORY_GROWTH && MAXIMUM_MEMORY != FOUR_GB ? MAXIMUM_MEMORY : INITIAL_MEMORY) >>> 16 }}}
8989
#endif
90-
#if USE_PTHREADS
90+
#if SHARED_MEMORY
9191
, 'shared': true
9292
#endif
9393
});

src/runtime_init_memory.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ if (ENVIRONMENT_IS_PTHREAD) {
3434
#else
3535
'maximum': INITIAL_MEMORY / {{{ WASM_PAGE_SIZE }}}
3636
#endif // ALLOW_MEMORY_GROWTH
37-
#if USE_PTHREADS
37+
#if SHARED_MEMORY
3838
,
3939
'shared': true
4040
#endif
4141
});
42-
#if USE_PTHREADS
42+
#if SHARED_MEMORY
4343
if (!(wasmMemory.buffer instanceof SharedArrayBuffer)) {
4444
err('requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag');
4545
if (ENVIRONMENT_IS_NODE) {

src/runtime_strings.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns
1010
// a copy of that string as a Javascript String object.
1111

12-
#if USE_PTHREADS && TEXTDECODER
12+
#if SHARED_MEMORY && TEXTDECODER
1313
/**
1414
* UTF8Decoder.decode may not work with a view of a SharedArrayBuffer, see
1515
* https://github.com/whatwg/encoding/issues/172
@@ -36,10 +36,10 @@ function TextDecoderWrapper(encoding) {
3636
#endif
3737

3838
#if TEXTDECODER == 2
39-
var UTF8Decoder = new TextDecoder{{{ USE_PTHREADS ? 'Wrapper' : ''}}}('utf8');
39+
var UTF8Decoder = new TextDecoder{{{ SHARED_MEMORY ? 'Wrapper' : ''}}}('utf8');
4040
#else // TEXTDECODER == 2
4141
#if TEXTDECODER
42-
var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder{{{ USE_PTHREADS ? 'Wrapper' : ''}}}('utf8') : undefined;
42+
var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder{{{ SHARED_MEMORY ? 'Wrapper' : ''}}}('utf8') : undefined;
4343
#endif // TEXTDECODER
4444
#endif // TEXTDECODER == 2
4545

src/runtime_strings_extra.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ function stringToAscii(str, outPtr) {
3232
// a copy of that string as a Javascript String object.
3333

3434
#if TEXTDECODER == 2
35-
var UTF16Decoder = new TextDecoder{{{ USE_PTHREADS ? 'Wrapper' : ''}}}('utf-16le');
35+
var UTF16Decoder = new TextDecoder{{{ SHARED_MEMORY ? 'Wrapper' : ''}}}('utf-16le');
3636
#else // TEXTDECODER == 2
3737
#if TEXTDECODER
38-
var UTF16Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder{{{ USE_PTHREADS ? 'Wrapper' : ''}}}('utf-16le') : undefined;
38+
var UTF16Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder{{{ SHARED_MEMORY ? 'Wrapper' : ''}}}('utf-16le') : undefined;
3939
#endif // TEXTDECODER
4040
#endif // TEXTDECODER == 2
4141

src/settings.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1465,7 +1465,11 @@ var SDL2_MIXER_FORMATS = ["ogg"];
14651465
// [other]
14661466
var IN_TEST_HARNESS = 0;
14671467

1468-
// If true, enables support for pthreads.
1468+
// If 1, target compiling a shared Wasm Memory.
1469+
// [compile+link] - affects user code at compile and system libraries at link.
1470+
var SHARED_MEMORY = 0;
1471+
1472+
// If true, enables support for pthreads. This implies SHARED_MEMORY.
14691473
// This setting is equivalent to `-pthread`, which should be preferred.
14701474
// [compile+link] - affects user code at compile and system libraries at link.
14711475
var USE_PTHREADS = 0;

0 commit comments

Comments
 (0)