diff options
author | Alon Zakai <azakai@google.com> | 2020-04-08 13:59:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-08 13:59:21 -0700 |
commit | 2f9d019267bd792e1df09a00648eb4d8edb39ac1 (patch) | |
tree | 5542994773bf4d34a53bd938fa8c628cf3c8dd5f | |
parent | 95a66b5b3ad34b47703131207bbab739366408c4 (diff) | |
download | binaryen-2f9d019267bd792e1df09a00648eb4d8edb39ac1.tar.gz binaryen-2f9d019267bd792e1df09a00648eb4d8edb39ac1.tar.bz2 binaryen-2f9d019267bd792e1df09a00648eb4d8edb39ac1.zip |
Avoid g$ in main modules where possible (#2721)
We realized it is not valid to do these f$, g$ optimizations in
main and side modules, as a symbol might appear in both (like
RTTI or a weak symbol). We do need one of the appearances
to "win". This does the g$ optimization in main modules only,
that is, if a global appears in a main module then we can avoid
a g$ import and instead compute its location directly in the
module, since we will "win" over other modules with the same
symbol anyhow.
-rw-r--r-- | src/wasm/wasm-emscripten.cpp | 29 | ||||
-rw-r--r-- | test/lld/gdollar_mainmodule.wat | 20 | ||||
-rw-r--r-- | test/lld/gdollar_mainmodule.wat.out | 119 |
3 files changed, 167 insertions, 1 deletions
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index 75598875c..5a4bda0a7 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -288,8 +288,35 @@ Function* EmscriptenGlueGenerator::generateAssignGOTEntriesFunction() { Block* block = builder.makeBlock(); assignFunc->body = block; + bool hasSingleMemorySegment = + wasm.memory.exists && wasm.memory.segments.size() == 1; + for (Global* g : gotMemEntries) { - Name getter(std::string("g$") + g->base.c_str()); + // If this global is defined in this module, we export its address relative + // to the relocatable memory. If we are in a main module, we can just use + // that location (since if other modules have this symbol too, we will "win" + // as we are loaded first). Otherwise, import a g$ getter. + // Note that this depends on memory having a single segment, so we know the + // offset, and that the export is a global. + auto base = g->base; + if (hasSingleMemorySegment && !sideModule) { + if (auto* ex = wasm.getExportOrNull(base)) { + if (ex->kind == ExternalKind::Global) { + // The base relative to which we are computed is the offset of the + // singleton segment. + auto* relativeBase = + ExpressionManipulator::copy(wasm.memory.segments[0].offset, wasm); + + auto* offset = + builder.makeGlobalGet(ex->value, wasm.getGlobal(ex->value)->type); + auto* add = builder.makeBinary(AddInt32, relativeBase, offset); + GlobalSet* globalSet = builder.makeGlobalSet(g->name, add); + block->list.push_back(globalSet); + continue; + } + } + } + Name getter(std::string("g$") + base.c_str()); ensureFunctionImport(&wasm, getter, Signature(Type::none, Type::i32)); Expression* call = builder.makeCall(getter, {}, Type::i32); GlobalSet* globalSet = builder.makeGlobalSet(g->name, call); diff --git a/test/lld/gdollar_mainmodule.wat b/test/lld/gdollar_mainmodule.wat new file mode 100644 index 000000000..2b9a30439 --- /dev/null +++ b/test/lld/gdollar_mainmodule.wat @@ -0,0 +1,20 @@ +(module + (import "env" "memory" (memory $0 0)) + (data (global.get $gimport$3) "") + (import "env" "__indirect_function_table" (table $timport$1 0 funcref)) + (import "env" "__stack_pointer" (global $gimport$2 (mut i32))) + (import "env" "__memory_base" (global $gimport$3 i32)) + (import "env" "__table_base" (global $gimport$4 i32)) + (import "GOT.mem" "someglobal1" (global $gimport$6 (mut i32))) + (import "GOT.mem" "someglobal2" (global $gimport$7 (mut i32))) + (import "GOT.mem" "someglobal3" (global $gimport$8 (mut i32))) + (global $global$1 i32 (i32.const 54)) + (global $global$2 i32 (i32.const 0)) + (export "someglobal2" (global $global$1)) + (export "main" (func $main)) + (export "__data_end" (global $global$2)) + (func $main (param $0 i32) (param $1 i32) (result i32) + (i32.const 0) + ) +) + diff --git a/test/lld/gdollar_mainmodule.wat.out b/test/lld/gdollar_mainmodule.wat.out new file mode 100644 index 000000000..85cf5e445 --- /dev/null +++ b/test/lld/gdollar_mainmodule.wat.out @@ -0,0 +1,119 @@ +(module + (type $none_=>_i32 (func (result i32))) + (type $i32_=>_i32 (func (param i32) (result i32))) + (type $none_=>_none (func)) + (type $i32_=>_none (func (param i32))) + (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) + (import "env" "memory" (memory $0 0)) + (data (global.get $gimport$3) "") + (import "env" "table" (table $0 0 funcref)) + (import "env" "__stack_pointer" (global $gimport$2_import i32)) + (import "env" "__memory_base" (global $gimport$3 i32)) + (import "env" "__table_base" (global $gimport$4 i32)) + (import "env" "g$someglobal1" (func $g$someglobal1 (result i32))) + (import "env" "g$someglobal3" (func $g$someglobal3 (result i32))) + (global $gimport$6 (mut i32) (i32.const 0)) + (global $gimport$7 (mut i32) (i32.const 0)) + (global $gimport$8 (mut i32) (i32.const 0)) + (global $global$1 i32 (i32.const 54)) + (global $global$2 i32 (i32.const 0)) + (global $gimport$2 (mut i32) (global.get $gimport$2_import)) + (export "someglobal2" (global $global$1)) + (export "main" (func $main)) + (export "__data_end" (global $global$2)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (export "__assign_got_enties" (func $__assign_got_enties)) + (func $main (; 2 ;) (param $0 i32) (param $1 i32) (result i32) + (i32.const 0) + ) + (func $stackSave (; 3 ;) (result i32) + (global.get $gimport$2) + ) + (func $stackAlloc (; 4 ;) (param $0 i32) (result i32) + (local $1 i32) + (global.set $gimport$2 + (local.tee $1 + (i32.and + (i32.sub + (global.get $gimport$2) + (local.get $0) + ) + (i32.const -16) + ) + ) + ) + (local.get $1) + ) + (func $stackRestore (; 5 ;) (param $0 i32) + (global.set $gimport$2 + (local.get $0) + ) + ) + (func $__growWasmMemory (; 6 ;) (param $newSize i32) (result i32) + (memory.grow + (local.get $newSize) + ) + ) + (func $__assign_got_enties (; 7 ;) + (global.set $gimport$6 + (call $g$someglobal1) + ) + (global.set $gimport$7 + (i32.add + (global.get $gimport$3) + (global.get $global$1) + ) + ) + (global.set $gimport$8 + (call $g$someglobal3) + ) + ) +) +(; +--BEGIN METADATA -- +{ + "staticBump": 4294966728, + "tableSize": 0, + "initializers": [ + "__assign_got_enties" + ], + "declares": [ + "g$someglobal1", + "g$someglobal3" + ], + "externs": [ + "___stack_pointer", + "___memory_base", + "___table_base" + ], + "implementedFunctions": [ + "_main", + "_stackSave", + "_stackAlloc", + "_stackRestore", + "___growWasmMemory", + "___assign_got_enties" + ], + "exports": [ + "main", + "stackSave", + "stackAlloc", + "stackRestore", + "__growWasmMemory", + "__assign_got_enties" + ], + "namedGlobals": { + "someglobal2" : "54", + "__data_end" : "0" + }, + "invokeFuncs": [ + ], + "features": [ + ], + "mainReadsParams": 1 +} +-- END METADATA -- +;) |