Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,7 @@ jobs:
other.test_min_node_version
other.test_node_emscripten_num_logical_cores
other.test_js_base64_api
other.test_memory_growth
core2.test_hello_world
core2.test_pthread_create
core2.test_i64_invoke_bigint
Expand Down
26 changes: 26 additions & 0 deletions src/runtime_common.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,37 @@ var runtimeExited = false;
};
}}}

#if ALLOW_MEMORY_GROWTH
var resizeableMemoryBuffer = 0;
#endif

function updateMemoryViews() {
#if RUNTIME_DEBUG
dbg(`updateMemoryViews: initial=${!HEAP8} size=${wasmMemory.buffer.byteLength}`);
#endif
#if ALLOW_MEMORY_GROWTH
if (resizeableMemoryBuffer) {
// If we already have a heap that is resizeable we
// don't need to do anything in updateMemoryViews.
return;
}
#if GROWABLE_ARRAYBUFFERS
var b = wasmMemory.toResizableBuffer();
#else
var b = wasmMemory.buffer;
try {
// This method may be missing or could fail with `Memory must have a maximum`
b = wasmMemory.toResizableBuffer();
resizeableMemoryBuffer = true;
} catch {}
#endif
#else
#if ASSERTIONS
// When memory growth is disabled this function should be called
// exacltly once.
assert(!HEAP8, 'updateMemoryViews should only be called once when ALLOW_MEMORY_GROWTH=0');
#endif
var b = wasmMemory.buffer;
#endif
{{{ maybeExportHeap('HEAP8') }}}HEAP8 = new Int8Array(b);
{{{ maybeExportHeap('HEAP16') }}}HEAP16 = new Int16Array(b);
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_hello_O0.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 23248,
"a.out.js.gz": 8396,
"a.out.js": 23344,
"a.out.js.gz": 8443,
"a.out.nodebug.wasm": 15115,
"a.out.nodebug.wasm.gz": 7464,
"total": 38363,
"total_gz": 15860,
"total": 38459,
"total_gz": 15907,
"sent": [
"fd_write"
],
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_mem_O3_grow.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 4541,
"a.out.js.gz": 2193,
"a.out.js": 4595,
"a.out.js.gz": 2221,
"a.out.nodebug.wasm": 5261,
"a.out.nodebug.wasm.gz": 2419,
"total": 9802,
"total_gz": 4612,
"total": 9856,
"total_gz": 4640,
"sent": [
"a (emscripten_resize_heap)"
],
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_mem_O3_grow_standalone.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 4012,
"a.out.js.gz": 1933,
"a.out.js": 4064,
"a.out.js.gz": 1956,
"a.out.nodebug.wasm": 5641,
"a.out.nodebug.wasm.gz": 2659,
"total": 9653,
"total_gz": 4592,
"total": 9705,
"total_gz": 4615,
"sent": [
"args_get",
"args_sizes_get",
Expand Down
3 changes: 3 additions & 0 deletions test/codesize/test_codesize_minimal_O0.expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,9 @@ var runtimeInitialized = false;


function updateMemoryViews() {
// When memory growth is disabled this function should be called
// exacltly once.
assert(!HEAP8, 'updateMemoryViews should only be called once when ALLOW_MEMORY_GROWTH=0');
var b = wasmMemory.buffer;
HEAP8 = new Int8Array(b);
HEAP16 = new Int16Array(b);
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_minimal_O0.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 18596,
"a.out.js.gz": 6718,
"a.out.js": 18687,
"a.out.js.gz": 6766,
"a.out.nodebug.wasm": 1015,
"a.out.nodebug.wasm.gz": 602,
"total": 19611,
"total_gz": 7320,
"total": 19702,
"total_gz": 7368,
"sent": [],
"imports": [],
"exports": [
Expand Down
8 changes: 4 additions & 4 deletions test/codesize/test_codesize_minimal_pthreads_memgrowth.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"a.out.js": 7357,
"a.out.js.gz": 3627,
"a.out.js": 7416,
"a.out.js.gz": 3658,
"a.out.nodebug.wasm": 19064,
"a.out.nodebug.wasm.gz": 8804,
"total": 26421,
"total_gz": 12431,
"total": 26480,
"total_gz": 12462,
"sent": [
"a (memory)",
"b (exit)",
Expand Down
14 changes: 7 additions & 7 deletions test/codesize/test_unoptimized_code_size.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"hello_world.js": 54902,
"hello_world.js.gz": 17283,
"hello_world.js": 55082,
"hello_world.js.gz": 17353,
"hello_world.wasm": 15115,
"hello_world.wasm.gz": 7464,
"no_asserts.js": 25903,
"no_asserts.js.gz": 8768,
"no_asserts.wasm": 12229,
"no_asserts.wasm.gz": 6004,
"strict.js": 52659,
"strict.js.gz": 16513,
"strict.js": 52839,
"strict.js.gz": 16584,
"strict.wasm": 15115,
"strict.wasm.gz": 7457,
"total": 175923,
"total_gz": 63489
"strict.wasm.gz": 7461,
"total": 176283,
"total_gz": 63634
}
16 changes: 10 additions & 6 deletions test/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,14 @@ def get_deno():
return get_engine(engine_is_deno)


def check_node_version(major, minor=0, revision=0):
nodejs = get_nodejs()
if not nodejs:
return False
version = shared.get_node_version(nodejs)
return version >= (major, minor, revision)


def clean_js_output(output):
"""Cleanup the JS output prior to running verification steps on it.

Expand Down Expand Up @@ -532,14 +540,10 @@ def require_wasm64(self):
self.fail('either d8, node >= 24 or deno required to run wasm64 tests. Use EMTEST_SKIP_WASM64 to skip')

def try_require_node_version(self, major, minor=0, revision=0):
nodejs = get_nodejs()
if not nodejs:
return False
version = shared.get_node_version(nodejs)
if version < (major, minor, revision):
if not check_node_version(major, minor, revision):
return False

self.require_engine(nodejs)
self.require_engine(get_nodejs())
return True

def require_wasm_legacy_eh(self):
Expand Down
43 changes: 26 additions & 17 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
TEST_ROOT,
WEBIDL_BINDER,
RunnerCore,
check_node_version,
copy_asset,
copytree,
create_file,
Expand Down Expand Up @@ -6426,28 +6427,36 @@ def test_file_packager_huge(self):
self.assertContained(MESSAGE, err)
self.clear()

@parameterized({
'': (True,),
'wasm2js': (False,),
})
def test_massive_alloc(self, wasm):
@also_with_wasm2js
def test_memory_growth(self):
create_file('main.c', r'''
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <emscripten/em_asm.h>
#include <emscripten/console.h>

int main() {
volatile long x = (long)malloc(1024 * 1024 * 1400);
return x == 0; // can't alloc it, but don't fail catastrophically, expect null
// Report whether we are running with `toResizableBuffer` enabled.
EM_ASM(out('resizable memory buffers:', Boolean(wasmMemory.toResizableBuffer)));

void* x = malloc(256 * 1024 * 1024);
assert(x != NULL);
// Have JS use some of the memory expanded range
char* str = (char*)x - 100;
strcpy(str, "Hello, world!");
emscripten_out(str);
return 0;
}
''')
cmd = [EMCC, 'main.c', '-sALLOW_MEMORY_GROWTH', '-sINITIAL_MEMORY=16MB']
if not wasm:
cmd += ['-sWASM=0']
self.run_process(cmd)
# just care about message regarding allocating over 1GB of memory
output = self.run_js('a.out.js')
if not wasm:
self.assertContained('Warning: Enlarging memory arrays, this is not fast! 16777216,1468137472\n', output)
''')
output = self.do_runf('main.c', 'Hello, world!\n', cflags=['-sALLOW_MEMORY_GROWTH'])
if self.is_wasm2js():
self.assertContained('Warning: Enlarging memory arrays, this is not fast! 16908288,268566528\n', output)

if check_node_version(26):
self.assertContained('resizable memory buffers: true\n', output)
else:
self.assertContained('resizable memory buffers: false\n', output)

@also_with_wasm2js
@parameterized({
Expand Down
2 changes: 1 addition & 1 deletion tools/acorn-optimizer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ function growableHeap(ast) {
if (
!(
node.id.type === 'Identifier' &&
(node.id.name === 'growMemViews' || node.id.name === 'LE_HEAP_UPDATE')
(node.id.name === 'growMemViews' || node.id.name === 'updateMemoryViews' || node.id.name === 'LE_HEAP_UPDATE')
)
) {
c(node.body);
Expand Down
1 change: 1 addition & 0 deletions tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,7 @@ def limit_incoming_module_api():

if settings.PURE_WASI:
settings.STANDALONE_WASM = 1
settings.ALLOW_MEMORY_GROWTH = 1
settings.WASM_BIGINT = 1
# WASI does not support Emscripten (JS-based) exception catching, which the
# JS-based longjmp support also uses. Emscripten EH is by default disabled
Expand Down
Loading