Skip to content

Commit 80e5cbf

Browse files
committed
Unify more of the minimal runtime and normal runtime initialization code.
This is a first step in trying to unify more of the code used by minimal runtime and the normal runtime and also move all addOn* functions into a library. First, make the call to the static constructors use the same code for both modes. With this change, it becomes necessary to have an injection point that runs before ctors and after ctors. To achieved that, I've replaced the unused ATMAIN with new ATPOSTINIT code injection point. The new ATPOSTINIT is similar to the old ATMAIN in that it runs after the static constructors, but it now runs even if there is no main function. Second, the FS initialization is now split into two parts (similar to how it used to be before a refactoring). 1) atInit the std<X> stream are setup. This allows ctors to use printf etc. 2) atPostInit the FS is locked down as late as possible but before main is run. Third, switch embind code generation to use the POSTINIT so it can run after the ctors have setup the bindings. Fourth, minimal runtime changes slightly in that ATINIT runs before ctors. This makes it consistent with the normal mode, but there is now POSTINIT if anyone needs the old behavior.
1 parent fd52f0a commit 80e5cbf

10 files changed

+56
-24
lines changed

src/jsifier.mjs

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import {
1111
ATEXITS,
1212
ATINITS,
13-
ATMAINS,
13+
ATPOSTINITS,
1414
defineI64Param,
1515
indentify,
1616
makeReturn64,
@@ -774,7 +774,7 @@ var proxiedFunctionTable = [
774774
asyncFuncs,
775775
libraryDefinitions: LibraryManager.libraryDefinitions,
776776
ATINITS: ATINITS.join('\n'),
777-
ATMAINS: STRICT ? '' : ATMAINS.join('\n'),
777+
ATPOSTINITS: ATPOSTINITS.join('\n'),
778778
ATEXITS: ATEXITS.join('\n'),
779779
}),
780780
);

src/lib/libembind_gen.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@ var LibraryEmbind = {
835835

836836
#if EMBIND_AOT
837837
$embindEmitAotJs__deps: ['$awaitingDependencies', '$throwBindingError', '$getTypeName', '$moduleDefinitions', '$JsPrinter'],
838-
$embindEmitAotJs__postset: 'addOnInit(embindEmitAotJs);',
838+
$embindEmitAotJs__postset: () => { addAtPostInit('embindEmitAotJs()'); },
839839
$embindEmitAotJs: () => {
840840
for (const typeId in awaitingDependencies) {
841841
throwBindingError(`Missing binding for type: '${getTypeName(typeId)}' typeId: ${typeId}`);
@@ -845,7 +845,7 @@ var LibraryEmbind = {
845845
},
846846
#else // EMBIND_AOT
847847
$embindEmitTypes__deps: ['$awaitingDependencies', '$throwBindingError', '$getTypeName', '$moduleDefinitions', '$TsPrinter'],
848-
$embindEmitTypes__postset: 'addOnInit(embindEmitTypes);',
848+
$embindEmitTypes__postset: () => { addAtPostInit('embindEmitTypes()'); },
849849
$embindEmitTypes: () => {
850850
for (const typeId in awaitingDependencies) {
851851
throwBindingError(`Missing binding for type: '${getTypeName(typeId)}' typeId: ${typeId}`);

src/lib/libfs.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ addToLibrary({
3636
addAtInit(`
3737
if (!Module['noFSInit'] && !FS.initialized)
3838
FS.init();
39-
FS.ignorePermissions = false;
40-
`)
39+
`);
40+
addAtPostInit('FS.ignorePermissions = false;');
4141
addAtExit('FS.quit();');
4242
return `
4343
FS.createPreloadedFile = FS_createPreloadedFile;

src/parseTools.mjs

+12-2
Original file line numberDiff line numberDiff line change
@@ -731,14 +731,22 @@ function makeEval(code) {
731731
return ret;
732732
}
733733

734-
export const ATMAINS = [];
735-
736734
export const ATINITS = [];
737735

736+
// Add code to run after the Wasm module is loaded, but before static
737+
// constructors and main (if applicable). The code will be executed before the
738+
// runtime `__ATINIT__` callbacks.
738739
function addAtInit(code) {
739740
ATINITS.push(code);
740741
}
741742

743+
export const ATPOSTINITS = [];
744+
745+
// Add code to run after static constructors, but before main (if applicable).
746+
function addAtPostInit(code) {
747+
ATPOSTINITS.push(code);
748+
}
749+
742750
export const ATEXITS = [];
743751

744752
function addAtExit(code) {
@@ -1086,6 +1094,7 @@ function ENVIRONMENT_IS_WORKER_THREAD() {
10861094
addToCompileTimeContext({
10871095
ATEXITS,
10881096
ATINITS,
1097+
ATPOSTINITS,
10891098
FOUR_GB,
10901099
LONG_TYPE,
10911100
POINTER_HEAP,
@@ -1104,6 +1113,7 @@ addToCompileTimeContext({
11041113
ENVIRONMENT_IS_WORKER_THREAD,
11051114
addAtExit,
11061115
addAtInit,
1116+
addAtPostInit,
11071117
asyncIf,
11081118
awaitIf,
11091119
buildStringArray,

src/parseTools_legacy.mjs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77
import {warn, addToCompileTimeContext} from './utility.mjs';
8-
import {ATMAINS, POINTER_SIZE, runIfMainThread} from './parseTools.mjs';
8+
import {ATPOSTINITS, POINTER_SIZE, runIfMainThread} from './parseTools.mjs';
99

1010
// Replaced (at least internally) with receiveI64ParamAsI53 that does
1111
// bounds checking.
@@ -42,7 +42,7 @@ const Runtime = {
4242
const runOnMainThread = runIfMainThread;
4343

4444
addToCompileTimeContext({
45-
ATMAINS,
45+
ATPOSTINITS,
4646
Runtime,
4747
makeMalloc,
4848
receiveI64ParamAsDouble,

src/postamble_minimal.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ function run() {
1313
emscriptenMemoryProfiler.onPreloadComplete();
1414
#endif
1515

16-
<<< ATMAINS >>>
17-
1816
#if PROXY_TO_PTHREAD
1917
// User requested the PROXY_TO_PTHREAD option, so call a stub main which
2018
// pthread_create()s a new thread that will call the user's real main() for
@@ -73,11 +71,13 @@ function initRuntime(wasmExports) {
7371
PThread.tlsInitFunctions.push(wasmExports['_emscripten_tls_init']);
7472
#endif
7573

74+
<<< ATINITS >>>
75+
7676
#if hasExportedSymbol('__wasm_call_ctors')
7777
wasmExports['__wasm_call_ctors']();
7878
#endif
7979

80-
<<< ATINITS >>>
80+
<<< ATPOSTINITS >>>
8181
}
8282

8383
// Initialize wasm (asynchronous)

src/preamble.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -217,16 +217,22 @@ function initRuntime() {
217217
#if RELOCATABLE
218218
callRuntimeCallbacks(__RELOC_FUNCS__);
219219
#endif
220+
220221
<<< ATINITS >>>
221222
callRuntimeCallbacks(__ATINIT__);
223+
224+
#if hasExportedSymbol('__wasm_call_ctors')
225+
wasmExports['__wasm_call_ctors']();
226+
#endif
227+
228+
<<< ATPOSTINITS >>>
222229
}
223230

224231
#if HAS_MAIN
225232
function preMain() {
226233
#if STACK_OVERFLOW_CHECK
227234
checkStackCookie();
228235
#endif
229-
<<< ATMAINS >>>
230236
callRuntimeCallbacks(__ATMAIN__);
231237
}
232238
#endif
@@ -951,10 +957,6 @@ function getWasmImports() {
951957
#endif
952958
#endif
953959

954-
#if hasExportedSymbol('__wasm_call_ctors')
955-
addOnInit(wasmExports['__wasm_call_ctors']);
956-
#endif
957-
958960
#if hasExportedSymbol('__wasm_apply_data_relocs')
959961
__RELOC_FUNCS__.push(wasmExports['__wasm_apply_data_relocs']);
960962
#endif

test/test_other.py

+24
Original file line numberDiff line numberDiff line change
@@ -8431,6 +8431,30 @@ def test_binaryen_stack_ir(self, opts, disable_and_enable):
84318431
self.assertLess(err.count(DISABLE), 2)
84328432
self.assertLess(err.count(ENABLE), 2)
84338433

8434+
@also_with_minimal_runtime
8435+
def test_run_order(self):
8436+
create_file('lib.js', r'''
8437+
addToLibrary({
8438+
foo__postset: () => {
8439+
addAtPostInit("console.log(`addAtPostInit`);");
8440+
addAtInit("console.log(`addAtInit`);");
8441+
},
8442+
foo: () => {},
8443+
});
8444+
''')
8445+
create_file('src.c', r'''
8446+
#include <stdio.h>
8447+
void foo();
8448+
__attribute__((constructor)) void ctor() {
8449+
printf("ctor\n");
8450+
}
8451+
int main() {
8452+
printf("main\n");
8453+
foo();
8454+
}
8455+
''')
8456+
self.do_runf('src.c', 'addAtInit\nctor\naddAtPostInit\nmain\n', emcc_args=['--js-library', 'lib.js'])
8457+
84348458
def test_override_js_execution_environment(self):
84358459
create_file('main.c', r'''
84368460
#include <emscripten.h>

tools/building.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -393,10 +393,7 @@ def acorn_optimizer(filename, passes, extra_info=None, return_output=False, work
393393
# evals ctors. if binaryen_bin is provided, it is the dir of the binaryen tool
394394
# for this, and we are in wasm mode
395395
def eval_ctors(js_file, wasm_file, debug_info):
396-
if settings.MINIMAL_RUNTIME:
397-
CTOR_ADD_PATTERN = f"wasmExports['{WASM_CALL_CTORS}']();" # TODO test
398-
else:
399-
CTOR_ADD_PATTERN = f"addOnInit(wasmExports['{WASM_CALL_CTORS}']);"
396+
CTOR_ADD_PATTERN = f"wasmExports['{WASM_CALL_CTORS}']();"
400397

401398
js = utils.read_file(js_file)
402399

tools/emscripten.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,7 @@ def update_settings_glue(wasm_file, metadata, base_metadata):
162162

163163
def apply_static_code_hooks(forwarded_json, code):
164164
code = shared.do_replace(code, '<<< ATINITS >>>', str(forwarded_json['ATINITS']))
165-
if settings.HAS_MAIN:
166-
code = shared.do_replace(code, '<<< ATMAINS >>>', str(forwarded_json['ATMAINS']))
165+
code = shared.do_replace(code, '<<< ATPOSTINITS >>>', str(forwarded_json['ATPOSTINITS']))
167166
if settings.EXIT_RUNTIME and (not settings.MINIMAL_RUNTIME or settings.HAS_MAIN):
168167
code = shared.do_replace(code, '<<< ATEXITS >>>', str(forwarded_json['ATEXITS']))
169168
return code

0 commit comments

Comments
 (0)