Skip to content

Commit 608f5d2

Browse files
committed
[wasm64] Fix and run run all pthread browser tests
1 parent a0a3f24 commit 608f5d2

18 files changed

+82
-32
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,7 @@ jobs:
820820
browser64.test_fetch_xhr_abort
821821
browser64.test_fetch_sync_xhr
822822
browser64.test_fetch_implicit_append
823+
browser64.test_pthread_*
823824
"
824825
test-browser-firefox:
825826
executor: bionic

src/jsifier.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,13 @@ function(${args}) {
246246
if (oneliner) {
247247
body = `return ${body}`;
248248
}
249+
const rtnType = sig && sig.length ? sig[0] : null;
250+
const proxyFunc = (MEMORY64 && rtnType == 'p') ? 'proxyToMainThreadPtr' : 'proxyToMainThread';
251+
deps.push('$' + proxyFunc);
249252
return `
250253
function(${args}) {
251254
if (ENVIRONMENT_IS_PTHREAD)
252-
return proxyToMainThread(${proxiedFunctionTable.length}, ${+sync}${args ? ', ' : ''}${args});
255+
return ${proxyFunc}(${proxiedFunctionTable.length}, ${+sync}${args ? ', ' : ''}${args});
253256
${body}
254257
}\n`
255258
});

src/library_pthread.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,15 @@ var LibraryPThread = {
948948
_exit(returnCode);
949949
},
950950
951-
$proxyToMainThread__deps: ['$withStackSave', '_emscripten_run_on_main_thread_js'],
951+
#if MEMORY64
952+
// Calls proxyToMainThread but returns a bigint rather than a number
953+
$proxyToMainThreadPtr__deps: ['$proxyToMainThread'],
954+
$proxyToMainThreadPtr: function() {
955+
return BigInt(proxyToMainThread.apply(null, arguments));
956+
},
957+
#endif
958+
959+
$proxyToMainThread__deps: ['$withStackSave', '_emscripten_run_on_main_thread_js'].concat(i53ConversionDeps),
952960
$proxyToMainThread__docs: '/** @type{function(number, (number|boolean), ...(number|boolean))} */',
953961
$proxyToMainThread: function(index, sync) {
954962
// Additional arguments are passed after those two, which are the actual
@@ -1032,6 +1040,19 @@ var LibraryPThread = {
10321040
PThread.currentProxiedOperationCallerThread = callingThread;
10331041
var rtn = func.apply(null, proxiedJSCallArgs);
10341042
PThread.currentProxiedOperationCallerThread = 0;
1043+
#if MEMORY64
1044+
// In memory64 mode some proxied functions return bigint/pointer but
1045+
// our return type is i53/double.
1046+
if (typeof rtn == "bigint") {
1047+
rtn = bigintToI53Checked(rtn);
1048+
}
1049+
#endif
1050+
#if ASSERTIONS
1051+
// Proxied functions can return any type except bigint. All other types
1052+
// cooerce to f64/double (the return type of this function in C) but not
1053+
// bigint.
1054+
assert(typeof rtn != "bigint");
1055+
#endif
10351056
return rtn;
10361057
},
10371058

src/preamble_minimal.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,15 @@ if (!ENVIRONMENT_IS_PTHREAD) {
100100
Module['mem'] ||
101101
#endif
102102
new WebAssembly.Memory({
103-
'initial': {{{ INITIAL_MEMORY >>> 16 }}}
103+
'initial': {{{ INITIAL_MEMORY >>> 16 }}},
104104
#if SHARED_MEMORY || !ALLOW_MEMORY_GROWTH || MAXIMUM_MEMORY != FOUR_GB
105-
, 'maximum': {{{ (ALLOW_MEMORY_GROWTH && MAXIMUM_MEMORY != FOUR_GB ? MAXIMUM_MEMORY : INITIAL_MEMORY) >>> 16 }}}
105+
'maximum': {{{ (ALLOW_MEMORY_GROWTH && MAXIMUM_MEMORY != FOUR_GB ? MAXIMUM_MEMORY : INITIAL_MEMORY) >>> 16 }}},
106106
#endif
107107
#if SHARED_MEMORY
108-
, 'shared': true
108+
'shared': true,
109+
#endif
110+
#if MEMORY64 == 1
111+
'index': 'i64',
109112
#endif
110113
});
111114
#if PTHREADS

test/common.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,14 @@ def no_windows(note=''):
169169
return lambda f: f
170170

171171

172+
def no_wasm64(note=''):
173+
assert not callable(note)
174+
175+
def decorated(f):
176+
return skip_if(f, 'is_wasm64', note)
177+
return decorated
178+
179+
172180
def only_windows(note=''):
173181
assert not callable(note)
174182
if not WINDOWS:
@@ -574,6 +582,9 @@ def is_wasm(self):
574582
def is_browser_test(self):
575583
return False
576584

585+
def is_wasm64(self):
586+
return self.get_setting('MEMORY64')
587+
577588
def check_dylink(self):
578589
if self.get_setting('ALLOW_MEMORY_GROWTH') == 1 and not self.is_wasm():
579590
self.skipTest('no dynamic linking with memory growth (without wasm)')

test/pthread/call_sync_on_main_thread.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ addToLibrary({
33
// This function returns the inner text of the given element
44
// Because it accesses the DOM, it must be called on the main thread.
55
getDomElementContents__proxy: 'sync',
6-
getDomElementContents__sig: 'viii',
6+
getDomElementContents__sig: 'pp',
77
getDomElementContents__deps: ['$stringToNewUTF8'],
88
getDomElementContents: function(domElementSelector) {
99
var selector = UTF8ToString(domElementSelector);

test/pthread/test_futex_wake_all.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ void *WaitingThread(void *arg)
5757

5858
int main()
5959
{
60-
for(int i = 0; i < NUM_THREADS; ++i)
60+
for(intptr_t i = 0; i < NUM_THREADS; ++i)
6161
{
6262
pthread_create(waitingThreads+i, 0, WaitingThread, (void*)i);
6363
}

test/pthread/test_large_pthread_allocation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ static void *thread_start(void *arg)
2121
pthread_exit((void*)0);
2222
}
2323

24-
void CreateThread(int idx) {
24+
void CreateThread(intptr_t idx) {
2525
int rc = pthread_create(&threads[idx], NULL, thread_start, (void*)idx);
2626
assert(rc == 0);
2727
}

test/pthread/test_pthread_barrier.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ void *thread_main(void *arg)
4444
}
4545

4646
// Then each thread sums the one intermediate vector.
47-
int totalSum = 0;
47+
intptr_t totalSum = 0;
4848
for(int i = 0; i < N; ++i)
4949
totalSum += intermediate[i];
5050

@@ -70,9 +70,10 @@ int main(int argc, char **argv)
7070
int ret = pthread_barrier_init(&barr, NULL, THREADS);
7171
assert(ret == 0);
7272

73-
for(int i = 0; i < THREADS; ++i) pthread_create(&thr[i], NULL, &thread_main, (void*)i);
74-
for(int i = 0; i < THREADS; ++i)
75-
{
73+
for(intptr_t i = 0; i < THREADS; ++i) {
74+
pthread_create(&thr[i], NULL, &thread_main, (void*)i);
75+
}
76+
for(int i = 0; i < THREADS; ++i) {
7677
int totalSum = 0;
7778
pthread_join(thr[i], (void**)&totalSum);
7879
assert(totalSum == expectedTotalSum);

test/pthread/test_pthread_cancel_cond_wait.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ volatile int res = 43;
2222

2323
static void cleanup_handler(void *arg) {
2424
emscripten_log(EM_LOG_CONSOLE, "Called clean-up handler with arg %p", arg);
25-
int a = reinterpret_cast<int>(arg);
25+
int a = reinterpret_cast<intptr_t>(arg);
2626
res -= a;
2727

2828
pthread_mutex_unlock(&mutex);

test/pthread/test_pthread_create.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,20 @@ void *ThreadMain(void *arg)
4646
}
4747
}
4848
// Ensure all elements are in place.
49-
int numGood = 0;
49+
intptr_t numGood = 0;
5050
for(unsigned int i = 0; i < N; ++i)
5151
if (n[i] == i) ++numGood;
5252
else emscripten_errf("n[%d]=%d", i, n[i]);
5353

54-
emscripten_outf("Thread idx %ld with param %d: all done with result %d.", idx, param, numGood);
54+
emscripten_outf("Thread idx %ld with param %d: all done with result %ld.", idx, param, numGood);
5555
pthread_exit((void*)numGood);
5656
}
5757

5858
pthread_t thread[NUM_THREADS];
5959

6060
int numThreadsToCreate = 1000;
6161

62-
void CreateThread(int i)
62+
void CreateThread(intptr_t i)
6363
{
6464
static int counter = 1;
6565
global_shared_data[i] = (counter++ * 12141231) & 0x7FFFFFFF; // Arbitrary random'ish data for perturbing the sort for this thread task.
@@ -81,7 +81,7 @@ int main()
8181
{
8282
if (thread[i])
8383
{
84-
int status;
84+
intptr_t status;
8585
int rc = pthread_join(thread[i], (void**)&status);
8686
assert(rc == 0);
8787
emscripten_errf("Main: Joined thread idx %d (param %d) with status %d", i, global_shared_data[i], (int)status);

test/pthread/test_pthread_gcc_64bit_atomic_fetch_and_op.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ int main()
110110
for(int i = 0; i < NUM_THREADS; ++i)
111111
{
112112
threadArg[i] = DUP(1 << i);
113-
pthread_create(&thread[i], NULL, thread_fetch_and_or, (void*)&threadArg[i]);
113+
pthread_create(&thread[i], NULL, thread_fetch_and_or, &threadArg[i]);
114114
}
115115
for(int i = 0; i < NUM_THREADS; ++i) pthread_join(thread[i], NULL);
116116
assert(fetch_and_or_data == HILO(65536 + (1<<(NUM_THREADS+1))-1, (1<<(NUM_THREADS+1))-1));

test/pthread/test_pthread_gcc_atomic_fetch_and_op.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ int main()
103103
fetch_and_or_data = (1<<NUM_THREADS);
104104
if (emscripten_has_threading_support())
105105
{
106-
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_fetch_and_or, (void*)(1<<i));
106+
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_fetch_and_or, (void*)(1ll<<i));
107107
for(int i = 0; i < NUM_THREADS; ++i) pthread_join(thread[i], NULL);
108108
assert(fetch_and_or_data == (1<<(NUM_THREADS+1))-1);
109109
}
@@ -119,7 +119,7 @@ int main()
119119
fetch_and_and_data = (1<<(NUM_THREADS+1))-1;
120120
if (emscripten_has_threading_support())
121121
{
122-
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_fetch_and_and, (void*)(~(1<<i)));
122+
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_fetch_and_and, (void*)(~(1ll<<i)));
123123
for(int i = 0; i < NUM_THREADS; ++i) pthread_join(thread[i], NULL);
124124
assert(fetch_and_and_data == 1<<NUM_THREADS);
125125
}
@@ -135,7 +135,7 @@ int main()
135135
fetch_and_xor_data = 1<<NUM_THREADS;
136136
if (emscripten_has_threading_support())
137137
{
138-
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_fetch_and_xor, (void*)(~(1<<i)));
138+
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_fetch_and_xor, (void*)(~(1ll<<i)));
139139
for(int i = 0; i < NUM_THREADS; ++i) pthread_join(thread[i], NULL);
140140
assert(fetch_and_xor_data == (1<<(NUM_THREADS+1))-1);
141141
}

test/pthread/test_pthread_gcc_atomic_op_and_fetch.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ int main()
102102
or_and_fetch_data = (1<<NUM_THREADS);
103103
if (emscripten_has_threading_support())
104104
{
105-
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_or_and_fetch, (void*)(1<<i));
105+
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_or_and_fetch, (void*)(1ll<<i));
106106
for(int i = 0; i < NUM_THREADS; ++i) pthread_join(thread[i], NULL);
107107
assert(or_and_fetch_data == (1<<(NUM_THREADS+1))-1);
108108
}
@@ -118,7 +118,7 @@ int main()
118118
and_and_fetch_data = (1<<(NUM_THREADS+1))-1;
119119
if (emscripten_has_threading_support())
120120
{
121-
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_and_and_fetch, (void*)(~(1<<i)));
121+
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_and_and_fetch, (void*)(~(1ll<<i)));
122122
for(int i = 0; i < NUM_THREADS; ++i) pthread_join(thread[i], NULL);
123123
assert(and_and_fetch_data == 1<<NUM_THREADS);
124124
}
@@ -134,7 +134,7 @@ int main()
134134
xor_and_fetch_data = 1<<NUM_THREADS;
135135
if (emscripten_has_threading_support())
136136
{
137-
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_xor_and_fetch, (void*)(~(1<<i)));
137+
for(int i = 0; i < NUM_THREADS; ++i) pthread_create(&thread[i], NULL, thread_xor_and_fetch, (void*)(~(1ll<<i)));
138138
for(int i = 0; i < NUM_THREADS; ++i) pthread_join(thread[i], NULL);
139139
assert(xor_and_fetch_data == (1<<(NUM_THREADS+1))-1);
140140
}

test/pthread/test_pthread_join.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ int main()
4040
assert(EM_ASM_INT(return PThread.runningWorkers.length) == 0);
4141
assert(EM_ASM_INT(return PThread.unusedWorkers.length) == 8); // This test should be run with a prepopulated pool of size 8.
4242

43-
int n = 20;
44-
emscripten_outf("Main: Spawning thread to compute fib(%d)...", n);
43+
intptr_t n = 20;
44+
emscripten_outf("Main: Spawning thread to compute fib(%ld)...", n);
4545
int s = pthread_create(&thr, NULL, thread_start, (void*)n);
4646
assert(s == 0);
4747
emscripten_out("Main: Waiting for thread to join");

test/pthread/test_pthread_malloc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ static void *thread_start(void *arg)
4040
int main()
4141
{
4242
pthread_t thr[NUM_THREADS];
43-
for(int i = 0; i < NUM_THREADS; ++i)
43+
for(intptr_t i = 0; i < NUM_THREADS; ++i)
4444
pthread_create(&thr[i], NULL, thread_start, (void*)(i*N));
4545
int result = 0;
4646
for(int i = 0; i < NUM_THREADS; ++i) {

test/pthread/test_pthread_preallocates_workers.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ static void *thread_start(void *arg)
2828
pthread_exit((void*)0);
2929
}
3030

31-
void CreateThread(int idx) {
32-
emscripten_outf("Main: Spawning thread %d...", idx);
31+
void CreateThread(intptr_t idx) {
32+
emscripten_outf("Main: Spawning thread %ld...", idx);
3333
int rc = pthread_create(&threads[idx], NULL, thread_start, (void*)idx);
3434
assert(rc == 0);
3535
}

test/test_browser.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
from common import BrowserCore, RunnerCore, path_from_root, has_browser, EMTEST_BROWSER, Reporting
2525
from common import create_file, parameterized, ensure_dir, disabled, test_file, WEBIDL_BINDER
26-
from common import read_file, requires_v8, also_with_minimal_runtime, EMRUN
26+
from common import read_file, requires_v8, also_with_minimal_runtime, EMRUN, no_wasm64
2727
from tools import shared
2828
from tools import ports
2929
from tools import utils
@@ -119,6 +119,8 @@ def also_with_wasm2js(f):
119119
def metafunc(self, with_wasm2js):
120120
assert self.get_setting('WASM') is None
121121
if with_wasm2js:
122+
if self.is_wasm64():
123+
self.skipTest('wasm2js is not compatible with MEMORY64')
122124
self.set_setting('WASM', 0)
123125
f(self)
124126
else:
@@ -3875,6 +3877,7 @@ def test_pthread_gcc_atomic_fetch_and_op(self):
38753877
self.btest_exit('pthread/test_pthread_gcc_atomic_fetch_and_op.cpp', args=args + ['-sINITIAL_MEMORY=64MB', '-pthread', '-sPTHREAD_POOL_SIZE=8'])
38763878

38773879
# 64 bit version of the above test.
3880+
@no_wasm64("XXX")
38783881
@also_with_wasm2js
38793882
@requires_threads
38803883
def test_pthread_gcc_64bit_atomic_fetch_and_op(self):
@@ -3891,6 +3894,7 @@ def test_pthread_gcc_atomic_op_and_fetch(self):
38913894
self.btest_exit('pthread/test_pthread_gcc_atomic_op_and_fetch.cpp', args=['-sINITIAL_MEMORY=64MB', '-O3', '-pthread', '-sPTHREAD_POOL_SIZE=8'])
38923895

38933896
# 64 bit version of the above test.
3897+
@no_wasm64("XXX")
38943898
@also_with_wasm2js
38953899
@requires_threads
38963900
def test_pthread_gcc_64bit_atomic_op_and_fetch(self):
@@ -4108,15 +4112,15 @@ def test_pthread_custom_pthread_main_url(self):
41084112

41094113
# Test that it is possible to define "Module.locateFile" string to locate where worker.js will be loaded from.
41104114
create_file('shell.html', read_file(path_from_root('src/shell.html')).replace('var Module = {', 'var Module = { locateFile: function (path, prefix) {if (path.endsWith(".wasm")) {return prefix + path;} else {return "cdn/" + path;}}, '))
4111-
self.compile_btest(['main.cpp', '--shell-file', 'shell.html', '-sWASM=0', '-pthread', '-sPTHREAD_POOL_SIZE', '-o', 'test.html'], reporting=Reporting.JS_ONLY)
4115+
self.compile_btest(['main.cpp', '--shell-file', 'shell.html', '-pthread', '-sPTHREAD_POOL_SIZE', '-o', 'test.html'], reporting=Reporting.JS_ONLY)
41124116
shutil.move('test.worker.js', Path('cdn/test.worker.js'))
41134117
if os.path.exists('test.html.mem'):
41144118
shutil.copyfile('test.html.mem', Path('cdn/test.html.mem'))
41154119
self.run_browser('test.html', '/report_result?exit:0')
41164120

41174121
# Test that it is possible to define "Module.locateFile(foo)" function to locate where worker.js will be loaded from.
41184122
create_file('shell2.html', read_file(path_from_root('src/shell.html')).replace('var Module = {', 'var Module = { locateFile: function(filename) { if (filename == "test.worker.js") return "cdn/test.worker.js"; else return filename; }, '))
4119-
self.compile_btest(['main.cpp', '--shell-file', 'shell2.html', '-sWASM=0', '-pthread', '-sPTHREAD_POOL_SIZE', '-o', 'test2.html'], reporting=Reporting.JS_ONLY)
4123+
self.compile_btest(['main.cpp', '--shell-file', 'shell2.html', '-pthread', '-sPTHREAD_POOL_SIZE', '-o', 'test2.html'], reporting=Reporting.JS_ONLY)
41204124
delete_file('test.worker.js')
41214125
self.run_browser('test2.html', '/report_result?exit:0')
41224126

@@ -4187,6 +4191,8 @@ def test_pthread_global_data_initialization(self):
41874191

41884192
@requires_threads
41894193
def test_pthread_global_data_initialization_in_sync_compilation_mode(self):
4194+
if self.is_wasm64():
4195+
self.skipTest('wasm2js is not compatible with MEMORY64')
41904196
mem_init_modes = [[], ['-sWASM=0', '--memory-init-file', '0'], ['-sWASM=0', '--memory-init-file', '1']]
41914197
for mem_init_mode in mem_init_modes:
41924198
print(mem_init_mode)
@@ -4230,6 +4236,7 @@ def test_pthread_safe_stack(self):
42304236
# same stack size as the main thread normally would.
42314237
self.btest('core/test_safe_stack.c', expected='abort:stack overflow', args=['-pthread', '-sPROXY_TO_PTHREAD', '-sSTACK_OVERFLOW_CHECK=2', '-sSTACK_SIZE=64KB'])
42324238

4239+
@no_wasm64('TODO: ASAN in memory64')
42334240
@parameterized({
42344241
'leak': ['test_pthread_lsan_leak', ['-gsource-map']],
42354242
'no_leak': ['test_pthread_lsan_no_leak', []],
@@ -4239,6 +4246,7 @@ def test_pthread_safe_stack(self):
42394246
def test_pthread_lsan(self, name, args):
42404247
self.btest(Path('pthread', name + '.cpp'), expected='1', args=['-fsanitize=leak', '-sINITIAL_MEMORY=256MB', '-pthread', '-sPROXY_TO_PTHREAD', '--pre-js', test_file('pthread', name + '.js')] + args)
42414248

4249+
@no_wasm64('TODO: ASAN in memory64')
42424250
@parameterized({
42434251
# Reusing the LSan test files for ASan.
42444252
'leak': ['test_pthread_lsan_leak', ['-gsource-map']],
@@ -4248,10 +4256,12 @@ def test_pthread_lsan(self, name, args):
42484256
def test_pthread_asan(self, name, args):
42494257
self.btest(Path('pthread', name + '.cpp'), expected='1', args=['-fsanitize=address', '-sINITIAL_MEMORY=256MB', '-pthread', '-sPROXY_TO_PTHREAD', '--pre-js', test_file('pthread', name + '.js')] + args)
42504258

4259+
@no_wasm64('TODO: ASAN in memory64')
42514260
@requires_threads
42524261
def test_pthread_asan_use_after_free(self):
42534262
self.btest('pthread/test_pthread_asan_use_after_free.cpp', expected='1', args=['-fsanitize=address', '-sINITIAL_MEMORY=256MB', '-pthread', '-sPROXY_TO_PTHREAD', '--pre-js', test_file('pthread/test_pthread_asan_use_after_free.js')])
42544263

4264+
@no_wasm64('TODO: ASAN in memory64')
42554265
@no_firefox('https://github.com/emscripten-core/emscripten/issues/20006')
42564266
@also_with_wasmfs
42574267
@requires_threads

0 commit comments

Comments
 (0)