diff --git a/emcc.py b/emcc.py index e14d3cdc85c08..6a3959b401f19 100755 --- a/emcc.py +++ b/emcc.py @@ -1176,6 +1176,11 @@ def check(input_file): if shared.Settings.BINARYEN_PASSES: shared.Settings.BINARYEN_PASSES += ',' shared.Settings.BINARYEN_PASSES += 'safe-heap' + # we will include the mem init data in the wasm, when we don't need the + # mem init file to be loadable by itself + shared.Settings.MEM_INIT_IN_WASM = 'asmjs' not in shared.Settings.BINARYEN_METHOD and \ + 'interpret-asm2wasm' not in shared.Settings.BINARYEN_METHOD and \ + not shared.Settings.USE_PTHREADS # wasm outputs are only possible with a side wasm if target.endswith(WASM_ENDINGS): @@ -1709,7 +1714,7 @@ def repl(m): if not shared.Settings.BINARYEN or 'asmjs' in shared.Settings.BINARYEN_METHOD or 'interpret-asm2wasm' in shared.Settings.BINARYEN_METHOD: return 'memoryInitializer = "%s";' % shared.JS.get_subresource_location(memfile, embed_memfile(options)) else: - return 'memoryInitializer = null;' + return '' src = re.sub(shared.JS.memory_initializer_pattern, repl, open(final).read(), count=1) open(final + '.mem.js', 'w').write(src) final += '.mem.js' @@ -2299,8 +2304,7 @@ def do_binaryen(target, asm_target, options, memfile, wasm_binary_target, cmd.append(shared.Building.opt_level_to_str(options.opt_level, options.shrink_level)) # import mem init file if it exists, and if we will not be using asm.js as a binaryen method (as it needs the mem init file, of course) mem_file_exists = options.memory_init_file and os.path.exists(memfile) - ok_binaryen_method = 'asmjs' not in shared.Settings.BINARYEN_METHOD and 'interpret-asm2wasm' not in shared.Settings.BINARYEN_METHOD - import_mem_init = mem_file_exists and ok_binaryen_method + import_mem_init = mem_file_exists and shared.Settings.MEM_INIT_IN_WASM if import_mem_init: cmd += ['--mem-init=' + memfile] if not shared.Settings.RELOCATABLE: diff --git a/src/postamble.js b/src/postamble.js index cb573b865abae..504d2aa08fe47 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -6,6 +6,7 @@ Module['asm'] = asm; {{{ maybeExport('FS') }}} {{{ maybeExport('GL') }}} +#if MEM_INIT_IN_WASM == 0 #if MEM_INIT_METHOD == 2 #if USE_PTHREADS if (memoryInitializer && !ENVIRONMENT_IS_PTHREAD) (function(s) { @@ -110,6 +111,7 @@ if (memoryInitializer) { } } #endif +#endif // MEM_INIT_IN_WASM == 0 #if CYBERDWARF Module['cyberdwarf'] = _cyberdwarf_Debugger(cyberDWARFFile); diff --git a/src/preamble.js b/src/preamble.js index 7e17e74888ebc..8c8b7b4e2c667 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -2106,10 +2106,12 @@ function integrateWasmJS() { var oldView = new Int8Array(oldBuffer); var newView = new Int8Array(newBuffer); +#if MEM_INIT_IN_WASM == 0 // If we have a mem init file, do not trample it if (!memoryInitializer) { oldView.set(newView.subarray(Module['STATIC_BASE'], Module['STATIC_BASE'] + Module['STATIC_BUMP']), Module['STATIC_BASE']); } +#endif newView.set(oldView); updateGlobalBuffer(newBuffer); diff --git a/src/settings.js b/src/settings.js index 87b0280d2fdc4..e5a97c07c480f 100644 --- a/src/settings.js +++ b/src/settings.js @@ -861,5 +861,7 @@ var WASM_BINARY_FILE = ''; // name of the file containing wasm binary, if releva var ASMJS_CODE_FILE = ''; // name of the file containing asm.js, if relevant var SOURCE_MAP_BASE = ''; // Base URL the source mapfile, if relevant +var MEM_INIT_IN_WASM = 0; // for internal use only + var SUPPORT_BASE64_EMBEDDING = 0; // If set to 1, src/base64Utils.js will be included in the bundle. // This is set internally when needed (SINGLE_FILE) diff --git a/tests/pthread/test_pthread_global_data_initialization.c b/tests/pthread/test_pthread_global_data_initialization.c new file mode 100644 index 0000000000000..4b8afbbaf9cc4 --- /dev/null +++ b/tests/pthread/test_pthread_global_data_initialization.c @@ -0,0 +1,36 @@ +#include +#include +#include + +int globalData = 1; + +void *thread_main(void *arg) +{ + EM_ASM(Module.print('hello from pthread 1: ' + $0), globalData); + assert(globalData == 10); + + globalData = 20; + EM_ASM(Module.print('hello from pthread 2: ' + $0), globalData); + assert(globalData == 20); + return 0; +} + +int main() +{ + EM_ASM(Module.print('hello from main 1: ' + $0), globalData); + assert(globalData == 1); + + globalData = 10; + EM_ASM(Module.print('hello from main 2: ' + $0), globalData); + assert(globalData == 10); + + pthread_t thread; + pthread_create(&thread, NULL, thread_main, NULL); + pthread_join(thread, 0); + + EM_ASM(Module.print('hello from main 3: ' + $0), globalData); + assert(globalData == 20); +#ifdef REPORT_RESULT + REPORT_RESULT(globalData); +#endif +} diff --git a/tests/test_browser.py b/tests/test_browser.py index 0ef8ef59d2b67..e287029e5f1b2 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -3329,6 +3329,12 @@ def test_pthread_call_async_on_main_thread(self): self.btest(path_from_root('tests', 'pthread', 'call_async_on_main_thread.c'), expected='7', args=['-O3', '-s', 'USE_PTHREADS=1', '-DPROXY_TO_PTHREAD=0', '--js-library', path_from_root('tests', 'pthread', 'call_async_on_main_thread.js')]) self.btest(path_from_root('tests', 'pthread', 'call_async_on_main_thread.c'), expected='7', args=['-Oz', '-DPROXY_TO_PTHREAD=0', '--js-library', path_from_root('tests', 'pthread', 'call_async_on_main_thread.js')]) + # Tests that spawning a new thread does not cause a reinitialization of the global data section of the application memory area. + def test_pthread_global_data_initialization(self): + for mem_init_mode in [[], ['--memory-init-file', '0'], ['--memory-init-file', '1']]: + for args in [[], ['-O3']]: + self.btest(path_from_root('tests', 'pthread', 'test_pthread_global_data_initialization.c'), expected='20', args=args+mem_init_mode+['-s', 'USE_PTHREADS=1', '-s', 'PROXY_TO_PTHREAD=1'], also_wasm=False) + # test atomicrmw i64 def test_atomicrmw_i64(self): Popen([PYTHON, EMCC, path_from_root('tests', 'atomicrmw_i64.ll'), '-s', 'USE_PTHREADS=1', '-s', 'IN_TEST_HARNESS=1', '-o', 'test.html']).communicate()