diff --git a/src/library.js b/src/library.js index ac7eb0b857505..4324e8974bb7c 100644 --- a/src/library.js +++ b/src/library.js @@ -523,9 +523,7 @@ LibraryManager.library = { #endif ], emscripten_resize_heap: function(requestedSize) { -#if CAN_ADDRESS_2GB requestedSize = requestedSize >>> 0; -#endif #if ALLOW_MEMORY_GROWTH == 0 #if ABORTING_MALLOC abortOnCannotGrowMemory(requestedSize); diff --git a/tests/browser/test_2GB_fail.cpp b/tests/browser/test_2GB_fail.cpp new file mode 100644 index 0000000000000..6a16d9bbd4687 --- /dev/null +++ b/tests/browser/test_2GB_fail.cpp @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +void* allocation; + +int main() { + const int CHUNK_SIZE = 100 * 1024 * 1024; + const int NUM_CHUNKS = 31; // total allocation will be over 3GB + + puts("allocating"); + + for (int i = 0; i < NUM_CHUNKS; i++) { + printf("alloc %d\n", i); + allocation = malloc(CHUNK_SIZE); + if (!allocation) { + assert(i <= 20); // can't get to 2GB + puts("expected allocation failure"); + return 0; + } + } + + puts("UNEXPECTED"); +} diff --git a/tests/browser/test_2GB_fail.txt b/tests/browser/test_2GB_fail.txt new file mode 100644 index 0000000000000..2b677ff103584 --- /dev/null +++ b/tests/browser/test_2GB_fail.txt @@ -0,0 +1 @@ +expected allocation failure diff --git a/tests/browser/test_4GB.cpp b/tests/browser/test_4GB.cpp new file mode 100644 index 0000000000000..d22c153ddc0b0 --- /dev/null +++ b/tests/browser/test_4GB.cpp @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +int main() { + const int CHUNK_SIZE = 100 * 1024 * 1024; + const int NUM_CHUNKS = 31; // total allocation will be over 3GB + + std::vector> chunks; + chunks.resize(NUM_CHUNKS); + + puts("allocating"); + + for (int i = 0; i < NUM_CHUNKS; i++) { + printf("alloc %d\n", i); + chunks[i].resize(CHUNK_SIZE); + } + + puts("testing"); + + for (int i = 0; i < NUM_CHUNKS; i++) { + printf("test %d\n", i); + chunks[i][i] = i; + int fromJS = EM_ASM_INT({ + return HEAP8[$0]; + }, &chunks[i][i]); + printf("wrote %d in C, read %d from JS\n", i, fromJS); + EM_ASM_INT({ + HEAP8[$0] = 2 * $1; + }, &chunks[i][i], i); + int fromC = chunks[i][i]; + printf("wrote %d in JS, read %d from C\n", 2 * i, fromC); + } + + puts("success"); +} + diff --git a/tests/browser/test_4GB.txt b/tests/browser/test_4GB.txt new file mode 100644 index 0000000000000..9fec1a33efbf7 --- /dev/null +++ b/tests/browser/test_4GB.txt @@ -0,0 +1,127 @@ +allocating +alloc 0 +alloc 1 +alloc 2 +alloc 3 +alloc 4 +alloc 5 +alloc 6 +alloc 7 +alloc 8 +alloc 9 +alloc 10 +alloc 11 +alloc 12 +alloc 13 +alloc 14 +alloc 15 +alloc 16 +alloc 17 +alloc 18 +alloc 19 +alloc 20 +alloc 21 +alloc 22 +alloc 23 +alloc 24 +alloc 25 +alloc 26 +alloc 27 +alloc 28 +alloc 29 +alloc 30 +testing +test 0 +wrote 0 in C, read 0 from JS +wrote 0 in JS, read 0 from C +test 1 +wrote 1 in C, read 1 from JS +wrote 2 in JS, read 2 from C +test 2 +wrote 2 in C, read 2 from JS +wrote 4 in JS, read 4 from C +test 3 +wrote 3 in C, read 3 from JS +wrote 6 in JS, read 6 from C +test 4 +wrote 4 in C, read 4 from JS +wrote 8 in JS, read 8 from C +test 5 +wrote 5 in C, read 5 from JS +wrote 10 in JS, read 10 from C +test 6 +wrote 6 in C, read 6 from JS +wrote 12 in JS, read 12 from C +test 7 +wrote 7 in C, read 7 from JS +wrote 14 in JS, read 14 from C +test 8 +wrote 8 in C, read 8 from JS +wrote 16 in JS, read 16 from C +test 9 +wrote 9 in C, read 9 from JS +wrote 18 in JS, read 18 from C +test 10 +wrote 10 in C, read 10 from JS +wrote 20 in JS, read 20 from C +test 11 +wrote 11 in C, read 11 from JS +wrote 22 in JS, read 22 from C +test 12 +wrote 12 in C, read 12 from JS +wrote 24 in JS, read 24 from C +test 13 +wrote 13 in C, read 13 from JS +wrote 26 in JS, read 26 from C +test 14 +wrote 14 in C, read 14 from JS +wrote 28 in JS, read 28 from C +test 15 +wrote 15 in C, read 15 from JS +wrote 30 in JS, read 30 from C +test 16 +wrote 16 in C, read 16 from JS +wrote 32 in JS, read 32 from C +test 17 +wrote 17 in C, read 17 from JS +wrote 34 in JS, read 34 from C +test 18 +wrote 18 in C, read 18 from JS +wrote 36 in JS, read 36 from C +test 19 +wrote 19 in C, read 19 from JS +wrote 38 in JS, read 38 from C +test 20 +wrote 20 in C, read 20 from JS +wrote 40 in JS, read 40 from C +test 21 +wrote 21 in C, read 21 from JS +wrote 42 in JS, read 42 from C +test 22 +wrote 22 in C, read 22 from JS +wrote 44 in JS, read 44 from C +test 23 +wrote 23 in C, read 23 from JS +wrote 46 in JS, read 46 from C +test 24 +wrote 24 in C, read 24 from JS +wrote 48 in JS, read 48 from C +test 25 +wrote 25 in C, read 25 from JS +wrote 50 in JS, read 50 from C +test 26 +wrote 26 in C, read 26 from JS +wrote 52 in JS, read 52 from C +test 27 +wrote 27 in C, read 27 from JS +wrote 54 in JS, read 54 from C +test 28 +wrote 28 in C, read 28 from JS +wrote 56 in JS, read 56 from C +test 29 +wrote 29 in C, read 29 from JS +wrote 58 in JS, read 58 from C +test 30 +wrote 30 in C, read 30 from JS +wrote 60 in JS, read 60 from C +success diff --git a/tests/runner.py b/tests/runner.py index 3c510e085f823..0d74e35037652 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -1140,6 +1140,26 @@ def do_run_from_file(self, src, expected_output, *args, **kwargs): logger.debug('do_run_from_file: %s' % src) self.do_run(open(src).read(), open(expected_output).read(), *args, **kwargs) + def do_run_in_out_file_test(self, *path, **kwargs): + test_path = path_from_root(*path) + + def find_files(*ext_list): + ret = None + count = 0 + for ext in ext_list: + if os.path.isfile(test_path + ext): + ret = test_path + ext + count += 1 + assert count > 0, ("No file found at {} with extension {}" + .format(test_path, ext_list)) + assert count <= 1, ("Test file {} found with multiple valid extensions {}" + .format(test_path, ext_list)) + return ret + + src = find_files('.c', '.cpp') + output = find_files('.out', '.txt') + self.do_run_from_file(src, output, **kwargs) + ## Does a complete test - builds, runs, checks output, etc. def do_run(self, src, expected_output, args=[], output_nicerizer=None, no_build=False, main_file=None, additional_files=[], diff --git a/tests/test_browser.py b/tests/test_browser.py index cf68332f38d2b..aefc4c5a9588c 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -22,7 +22,7 @@ from runner import BrowserCore, path_from_root, has_browser, EMTEST_BROWSER, no_fastcomp, no_wasm_backend, create_test_file, parameterized, ensure_dir from tools import system_libs -from tools.shared import PYTHON, EMCC, WINDOWS, FILE_PACKAGER, PIPE, SPIDERMONKEY_ENGINE, JS_ENGINES +from tools.shared import PYTHON, EMCC, WINDOWS, FILE_PACKAGER, PIPE, SPIDERMONKEY_ENGINE, V8_ENGINE, JS_ENGINES from tools.shared import try_delete, run_process, run_js, Building try: @@ -5002,3 +5002,30 @@ def test_pthread_modularize_export_name(self): def test_system(self): self.btest(path_from_root('tests', 'system.c'), '0') + + @no_fastcomp('only upstream supports 4GB') + @no_firefox('no 4GB support yet') + def test_zzz_zzz_4GB(self): + # TODO Convert to an actual browser test when it reaches stable. + # For now, keep this in browser as this suite runs serially, which + # means we don't compete for memory with anything else (and run it + # at the very very end, to reduce the risk of it OOM-killing the + # browser). + + # test that we can allocate in the 2-4GB range, if we enable growth and + # set the max appropriately + self.emcc_args += ['-O2', '-s', 'ALLOW_MEMORY_GROWTH', '-s', 'MAXIMUM_MEMORY=4GB', '-s', 'ASSERTIONS'] + self.do_run_in_out_file_test('tests', 'browser', 'test_4GB', js_engines=[V8_ENGINE]) + + @no_fastcomp('only upstream supports 4GB') + def test_zzz_zzz_2GB_fail(self): + # TODO Convert to an actual browser test when it reaches stable. + # For now, keep this in browser as this suite runs serially, which + # means we don't compete for memory with anything else (and run it + # at the very very end, to reduce the risk of it OOM-killing the + # browser). + + # test that growth doesn't go beyond 2GB without the max being set for that, + # and that we can catch an allocation failure exception for that + self.emcc_args += ['-O2', '-fexceptions', '-s', 'ALLOW_MEMORY_GROWTH', '-s', 'MAXIMUM_MEMORY=2GB', '-s', 'ASSERTIONS'] + self.do_run_in_out_file_test('tests', 'browser', 'test_2GB_fail', js_engines=[V8_ENGINE]) diff --git a/tests/test_core.py b/tests/test_core.py index 63c63ef1769d3..9dd5cea5fbd7c 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -317,26 +317,6 @@ def maybe_closure(self): return True return False - def do_run_in_out_file_test(self, *path, **kwargs): - test_path = path_from_root(*path) - - def find_files(*ext_list): - ret = None - count = 0 - for ext in ext_list: - if os.path.isfile(test_path + ext): - ret = test_path + ext - count += 1 - assert count > 0, ("No file found at {} with extension {}" - .format(test_path, ext_list)) - assert count <= 1, ("Test file {} found with multiple valid extensions {}" - .format(test_path, ext_list)) - return ret - - src = find_files('.c', '.cpp') - output = find_files('.out', '.txt') - self.do_run_from_file(src, output, **kwargs) - def verify_in_strict_mode(self, filename): with open(filename) as infile: js = infile.read()