Skip to content

Commit

Permalink
[Wasm64] Fix many remaining issues and add wasm64_4gb test configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
sbc100 committed Aug 18, 2023
1 parent 0f83fd4 commit 8f871c3
Show file tree
Hide file tree
Showing 19 changed files with 169 additions and 94 deletions.
24 changes: 20 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -616,15 +616,28 @@ jobs:
title: "wasm64"
test_targets: "
wasm64
wasm64_4gb.test_hello_world
wasm64_4gb.test_em_asm
wasm64_4gb.test_async_main
wasm64_4gb.*embind*
core_2gb.test_em_asm
wasm64l.test_bigswitch
other.test_memory64_proxies
other.test_failing_growth_wasm64"
- upload-test-results
test-wasm64_4gb:
environment:
EMTEST_SKIP_NODE_CANARY: "1"
# We don't use `bionic` here since its tool old to run recent node versions:
# `/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found`
executor: linux-python
steps:
- prepare-for-tests
# The linux-python image uses /home/circleci rather than /root and jsvu
# hardcodes /root into its launcher scripts do we need to reinstall v8.
- run: rm -rf $HOME/.jsvu
- install-v8
- install-node-canary
- run-tests:
title: "wasm64_4gb"
test_targets: "wasm64_4gb"
- upload-test-results
test-jsc:
executor: linux-python
steps:
Expand Down Expand Up @@ -876,6 +889,9 @@ workflows:
- test-wasm64:
requires:
- build-linux
- test-wasm64_4gb:
requires:
- build-linux
- test-wasm64l:
requires:
- build-linux
Expand Down
5 changes: 4 additions & 1 deletion emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1783,7 +1783,10 @@ def set_max_memory():

# INITIAL_MEMORY sets a lower bound for MAXIMUM_MEMORY
if 'MAXIMUM_MEMORY' not in user_settings:
if settings.INITIAL_MEMORY > settings.MAXIMUM_MEMORY:
if settings.ALLOW_MEMORY_GROWTH and settings.MEMORY64:
# 16gb is the current limit for wasm-ld
settings.MAXIMUM_MEMORY = 16 * 1024 * 1024 * 1024
elif settings.INITIAL_MEMORY > settings.MAXIMUM_MEMORY:
settings.MAXIMUM_MEMORY = settings.INITIAL_MEMORY

if settings.MAXIMUM_MEMORY < settings.INITIAL_MEMORY:
Expand Down
8 changes: 4 additions & 4 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ addToLibrary({
// it. Returns 1 on success, 0 on error.
$growMemory: (size) => {
var b = wasmMemory.buffer;
var pages = (size - b.byteLength + 65535) >>> 16;
var pages = (size - b.byteLength + {{{ WASM_PAGE_SIZE - 1 }}}) / {{{ WASM_PAGE_SIZE }}};
#if RUNTIME_DEBUG
dbg(`emscripten_resize_heap: ${size} (+${size - b.byteLength} bytes / ${pages} pages)`);
dbg(`growMemory: ${size} (+${size - b.byteLength} bytes / ${pages} pages)`);
#endif
#if MEMORYPROFILER
var oldHeapSize = b.byteLength;
Expand Down Expand Up @@ -249,7 +249,7 @@ addToLibrary({
var maxHeapSize = getHeapMax();
if (requestedSize > maxHeapSize) {
#if ASSERTIONS
err(`Cannot enlarge memory, asked to go up to ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);
err(`Cannot enlarge memory, requested ${requestedSize} bytes, but the limit is ${maxHeapSize} bytes!`);
#endif
#if ABORTING_MALLOC
abortOnCannotGrowMemory(requestedSize);
Expand Down Expand Up @@ -693,7 +693,7 @@ addToLibrary({
// size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr);
// http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html

var tm_zone = {{{ makeGetValue('tm', C_STRUCTS.tm.tm_zone, 'i32') }}};
var tm_zone = {{{ makeGetValue('tm', C_STRUCTS.tm.tm_zone, '*') }}};

var date = {
tm_sec: {{{ makeGetValue('tm', C_STRUCTS.tm.tm_sec, 'i32') }}},
Expand Down
2 changes: 1 addition & 1 deletion src/library_fs_shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ addToLibrary({
var fd = process.stdin.fd;

try {
bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, -1);
bytesRead = fs.readSync(fd, buf, { position: -1 });
} catch(e) {
// Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes,
// reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0.
Expand Down
45 changes: 25 additions & 20 deletions src/library_int53.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,32 @@ addToLibrary({
// function $writeI53ToU64(): the implementation would be identical, and it is up to the
// C/C++ side code to interpret the resulting number as signed or unsigned as is desirable.
$writeI53ToI64: (ptr, num) => {
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
{{{ makeSetValue('ptr', 0, 'num', 'u32') }}};
var lower = {{{ makeGetValue('ptr', 0, 'u32') }}};
{{{ makeSetValue('ptr', 4, '(num - lower)/4294967296', 'u32') }}};
#if ASSERTIONS
var deserialized = (num >= 0) ? readI53FromU64(ptr) : readI53FromI64(ptr);
if (deserialized != num) warnOnce('writeI53ToI64() out of range: serialized JS Number ' + num + ' to Wasm heap as bytes lo=' + ptrToString(HEAPU32[ptr>>2]) + ', hi=' + ptrToString(HEAPU32[ptr+4>>2]) + ', which deserializes back to ' + deserialized + ' instead!');
if (deserialized != num) warnOnce(`writeI53ToI64() out of range: serialized JS Number ${num} to Wasm heap as bytes lo=${ptrToString(HEAPU32[ptr/4])}, hi=${ptrToString(HEAPU32[ptr/4+1])}, which deserializes back to ${deserialized} instead!`);
#endif
},

// Same as writeI53ToI64, but if the double precision number does not fit within the
// 64-bit number, the number is clamped to range [-2^63, 2^63-1].
$writeI53ToI64Clamped__deps: ['$writeI53ToI64'],
$writeI53ToI64Clamped: (ptr, num) => {
if (num > 0x7FFFFFFFFFFFFFFF) {
HEAPU32[ptr>>2] = 0xFFFFFFFF;
HEAPU32[ptr+4>>2] = 0x7FFFFFFF;
{{{ makeSetValue('ptr', 0, 0xFFFFFFFF, 'u32') }}};
{{{ makeSetValue('ptr', 4, 0x7FFFFFFF, 'u32') }}};
} else if (num < -0x8000000000000000) {
HEAPU32[ptr>>2] = 0;
HEAPU32[ptr+4>>2] = 0x80000000;
{{{ makeSetValue('ptr', 0, 0, 'u32') }}};
{{{ makeSetValue('ptr', 4, 0x80000000, 'u32') }}};
} else {
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
writeI53ToI64(ptr, num);
}
},

// Like writeI53ToI64, but throws if the passed number is out of range of int64.
$writeI53ToI64__deps: ['$writeI53ToI64'],
$writeI53ToI64Signaling: (ptr, num) => {
if (num > 0x7FFFFFFFFFFFFFFF || num < -0x8000000000000000) {
#if ASSERTIONS
Expand All @@ -51,22 +53,26 @@ addToLibrary({
throw 'RangeError:' + num;
#endif
}
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
writeI53ToI64(ptr, num);
},

// Uint64 variant of writeI53ToI64Clamped. Writes the Number to a Uint64 variable on
// the heap, clamping out of range values to range [0, 2^64-1].
$writeI53ToU64Clamped__deps: ['$writeI53ToI64'],
$writeI53ToU64Clamped: (ptr, num) => {
if (num > 0xFFFFFFFFFFFFFFFF) HEAPU32[ptr>>2] = HEAPU32[ptr+4>>2] = 0xFFFFFFFF;
else if (num < 0) HEAPU32[ptr>>2] = HEAPU32[ptr+4>>2] = 0;
else {
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
if (num > 0xFFFFFFFFFFFFFFFF) {
{{{ makeSetValue('ptr', 0, 0xFFFFFFFF, 'u32') }}};
{{{ makeSetValue('ptr', 4, 0xFFFFFFFF, 'u32') }}};
} else if (num < 0) {
{{{ makeSetValue('ptr', 0, 0, 'u32') }}};
{{{ makeSetValue('ptr', 4, 0, 'u32') }}};
} else {
writeI53ToI64(ptr, num);
}
},

// Like writeI53ToI64, but throws if the passed number is out of range of uint64.
$writeI53ToU64Signaling__deps: ['$writeI53ToI64'],
$writeI53ToU64Signaling: (ptr, num) => {
if (num < 0 || num > 0xFFFFFFFFFFFFFFFF) {
#if ASSERTIONS
Expand All @@ -75,22 +81,21 @@ addToLibrary({
throw 'RangeError:'+num;
#endif
}
HEAPU32[ptr>>2] = num;
HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
writeI53ToI64(ptr, num);
},

// Reads a 64-bit signed integer from the WebAssembly heap and
// converts it to a JavaScript Number, which can represent 53 integer bits precisely.
// TODO: Add $readI53FromI64Signaling() variant.
$readI53FromI64: (ptr) => {
return HEAPU32[ptr>>2] + HEAP32[ptr+4>>2] * 4294967296;
return {{{ makeGetValue('ptr', 0, 'u32') }}} + {{{ makeGetValue('ptr', 4, 'i32') }}} * 4294967296;
},

// Reads a 64-bit unsigned integer from the WebAssembly heap and
// converts it to a JavaScript Number, which can represent 53 integer bits precisely.
// TODO: Add $readI53FromU64Signaling() variant.
$readI53FromU64: (ptr) => {
return HEAPU32[ptr>>2] + HEAPU32[ptr+4>>2] * 4294967296;
return {{{ makeGetValue('ptr', 0, 'u32') }}} + {{{ makeGetValue('ptr', 4, 'u32') }}} * 4294967296;
},

// Converts the given signed 32-bit low-high pair to a JavaScript Number that
Expand Down
4 changes: 3 additions & 1 deletion src/library_math.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ addToLibrary({
emscripten_math_cosh: (x) => Math.cosh(x),
emscripten_math_hypot: (count, varargs) => {
var args = [];
for (var i = 0; i < count; ++i) args.push(HEAPF64[(varargs>>3) + i]);
for (var i = 0; i < count; ++i) {
args.push({{{ makeGetValue('varargs', `i * ${getNativeTypeSize('double')}`, 'double') }}});
}
return Math.hypot.apply(null, args);
},
emscripten_math_sin: (x) => Math.sin(x),
Expand Down
5 changes: 3 additions & 2 deletions src/library_nodefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,17 +269,18 @@ addToLibrary({
}
},
read(stream, buffer, offset, length, position) {
//err(`nodefs read: offset=${offset} length=${length} position=${position}`);
// Node.js < 6 compatibility: node errors on 0 length reads
if (length === 0) return 0;
try {
return fs.readSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position);
return fs.readSync(stream.nfd, new Int8Array(buffer.buffer, offset, length), { position: position });
} catch (e) {
throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
}
},
write(stream, buffer, offset, length, position) {
try {
return fs.writeSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position);
return fs.writeSync(stream.nfd, new Int8Array(buffer.buffer, offset, length), { position: position });
} catch (e) {
throw new FS.ErrnoError(NODEFS.convertNodeCode(e));
}
Expand Down
4 changes: 2 additions & 2 deletions src/library_noderawfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ addToLibrary({
}
var seeking = typeof position != 'undefined';
if (!seeking && stream.seekable) position = stream.position;
var bytesRead = fs.readSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position);
var bytesRead = fs.readSync(stream.nfd, new Int8Array(buffer.buffer, offset, length), { position: position });
// update position marker when non-seeking
if (!seeking) stream.position += bytesRead;
return bytesRead;
Expand All @@ -164,7 +164,7 @@ addToLibrary({
}
var seeking = typeof position != 'undefined';
if (!seeking && stream.seekable) position = stream.position;
var bytesWritten = fs.writeSync(stream.nfd, Buffer.from(buffer.buffer), offset, length, position);
var bytesWritten = fs.writeSync(stream.nfd, new Int8Array(buffer.buffer, offset, length), { position: position });
// update position marker when non-seeking
if (!seeking) stream.position += bytesWritten;
return bytesWritten;
Expand Down
4 changes: 4 additions & 0 deletions src/library_pipefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,12 @@ addToLibrary({
currentLength += bucket.offset - bucket.roffset;
}

#if !MEMORY64
#if PTHREADS
assert(buffer instanceof ArrayBuffer || buffer instanceof SharedArrayBuffer || ArrayBuffer.isView(buffer));
#else
assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer));
#endif
#endif
var data = buffer.subarray(offset, offset + length);

Expand Down Expand Up @@ -149,10 +151,12 @@ addToLibrary({
write(stream, buffer, offset, length, position /* ignored */) {
var pipe = stream.node.pipe;

#if !MEMORY64
#if PTHREADS
assert(buffer instanceof ArrayBuffer || buffer instanceof SharedArrayBuffer || ArrayBuffer.isView(buffer));
#else
assert(buffer instanceof ArrayBuffer || ArrayBuffer.isView(buffer));
#endif
#endif
var data = buffer.subarray(offset, offset + length);

Expand Down
31 changes: 24 additions & 7 deletions src/library_syscall.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,30 @@ var SyscallsLibrary = {
#if ASSERTIONS
assert(SYSCALLS.varargs != undefined);
#endif
var ret = {{{ makeGetValue('SYSCALLS.varargs', 0, 'i32') }}};
SYSCALLS.varargs += 4;
var ret = {{{ makeGetValue('SYSCALLS.varargs', '-4', 'i32') }}};
#if SYSCALL_DEBUG
dbg(` (raw: "${ret}")`);
#endif
return ret;
},
#if MEMORY64
getp() {
#if ASSERTIONS
assert(SYSCALLS.varargs != undefined);
#endif
var ret = {{{ makeGetValue('SYSCALLS.varargs', 0, '*') }}};
SYSCALLS.varargs += {{{ POINTER_SIZE }}};
#if SYSCALL_DEBUG
dbg(` (raw: "${ret}")`);
#endif
return ret;
},
#else
getp() { return SYSCALLS.get() },
#endif
getStr(ptr) {
var ret = UTF8ToString(ptr);
#if SYSCALL_DEBUG
Expand Down Expand Up @@ -216,7 +233,7 @@ var SyscallsLibrary = {
if (!stream.tty) return -{{{ cDefs.ENOTTY }}};
if (stream.tty.ops.ioctl_tcgets) {
var termios = stream.tty.ops.ioctl_tcgets(stream);
var argp = SYSCALLS.get();
var argp = SYSCALLS.getp();
{{{ makeSetValue('argp', C_STRUCTS.termios.c_iflag, 'termios.c_iflag || 0', 'i32') }}};
{{{ makeSetValue('argp', C_STRUCTS.termios.c_oflag, 'termios.c_oflag || 0', 'i32') }}};
{{{ makeSetValue('argp', C_STRUCTS.termios.c_cflag, 'termios.c_cflag || 0', 'i32') }}};
Expand All @@ -242,7 +259,7 @@ var SyscallsLibrary = {
case {{{ cDefs.TCSETSF }}}: {
if (!stream.tty) return -{{{ cDefs.ENOTTY }}};
if (stream.tty.ops.ioctl_tcsets) {
var argp = SYSCALLS.get();
var argp = SYSCALLS.getp();
var c_iflag = {{{ makeGetValue('argp', C_STRUCTS.termios.c_iflag, 'i32') }}};
var c_oflag = {{{ makeGetValue('argp', C_STRUCTS.termios.c_oflag, 'i32') }}};
var c_cflag = {{{ makeGetValue('argp', C_STRUCTS.termios.c_cflag, 'i32') }}};
Expand All @@ -257,7 +274,7 @@ var SyscallsLibrary = {
}
case {{{ cDefs.TIOCGPGRP }}}: {
if (!stream.tty) return -{{{ cDefs.ENOTTY }}};
var argp = SYSCALLS.get();
var argp = SYSCALLS.getp();
{{{ makeSetValue('argp', 0, 0, 'i32') }}};
return 0;
}
Expand All @@ -266,7 +283,7 @@ var SyscallsLibrary = {
return -{{{ cDefs.EINVAL }}}; // not supported
}
case {{{ cDefs.FIONREAD }}}: {
var argp = SYSCALLS.get();
var argp = SYSCALLS.getp();
return FS.ioctl(stream, op, argp);
}
case {{{ cDefs.TIOCGWINSZ }}}: {
Expand All @@ -275,7 +292,7 @@ var SyscallsLibrary = {
if (!stream.tty) return -{{{ cDefs.ENOTTY }}};
if (stream.tty.ops.ioctl_tiocgwinsz) {
var winsize = stream.tty.ops.ioctl_tiocgwinsz(stream.tty);
var argp = SYSCALLS.get();
var argp = SYSCALLS.getp();
{{{ makeSetValue('argp', 0, 'winsize[0]', 'i16') }}};
{{{ makeSetValue('argp', 2, 'winsize[1]', 'i16') }}};
}
Expand Down Expand Up @@ -770,7 +787,7 @@ var SyscallsLibrary = {
return 0;
}
case {{{ cDefs.F_GETLK }}}: {
var arg = SYSCALLS.get();
var arg = SYSCALLS.getp();
var offset = {{{ C_STRUCTS.flock.l_type }}};
// We're always unlocked.
{{{ makeSetValue('arg', 'offset', cDefs.F_UNLCK, 'i16') }}};
Expand Down
4 changes: 2 additions & 2 deletions src/library_wasmfs_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ addToLibrary({
try {
// TODO: Cache open file descriptors to guarantee that opened files will
// still exist when we try to access them.
let nread = fs.readSync(fd, HEAPU8, buf_p, len, pos);
let nread = fs.readSync(fd, new Int8Array(HEAPU8.buffer, buf_p, len), { position: pos });
{{{ makeSetValue('nread_p', 0, 'nread', 'i32') }}};
} catch (e) {
if (!e.code) throw e;
Expand All @@ -201,7 +201,7 @@ addToLibrary({
try {
// TODO: Cache open file descriptors to guarantee that opened files will
// still exist when we try to access them.
let nwritten = fs.writeSync(fd, HEAPU8, buf_p, len, pos);
let nwritten = fs.writeSync(fd, new Int8Array(HEAPU8.buffer, buf_p, len), { position: pos });
{{{ makeSetValue('nwritten_p', 0, 'nwritten', 'i32') }}};
} catch (e) {
if (!e.code) throw e;
Expand Down
6 changes: 5 additions & 1 deletion src/preamble_minimal.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,15 @@ function updateMemoryViews() {
#if SUPPORT_BIG_ENDIAN
{{{ maybeExport('HEAP_DATA_VIEW') }}} HEAP_DATA_VIEW = new DataView(b);
#endif
#if MEMORY64 && MAXIMUM_MEMORY > FOUR_GB
#include "runtime_view_proxy.js"
#else
{{{ maybeExport('HEAP8') }}} HEAP8 = new Int8Array(b);
{{{ maybeExport('HEAP16') }}} HEAP16 = new Int16Array(b);
{{{ maybeExport('HEAP32') }}} HEAP32 = new Int32Array(b);
{{{ maybeExport('HEAPU8') }}} HEAPU8 = new Uint8Array(b);
{{{ maybeExport('HEAPU16') }}} HEAPU16 = new Uint16Array(b);
#endif
{{{ maybeExport('HEAP32') }}} HEAP32 = new Int32Array(b);
{{{ maybeExportIfAudioWorklet('HEAPU32') }}} HEAPU32 = new Uint32Array(b);
{{{ maybeExportIfAudioWorklet('HEAPF32') }}} HEAPF32 = new Float32Array(b);
{{{ maybeExport('HEAPF64') }}} HEAPF64 = new Float64Array(b);
Expand Down
Loading

0 comments on commit 8f871c3

Please sign in to comment.