Skip to content

Commit 8f63761

Browse files
authored
Enable bulk-memory by default (#22873)
* Remove libbulkmemory `_emscripten_memcpy_js` and fold memcpy and memset into libc * Use bulk memcpy/memset for Oz builds, but keep ASan behavior the same. * Move the zero-length check in memcpy from C into assembly, and add one for memset * Remove the use of `-mno-bulk-memory` at compile time (enabling it in object files) * Temporarily set the Safari version required to use bulk memory to a 14.1 (which has the effect of enabling it by default without enabling the other 14.1 features by default). This will be reverted when nontrapping-fptoint and bigint are also enabled by default. See #23184
1 parent 8af8100 commit 8f63761

File tree

137 files changed

+209
-303
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+209
-303
lines changed

.circleci/config.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ commands:
240240
description: "Name of given test suite"
241241
type: string
242242
default: ""
243+
extra-cflags:
244+
description: "Extra EMCC_CFLAGS"
245+
type: string
246+
default: ""
243247
steps:
244248
- when:
245249
# We only set EMTEST_RETRY_FLAKY on pull requests. When we run
@@ -250,6 +254,8 @@ commands:
250254
- set-retry-flaky-tests
251255
- run:
252256
name: run tests (<< parameters.title >>)
257+
environment:
258+
EMCC_CFLAGS: << parameters.extra-cflags >>
253259
command: |
254260
env
255261
./test/runner << parameters.test_targets >>
@@ -765,6 +771,7 @@ jobs:
765771
node_version: "10.19.0"
766772
- run-tests:
767773
title: "node (oldest / 10.19.0)"
774+
extra-cflags: "-sMIN_NODE_VERSION=101900"
768775
test_targets: "
769776
other.test_gen_struct_info
770777
other.test_native_call_before_init

embuilder.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030

3131
# Minimal subset of targets used by CI systems to build enough to be useful
3232
MINIMAL_TASKS = [
33-
'libbulkmemory',
3433
'libcompiler_rt',
3534
'libcompiler_rt-wasm-sjlj',
3635
'libcompiler_rt-ww',

emcc.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -385,14 +385,6 @@ def get_clang_flags(user_args):
385385
if '-mbulk-memory' not in user_args:
386386
flags.append('-mbulk-memory')
387387

388-
# In emscripten we currently disable bulk memory by default.
389-
# This should be removed/updated when we als update the default browser targets.
390-
if '-mbulk-memory' not in user_args and '-mno-bulk-memory' not in user_args:
391-
# Bulk memory may be enabled via threads or directly via -s.
392-
if not settings.BULK_MEMORY:
393-
flags.append('-mno-bulk-memory')
394-
flags.append('-mno-bulk-memory-opt')
395-
396388
if settings.RELOCATABLE and '-fPIC' not in user_args:
397389
flags.append('-fPIC')
398390

src/library.js

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -405,38 +405,6 @@ addToLibrary({
405405
// the initial values of the environment accessible by getenv.
406406
$ENV: {},
407407

408-
// In -Oz builds, we replace memcpy() altogether with a non-unrolled wasm
409-
// variant, so we should never emit _emscripten_memcpy_js() in the build.
410-
// In STANDALONE_WASM we avoid the _emscripten_memcpy_js dependency so keep
411-
// the wasm file standalone.
412-
// In BULK_MEMORY mode we include native versions of these functions based
413-
// on memory.fill and memory.copy.
414-
// In MAIN_MODULE=1 or EMCC_FORCE_STDLIBS mode all of libc is force included
415-
// so we cannot override parts of it, and therefore cannot use libc_optz.
416-
#if (SHRINK_LEVEL < 2 || LINKABLE || process.env.EMCC_FORCE_STDLIBS) && !STANDALONE_WASM && !BULK_MEMORY
417-
418-
#if MIN_CHROME_VERSION < 45 || MIN_FIREFOX_VERSION < 34 || MIN_SAFARI_VERSION < 100101
419-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/copyWithin lists browsers that support TypedArray.prototype.copyWithin, but it
420-
// has outdated information for Safari, saying it would not support it.
421-
// https://github.com/WebKit/webkit/commit/24a800eea4d82d6d595cdfec69d0f68e733b5c52#diff-c484911d8df319ba75fce0d8e7296333R1 suggests support was added on Aug 28, 2015.
422-
// Manual testing suggests:
423-
// Safari/601.1 Version/9.0 on iPhone 4s with iOS 9.3.6 (released September 30, 2015) does not support copyWithin.
424-
// but the following systems do:
425-
// AppleWebKit/602.2.14 Safari/602.1 Version/10.0 Mobile/14B100 iPhone OS 10_1_1 on iPhone 5s with iOS 10.1.1 (released October 31, 2016)
426-
// AppleWebKit/603.3.8 Safari/602.1 Version/10.0 on iPhone 5 with iOS 10.3.4 (released July 22, 2019)
427-
// AppleWebKit/605.1.15 iPhone OS 12_3_1 Version/12.1.1 Safari/604.1 on iPhone SE with iOS 12.3.1
428-
// AppleWebKit/605.1.15 Safari/604.1 Version/13.0.4 iPhone OS 13_3 on iPhone 6s with iOS 13.3
429-
// AppleWebKit/605.1.15 Version/13.0.3 Intel Mac OS X 10_15_1 on Safari 13.0.3 (15608.3.10.1.4) on macOS Catalina 10.15.1
430-
// Hence the support status of .copyWithin() for Safari version range [10.0.0, 10.1.0] is unknown.
431-
_emscripten_memcpy_js: `= Uint8Array.prototype.copyWithin
432-
? (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num)
433-
: (dest, src, num) => HEAPU8.set(HEAPU8.subarray(src, src+num), dest)`,
434-
#else
435-
_emscripten_memcpy_js: (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num),
436-
#endif
437-
438-
#endif
439-
440408
#if !STANDALONE_WASM
441409
// ==========================================================================
442410
// assert.h

src/library_sigs.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,6 @@ sigs = {
321321
_emscripten_get_progname__sig: 'vpi',
322322
_emscripten_init_main_thread_js__sig: 'vp',
323323
_emscripten_lookup_name__sig: 'ip',
324-
_emscripten_memcpy_js__sig: 'vppp',
325324
_emscripten_notify_mailbox_postmessage__sig: 'vpp',
326325
_emscripten_push_main_loop_blocker__sig: 'vppp',
327326
_emscripten_push_uncounted_main_loop_blocker__sig: 'vppp',

system/lib/libc/emscripten_internal.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@ _Noreturn void _abort_js(void);
3030

3131
void setThrew(uintptr_t threw, int value);
3232

33-
// An external JS implementation that is efficient for very large copies, using
34-
// HEAPU8.set()
35-
void _emscripten_memcpy_js(void* __restrict__ dest,
36-
const void* __restrict__ src,
37-
size_t n) EM_IMPORT(_emscripten_memcpy_js);
38-
3933
void* _emscripten_memcpy_bulkmem(void* __restrict__ dest,
4034
const void* __restrict__ src,
4135
size_t n);

system/lib/libc/emscripten_memcpy.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,20 @@
99
#include "emscripten_internal.h"
1010

1111
// Use the simple/naive version of memcpy when building with asan
12-
#if defined(EMSCRIPTEN_OPTIMIZE_FOR_OZ) || __has_feature(address_sanitizer)
12+
#if __has_feature(address_sanitizer)
1313

1414
static void *__memcpy(void *dest, const void *src, size_t n) {
1515
unsigned char *d = (unsigned char *)dest;
1616
const unsigned char *s = (const unsigned char *)src;
17-
#pragma clang loop unroll(disable)
1817
while(n--) *d++ = *s++;
1918
return dest;
2019
}
2120

22-
#elif defined(__wasm_bulk_memory__)
21+
#elif defined(EMSCRIPTEN_OPTIMIZE_FOR_OZ)
2322

2423
static void *__memcpy(void *restrict dest, const void *restrict src, size_t n) {
25-
return n ? _emscripten_memcpy_bulkmem(dest, src, n) : dest;
24+
// TODO: Ensure this is inlined with Binaryen or inline asm
25+
return _emscripten_memcpy_bulkmem(dest, src, n);
2626
}
2727

2828
#else
@@ -35,12 +35,10 @@ static void *__memcpy(void *restrict dest, const void *restrict src, size_t n) {
3535
unsigned char *block_aligned_d_end;
3636
unsigned char *d_end;
3737

38-
#if !defined(EMSCRIPTEN_STANDALONE_WASM)
3938
if (n >= 512) {
40-
_emscripten_memcpy_js(dest, src, n);
41-
return dest;
39+
// TODO: Re-investigate the size threshold to enable this
40+
return _emscripten_memcpy_bulkmem(dest, src, n);
4241
}
43-
#endif
4442

4543
d_end = d + n;
4644
if ((((uintptr_t)d) & 3) == (((uintptr_t)s) & 3)) {

system/lib/libc/emscripten_memcpy_bulkmem.S

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@
77
.globl _emscripten_memcpy_bulkmem
88
_emscripten_memcpy_bulkmem:
99
.functype _emscripten_memcpy_bulkmem (PTR, PTR, PTR) -> (PTR)
10-
local.get 0
11-
local.get 1
1210
local.get 2
13-
memory.copy 0, 0
11+
#ifdef __wasm64__
12+
i32.wrap_i64
13+
#endif
14+
// memory.copy traps on OOB zero-length copies, but memcpy must not.
15+
if
16+
local.get 0
17+
local.get 1
18+
local.get 2
19+
memory.copy 0, 0
20+
end_if
1421
local.get 0
1522
end_function
1623

system/lib/libc/emscripten_memset.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,7 @@ __attribute__((no_sanitize("address"))) void *__memset(void *str, int c, size_t
99
__attribute__((__weak__)) void *__musl_memset(void *str, int c, size_t n);
1010
__attribute__((__weak__)) void *__memset(void *str, int c, size_t n);
1111

12-
#ifdef EMSCRIPTEN_OPTIMIZE_FOR_OZ
13-
14-
void *__memset(void *str, int c, size_t n) {
15-
unsigned char *s = (unsigned char *)str;
16-
#pragma clang loop unroll(disable)
17-
while(n--) *s++ = c;
18-
return str;
19-
}
20-
21-
#elif defined(__wasm_bulk_memory__)
12+
#if defined(EMSCRIPTEN_OPTIMIZE_FOR_OZ)
2213

2314
void *__memset(void *str, int c, size_t n) {
2415
return _emscripten_memset_bulkmem(str, c, n);

system/lib/libc/emscripten_memset_bulkmem.S

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@
77
.globl _emscripten_memset_bulkmem
88
_emscripten_memset_bulkmem:
99
.functype _emscripten_memset_bulkmem (PTR, i32, PTR) -> (PTR)
10-
local.get 0
11-
local.get 1
1210
local.get 2
13-
memory.fill 0
11+
#ifdef __wasm64__
12+
i32.wrap_i64
13+
#endif
14+
// memory.fill traps on OOB zero-length sets, but memset must not.
15+
if
16+
local.get 0
17+
local.get 1
18+
local.get 2
19+
memory.fill 0
20+
end_if
1421
local.get 0
1522
end_function
1623

0 commit comments

Comments
 (0)