From f32057642ba0357312e5227cc2f05035ec00e2ef Mon Sep 17 00:00:00 2001 From: Martin Kustermann Date: Tue, 24 Mar 2026 13:07:26 -0700 Subject: [PATCH] [dart2wasm] Run an additional -Os in open world compilation This reduces e main module size by ~ 0.5-1% When compiling with deferred loading, we optimize each module individually with open world assumptions. Currently we run only one -Os pass which leaves code behind that can be optimized by another -Os. See e.g. discussion at [0]. The additional -Os pass is much faster than the first, so it doesn't add meaningful compile-time. [0] https://github.com/WebAssembly/binaryen/issues/8077 Change-Id: Id8c5e49d97439e28b2f7d9c5a0c206eec0893cad Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/490101 Reviewed-by: Srujan Gaddam Commit-Queue: Martin Kustermann --- pkg/dart2wasm/lib/compile.dart | 1 + ...red.fine_grained.devirtualized_module1.wat | 11 ++--- .../ir_tests/deferred.type_checks_module1.wat | 41 +++++++++---------- ...ce_map_simple_optimized_deferred_test.dart | 5 ++- 4 files changed, 27 insertions(+), 31 deletions(-) diff --git a/pkg/dart2wasm/lib/compile.dart b/pkg/dart2wasm/lib/compile.dart index ed6180f3f19..5a8544bda45 100644 --- a/pkg/dart2wasm/lib/compile.dart +++ b/pkg/dart2wasm/lib/compile.dart @@ -195,6 +195,7 @@ const List _binaryenFlagsMultiModule = [ '--no-inline=**', '--traps-never-happen', '-Os', + '-Os', ]; /// Compile a Dart file into a Wasm module. diff --git a/pkg/dart2wasm/test/ir_tests/deferred.fine_grained.devirtualized_module1.wat b/pkg/dart2wasm/test/ir_tests/deferred.fine_grained.devirtualized_module1.wat index fedd2497104..301a32ba925 100644 --- a/pkg/dart2wasm/test/ir_tests/deferred.fine_grained.devirtualized_module1.wat +++ b/pkg/dart2wasm/test/ir_tests/deferred.fine_grained.devirtualized_module1.wat @@ -63,8 +63,6 @@ ) (func $"foo1 " (result (ref null $#Top)) (local $var0 (ref $Object)) - (local $var1 (ref $Object)) - (local $var2 (ref $Object)) block $label0 block $label1 (result (ref $Object)) global.get $baseObj @@ -92,17 +90,15 @@ br_on_non_null $label3 br $label0 end $label3 - local.set $var1 - call $Foo1.doitDevirt drop + call $Foo1.doitDevirt block $label4 (result (ref $Object)) global.get $foo1Obj br_on_non_null $label4 br $label0 end $label4 - local.set $var2 - call $Foo1.doitDevirt drop + call $Foo1.doitDevirt ref.null none return end $label0 @@ -125,7 +121,7 @@ ref.null none ) (func $Foo1 (result (ref $Object)) <...>) - (func $Foo1.doitDevirt (result nullref) + (func $Foo1.doitDevirt global.get $"\"Foo1.doitDevirt(\"" global.get $1 global.get $"\")\"" @@ -142,7 +138,6 @@ i32.const 6 call_indirect $module0.cross-module-funcs-0 (param (ref null $#Top)) (result (ref null $#Top)) drop - ref.null none ) (func $Foo1.doitDispatch (param $var0 (ref $Object)) (param $var1 (ref null $#Top)) (result (ref null $#Top)) global.get $"\"Foo1.doitDispatch(\"" diff --git a/pkg/dart2wasm/test/ir_tests/deferred.type_checks_module1.wat b/pkg/dart2wasm/test/ir_tests/deferred.type_checks_module1.wat index 79a684b35f0..bec8d0be90d 100644 --- a/pkg/dart2wasm/test/ir_tests/deferred.type_checks_module1.wat +++ b/pkg/dart2wasm/test/ir_tests/deferred.type_checks_module1.wat @@ -17,7 +17,6 @@ (elem $$.$ <...>) (func $"Foo.takeT (body) " (param $var0 (ref $Foo)) (param $var1 (ref $#Top)) (local $var2 (ref $_InterfaceType)) - (local $var3 (ref null $Foo)) global.get $"\"Foo<\"" local.get $var0 struct.get $Foo $field2 @@ -35,7 +34,6 @@ block $label0 (result i32) i32.const 0 local.get $var0 - local.tee $var3 struct.get $Foo $field0 i32.const 118 i32.ne @@ -68,37 +66,37 @@ unreachable end local.get $var0 - ref.as_non_null i32.const 20 call_indirect $$.& (param (ref null $#Top)) (result (ref null $#Top)) drop ) (func $"Foo.takeT (checked entry)" (param $var0 (ref $Foo)) (param $var1 (ref $#Top)) - (local $var2 (ref null $_Type)) - (local $var3 i32) + (local $var2 i32) + (local $var3 (ref null $_Type)) + (local $var4 (ref $_Type)) block $label0 (result i32) block $label1 local.get $var0 struct.get $Foo $field2 - local.tee $var2 - struct.get $_Type $field0 local.tee $var3 + struct.get $_Type $field0 + local.tee $var2 i32.const 9 i32.le_u if - local.get $var3 + local.get $var2 i32.const 5 i32.le_u if - local.get $var3 + local.get $var2 i32.const 4 i32.le_u if - local.get $var3 + local.get $var2 i32.const 4 i32.eq if - local.get $var2 + local.get $var3 ref.as_non_null local.get $var1 i32.const 4 @@ -107,18 +105,18 @@ end br $label1 end - local.get $var2 + local.get $var3 ref.as_non_null local.get $var1 i32.const 5 call_indirect $$.& (param (ref $_Type) (ref $#Top)) (result i32) br $label0 end - local.get $var3 + local.get $var2 i32.const 9 i32.eq if - local.get $var2 + local.get $var3 ref.as_non_null local.get $var1 i32.const 6 @@ -127,15 +125,15 @@ end br $label1 end - local.get $var3 + local.get $var2 i32.const 11 i32.le_u if - local.get $var3 + local.get $var2 i32.const 11 i32.eq if - local.get $var2 + local.get $var3 ref.as_non_null local.get $var1 i32.const 7 @@ -144,11 +142,11 @@ end br $label1 end - local.get $var3 + local.get $var2 i32.const 13 i32.eq if - local.get $var2 + local.get $var3 ref.as_non_null local.get $var1 i32.const 8 @@ -156,10 +154,11 @@ br $label0 end end $label1 - local.get $var2 + local.get $var3 ref.as_non_null + local.tee $var4 local.get $var1 - local.get $var2 + local.get $var4 struct.get $_Type $field0 i32.const 498 i32.add diff --git a/tests/web/wasm/source_map_simple_optimized_deferred_test.dart b/tests/web/wasm/source_map_simple_optimized_deferred_test.dart index 1a4b16d4d9b..244e6d1f30b 100644 --- a/tests/web/wasm/source_map_simple_optimized_deferred_test.dart +++ b/tests/web/wasm/source_map_simple_optimized_deferred_test.dart @@ -13,13 +13,14 @@ void main() { const List<(String?, int?, int?, String?)?> frameDetails = [ ('source_map_simple_lib.dart', 18, 3, 'g'), ('source_map_simple_lib.dart', 14, 3, 'f'), - ('source_map_simple_lib.dart', 43, 5, 'testMain'), + // The wasm runtime will produce stack frames including `_invokeMain`. But + // `wasm-opt` will inline `f` into `_invokeMain` which will make the source + // maps map `_invokeMain+` to be `f`. ]; /* at $.Error._throwWithCurrentStackTrace (wasm://wasm/$-0009ed7a:wasm-function[57]:0xb2bb) at $.g (wasm://wasm/$-0009ed7a:wasm-function[194]:0xe340) -at $.f (wasm://wasm/$-0009ed7a:wasm-function[193]:0xe334) at $._invokeMain (wasm://wasm/$-0009ed7a:wasm-function[52]:0xa82c) at InstantiatedApp.invokeMain (.../source_map_simple_optimized_deferred_test.mjs:413:37) at main (.../run_wasm.js:428:21)