Skip to content

Commit

Permalink
Move loading of initial dynamic libraries to before run
Browse files Browse the repository at this point in the history
Previously we were calling `loadDylibs` in the `run` function but
we can call it earlier as soon as the main module is instantiated.  This
saves a little on code size since it relies on the existing
`runDependencies` mechanism.

Split out from #19390
  • Loading branch information
sbc100 committed May 25, 2023
1 parent 9663a7d commit 51912b9
Show file tree
Hide file tree
Showing 12 changed files with 69 additions and 78 deletions.
4 changes: 4 additions & 0 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2076,6 +2076,7 @@ def phase_linker_setup(options, state, newargs):
assert not settings.SIDE_MODULE
if settings.MAIN_MODULE == 1:
settings.INCLUDE_FULL_LIBRARY = 1
# Called from preamble.js once the main module is instantiated.
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$loadDylibs']
settings.REQUIRED_EXPORTS += ['malloc']

Expand Down Expand Up @@ -2195,6 +2196,9 @@ def phase_linker_setup(options, state, newargs):
else:
settings.REQUIRED_EXPORTS += ['emscripten_stack_init']

if settings.STACK_OVERFLOW_CHECK >= 2:
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$setStackLimits']

if settings.MODULARIZE:
if settings.PROXY_TO_WORKER:
exit_with_error('-sMODULARIZE is not compatible with --proxy-to-worker (if you want to run in a worker with -sMODULARIZE, you likely want to do the worker side setup manually)')
Expand Down
22 changes: 22 additions & 0 deletions src/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
// new function with an '_', it will not be found.

mergeInto(LibraryManager.library, {

$ptrToString: function(ptr) {
#if ASSERTIONS
assert(typeof ptr === 'number');
Expand Down Expand Up @@ -559,6 +560,27 @@ mergeInto(LibraryManager.library, {
return buf;
},

#if STACK_OVERFLOW_CHECK >= 2
#if MAIN_MODULE
$setStackLimits__deps: ['$setDylinkStackLimits'],
// Set stack limits used by binaryen's `StackCheck` pass.
#endif
$setStackLimits: function() {
#if RUNTIME_DEBUG
dbg(`setStackLimits: ${ptrToString(stackLow)}, ${ptrToString(stackHigh)}`);
#endif
var stackLow = _emscripten_stack_get_base();
var stackHigh = _emscripten_stack_get_end();
#if MAIN_MODULE
// With dynamic linking we could have any number of pre-loaded libraries
// that each need to have their stack limits set.
setDylinkStackLimits(stackLow, stackHigh);
#else
___set_stack_limits(stackLow, stackHigh);
#endif
},
#endif

$withStackSave__internal: true,
$withStackSave: function(f) {
var stack = stackSave();
Expand Down
24 changes: 10 additions & 14 deletions src/library_dylink.js
Original file line number Diff line number Diff line change
Expand Up @@ -767,12 +767,10 @@ var LibraryDylink = {
reportUndefinedSymbols();
}
#if STACK_OVERFLOW_CHECK >= 2
if (moduleExports['__set_stack_limits']) {
#if PTHREADS
// When we are on an uninitialized pthread we delay calling
// __set_stack_limits until $setDylinkStackLimits.
if (!ENVIRONMENT_IS_PTHREAD || runtimeInitialized)
#endif
// If the runtime has already been initialized we set the stack limits
// now. Othwerwise this is delayed until `setDylinkStackLimits` is
// called after initialization.
if (moduleExports['__set_stack_limits'] && runtimeInitialized) {
moduleExports['__set_stack_limits']({{{ to64('_emscripten_stack_get_base()') }}}, {{{ to64('_emscripten_stack_get_end()') }}});
}
#endif
Expand Down Expand Up @@ -871,20 +869,18 @@ var LibraryDylink = {
return loadModule();
},

#if STACK_OVERFLOW_CHECK >= 2 && PTHREADS
// With PTHREADS we load libraries before we are running a pthread and
// therefore before we have a stack. Instead we delay calling
// `__set_stack_limits` until we start running a thread. We also need to call
// this again for each new thread that the runs on a worker (since each thread
// has its own separate stack region).
#if STACK_OVERFLOW_CHECK >= 2
// Sometimes we load libraries before runtime initialization. In this case
// we delay calling __set_stack_limits (which must be called for each
// module).
$setDylinkStackLimits: function(stackTop, stackMax) {
for (var name in LDSO.loadedLibsByName) {
#if DYLINK_DEBUG
dbg(`setDylinkStackLimits[${name}]`);
dbg(`setDylinkStackLimits for '${name}'`);
#endif
var lib = LDSO.loadedLibsByName[name];
if (lib.exports['__set_stack_limits']) {
lib.exports['__set_stack_limits'](stackTop, stackMax);
lib.exports['__set_stack_limits']({{{ to64("stackTop") }}}, {{{ to64("stackMax") }}});
}
}
},
Expand Down
39 changes: 19 additions & 20 deletions src/library_pthread.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ var LibraryPThread = {
PThread.allocateUnusedWorker();
}
#endif
#if !MINIMAL_RUNTIME
// MINIMAL_RUNTIME takes care of calling loadWasmModuleToAllWorkers
// in postamble_minimal.js
addOnPreRun(() => {
addRunDependency('loading-workers')
PThread.loadWasmModuleToAllWorkers(() => removeRunDependency('loading-workers'));
});
#endif
#if MAIN_MODULE
PThread.outstandingPromises = {};
// Finished threads are threads that have finished running but we not yet
Expand Down Expand Up @@ -1043,39 +1051,30 @@ var LibraryPThread = {
return func.apply(null, emscripten_receive_on_main_thread_js_callArgs);
},

#if STACK_OVERFLOW_CHECK >= 2 && MAIN_MODULE
$establishStackSpace__deps: ['$setDylinkStackLimits'],
#endif
$establishStackSpace__internal: true,
$establishStackSpace: function() {
var pthread_ptr = _pthread_self();
var stackTop = {{{ makeGetValue('pthread_ptr', C_STRUCTS.pthread.stack, 'i32') }}};
var stackHigh = {{{ makeGetValue('pthread_ptr', C_STRUCTS.pthread.stack, 'i32') }}};
var stackSize = {{{ makeGetValue('pthread_ptr', C_STRUCTS.pthread.stack_size, 'i32') }}};
var stackMax = stackTop - stackSize;
var stackLow = stackHigh - stackSize;
#if PTHREADS_DEBUG
dbg('establishStackSpace: ' + ptrToString(stackTop) + ' -> ' + ptrToString(stackMax));
dbg('establishStackSpace: ' + ptrToString(stackHigh) + ' -> ' + ptrToString(stackLow));
#endif
#if ASSERTIONS
assert(stackTop != 0);
assert(stackMax != 0);
assert(stackTop > stackMax, 'stackTop must be higher then stackMax');
assert(stackHigh != 0);
assert(stackLow != 0);
assert(stackHigh > stackLow, 'stackHigh must be higher then stackLow');
#endif
// Set stack limits used by `emscripten/stack.h` function. These limits are
// cached in wasm-side globals to make checks as fast as possible.
_emscripten_stack_set_limits(stackTop, stackMax);
_emscripten_stack_set_limits(stackHigh, stackLow);

#if STACK_OVERFLOW_CHECK >= 2
// Set stack limits used by binaryen's `StackCheck` pass.
// TODO(sbc): Can this be combined with the above.
___set_stack_limits(stackTop, stackMax);
#if MAIN_MODULE
// With dynamic linking we could have any number of pre-loaded libraries
// that each need to have their stack limits set.
setDylinkStackLimits(stackTop, stackMax);
#endif
#endif
setStackLimits(stackHigh, stackLow);
#endif STACK_OVERFLOW_CHECK

// Call inside wasm module to set up the stack frame for this pthread in wasm module scope
stackRestore(stackTop);
stackRestore(stackHigh);

#if STACK_OVERFLOW_CHECK
// Write the stack cookie last, after we have set up the proper bounds and
Expand Down
28 changes: 0 additions & 28 deletions src/postamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,6 @@ function stackCheckInit() {
}
#endif

#if RELOCATABLE
var dylibsLoaded = false;
#if '$LDSO' in addedLibraryItems
LDSO.init();
#endif
#endif

#if MAIN_READS_PARAMS
function run(args = arguments_) {
#else
Expand All @@ -158,27 +151,6 @@ function run() {
stackCheckInit();
#endif

#if RELOCATABLE
if (!dylibsLoaded) {
// Loading of dynamic libraries needs to happen on each thread, so we can't
// use the normal __ATPRERUN__ mechanism.
#if MAIN_MODULE
loadDylibs();
#else
reportUndefinedSymbols();
#endif
dylibsLoaded = true;

// Loading dylibs can add run dependencies.
if (runDependencies > 0) {
#if RUNTIME_DEBUG
dbg('loadDylibs added run() dependencies, not running yet');
#endif
return;
}
}
#endif

#if WASM_WORKERS
if (ENVIRONMENT_IS_WASM_WORKER) {
#if MODULARIZE
Expand Down
2 changes: 1 addition & 1 deletion src/postamble_minimal.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function initRuntime(asm) {
_emscripten_stack_init();
writeStackCookie();
#if STACK_OVERFLOW_CHECK >= 2
___set_stack_limits(_emscripten_stack_get_base(), _emscripten_stack_get_end());
setStackLimits();
#endif
#endif

Expand Down
18 changes: 8 additions & 10 deletions src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,9 @@ function initRuntime() {
#endif

#if STACK_OVERFLOW_CHECK >= 2
#if RUNTIME_DEBUG
dbg('__set_stack_limits: ' + _emscripten_stack_get_base() + ', ' + _emscripten_stack_get_end());
#endif
___set_stack_limits(_emscripten_stack_get_base(), _emscripten_stack_get_end());
setStackLimits();
#endif

#if RELOCATABLE
callRuntimeCallbacks(__RELOC_FUNCS__);
#endif
Expand Down Expand Up @@ -980,6 +978,12 @@ function createWasm() {
}
#endif
mergeLibSymbols(exports, 'main')
#if '$LDSO' in addedLibraryItems
LDSO.init();
#endif
loadDylibs();
#elif RELOCATABLE
reportUndefinedSymbols();
#endif

#if MEMORY64
Expand Down Expand Up @@ -1047,13 +1051,7 @@ function createWasm() {
// We now have the Wasm module loaded up, keep a reference to the compiled module so we can post it to the workers.
wasmModule = module;
#endif

#if PTHREADS
PThread.loadWasmModuleToAllWorkers(() => removeRunDependency('wasm-instantiate'));
#else // singlethreaded build:
removeRunDependency('wasm-instantiate');
#endif // ~PTHREADS

return exports;
}
// wait for the pthread pool (if any)
Expand Down
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_hello_dylink.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
15060
15023
2 changes: 1 addition & 1 deletion test/other/metadce/test_metadce_minimal_pthreads.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
15415
15456
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
59630
59629
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size_no_asserts.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
33256
33255
2 changes: 1 addition & 1 deletion test/other/test_unoptimized_code_size_strict.js.size
Original file line number Diff line number Diff line change
@@ -1 +1 @@
58572
58571

0 comments on commit 51912b9

Please sign in to comment.