summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2020-04-08 13:59:21 -0700
committerGitHub <noreply@github.com>2020-04-08 13:59:21 -0700
commit2f9d019267bd792e1df09a00648eb4d8edb39ac1 (patch)
tree5542994773bf4d34a53bd938fa8c628cf3c8dd5f
parent95a66b5b3ad34b47703131207bbab739366408c4 (diff)
downloadbinaryen-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.cpp29
-rw-r--r--test/lld/gdollar_mainmodule.wat20
-rw-r--r--test/lld/gdollar_mainmodule.wat.out119
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 --
+;)