Unverified Commit abadf9ff authored by Martin Kustermann's avatar Martin Kustermann Committed by GitHub

Use `dart compile wasm` for wasm compilations (#143298)

* Flags to `dart compile wasm`

Some options are not relevant to a standalone user of `dart compile
wasm` (e.g. specyfing dart-sdk, platform file etc). => Those aren't
offered by the `dart compile wasm` tool directly. => We use the
`--extra-compiler-option=` instead which passes through arbitrary
options to the dart2wasm compiler. => We don't maintain compatibility of
those options, if we update them we'll ensure to also update flutter
tools

* Binaryen optimization passes

This change will mean we use the binaryen flags from Dart SDK which are
slightly different from the ones in flutter.

* Optimization configuration

This change will also start using the more standardized `-O` flag for
determining optimization levels. The meaning of those flags have been
mostly aligned with dart2js (with some differences remaining).

* Minimization

Using the new optimization flags, namely `-O4` for `--wasm-opt=full`,
will automatically enable the new `--minify` support. Minification is
Dart semantics preserving but changes the `<obj>.runtimeType.toString()`
to use minified names (just as in dart2js).

* Code size changes

  Overall this change will reduce wonderous code size by around 10%.

Issue https://github.com/dart-lang/sdk/issues/54675
parent 295eeaf1
......@@ -249,9 +249,8 @@ class Dart2WasmTarget extends Dart2WebTarget {
}
final BuildMode buildMode = BuildMode.fromCliName(buildModeEnvironment);
final Artifacts artifacts = environment.artifacts;
final File outputWasmFile = environment.buildDir.childFile(
compilerConfig.runWasmOpt ? 'main.dart.unopt.wasm' : 'main.dart.wasm'
);
final File outputWasmFile =
environment.buildDir.childFile('main.dart.wasm');
final File depFile = environment.buildDir.childFile('dart2wasm.d');
final String dartSdkPath = artifacts.getArtifactPath(Artifact.engineDartSdkPath, platform: TargetPlatform.web_javascript);
final String platformBinariesPath = artifacts.getHostArtifact(HostArtifact.webPlatformKernelFolder).path;
......@@ -261,12 +260,16 @@ class Dart2WasmTarget extends Dart2WebTarget {
);
final List<String> compilationArgs = <String>[
artifacts.getArtifactPath(Artifact.engineDartAotRuntime, platform: TargetPlatform.web_javascript),
'--disable-dart-dev',
artifacts.getArtifactPath(Artifact.dart2wasmSnapshot, platform: TargetPlatform.web_javascript),
artifacts.getArtifactPath(Artifact.engineDartBinary, platform: TargetPlatform.web_javascript),
'compile',
'wasm',
'--packages=.dart_tool/package_config.json',
'--dart-sdk=$dartSdkPath',
'--platform=$platformFilePath',
'--extra-compiler-option=--dart-sdk=$dartSdkPath',
'--extra-compiler-option=--platform=$platformFilePath',
if (compilerConfig.renderer == WebRendererMode.skwasm) ...<String>[
'--extra-compiler-option=--import-shared-memory',
'--extra-compiler-option=--shared-memory-max-pages=32768',
],
if (buildMode == BuildMode.profile)
'-Ddart.vm.profile=true'
else
......@@ -274,16 +277,12 @@ class Dart2WasmTarget extends Dart2WebTarget {
...decodeCommaSeparated(environment.defines, kExtraFrontEndOptions),
for (final String dartDefine in dartDefines)
'-D$dartDefine',
...compilerConfig.toCommandOptions(),
if (compilerConfig.renderer == WebRendererMode.skwasm)
...<String>[
'--import-shared-memory',
'--shared-memory-max-pages=32768',
],
'--depfile=${depFile.path}',
'--extra-compiler-option=--depfile=${depFile.path}',
environment.buildDir.childFile('main.dart').path, // dartfile
...compilerConfig.toCommandOptions(),
'-o',
outputWasmFile.path,
environment.buildDir.childFile('main.dart').path, // dartfile
];
final ProcessUtils processUtils = ProcessUtils(
......@@ -295,37 +294,6 @@ class Dart2WasmTarget extends Dart2WebTarget {
throwOnError: true,
compilationArgs,
);
if (compilerConfig.runWasmOpt) {
final String wasmOptBinary = artifacts.getArtifactPath(
Artifact.wasmOptBinary,
platform: TargetPlatform.web_javascript
);
final File optimizedOutput = environment.buildDir.childFile('main.dart.wasm');
final List<String> optimizeArgs = <String>[
wasmOptBinary,
'--all-features',
'--closed-world',
'--traps-never-happen',
'-O3',
'--type-ssa',
'--gufa',
'-O3',
'--type-merging',
if (compilerConfig.wasmOpt == WasmOptLevel.debug)
'--debuginfo',
outputWasmFile.path,
'-o',
optimizedOutput.path,
];
await processUtils.run(
throwOnError: true,
optimizeArgs,
);
// Rename the .mjs file not to have the `.unopt` bit
final File jsRuntimeFile = environment.buildDir.childFile('main.dart.unopt.mjs');
await jsRuntimeFile.rename(environment.buildDir.childFile('main.dart.mjs').path);
}
}
@override
......
......@@ -148,12 +148,23 @@ class WasmCompilerConfig extends WebCompilerConfig {
@override
CompileTarget get compileTarget => CompileTarget.wasm;
bool get runWasmOpt =>
wasmOpt == WasmOptLevel.full || wasmOpt == WasmOptLevel.debug;
List<String> toCommandOptions() => <String>[
if (omitTypeChecks) '--omit-type-checks',
];
List<String> toCommandOptions() {
// -O1: Optimizes
// -O2: Same as -O1 but also minifies (still semantics preserving)
// -O3: Same as -O2 but also omits implicit type checks.
// -O4: Same as -O3 but also omits explicit type checks.
// (NOTE: This differs from dart2js -O4 semantics atm.)
// Ortogonal: The name section is always kept by default and we emit it only
// in [WasmOptLevel.full] mode (similar to `--strip` of static symbols in
// AOT mode).
final String level = !omitTypeChecks ? '-O2' : '-O4';
return switch (wasmOpt) {
WasmOptLevel.none => <String>['-O0'],
WasmOptLevel.debug => <String>[level, '--no-minify'],
WasmOptLevel.full => <String>[level, '--no-name-section'],
};
}
@override
Map<String, Object> get buildEventAnalyticsValues => <String, Object>{
......
......@@ -30,24 +30,12 @@ const List<String> _kDart2jsLinuxArgs = <String>[
];
const List<String> _kDart2WasmLinuxArgs = <String> [
'Artifact.engineDartAotRuntime.TargetPlatform.web_javascript',
'--disable-dart-dev',
'Artifact.dart2wasmSnapshot.TargetPlatform.web_javascript',
'Artifact.engineDartBinary.TargetPlatform.web_javascript',
'compile',
'wasm',
'--packages=.dart_tool/package_config.json',
'--dart-sdk=Artifact.engineDartSdkPath.TargetPlatform.web_javascript',
'--platform=HostArtifact.webPlatformKernelFolder/dart2wasm_platform.dill',
];
const List<String> _kWasmOptLinuxArgrs = <String> [
'Artifact.wasmOptBinary.TargetPlatform.web_javascript',
'--all-features',
'--closed-world',
'--traps-never-happen',
'-O3',
'--type-ssa',
'--gufa',
'-O3',
'--type-merging',
'--extra-compiler-option=--dart-sdk=Artifact.engineDartSdkPath.TargetPlatform.web_javascript',
'--extra-compiler-option=--platform=HostArtifact.webPlatformKernelFolder/dart2wasm_platform.dill',
];
void main() {
......@@ -920,7 +908,7 @@ void main() {
final File depFile = environment.buildDir.childFile('dart2wasm.d');
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
processManager.addCommand(FakeCommand(
command: <String>[
..._kDart2WasmLinuxArgs,
......@@ -929,32 +917,23 @@ void main() {
'-DBAZ=qux',
'-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true',
'--depfile=${depFile.absolute.path}',
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
'-O2',
'--no-name-section',
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
],
onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo'))
);
processManager.addCommand(FakeCommand(
command: <String>[
..._kWasmOptLinuxArgrs,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
])
);
await Dart2WasmTarget(
const WasmCompilerConfig(
renderer: WebRendererMode.canvaskit
)
).build(environment);
expect(outputJsFile.existsSync(), isFalse);
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
expect(movedJsFile.existsSync(), isTrue);
expect(movedJsFile.readAsStringSync(), 'foo');
expect(outputJsFile.existsSync(), isTrue);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
......@@ -966,30 +945,23 @@ void main() {
final File depFile = environment.buildDir.childFile('dart2wasm.d');
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
processManager.addCommand(FakeCommand(
command: <String>[
..._kDart2WasmLinuxArgs,
'-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true',
'--omit-type-checks',
'--depfile=${depFile.absolute.path}',
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
'-O4',
'--no-name-section',
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
],
onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo'))
);
processManager.addCommand(FakeCommand(
command: <String>[
..._kWasmOptLinuxArgrs,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
])
);
await Dart2WasmTarget(
const WasmCompilerConfig(
omitTypeChecks: true,
......@@ -997,10 +969,7 @@ void main() {
)
).build(environment);
expect(outputJsFile.existsSync(), isFalse);
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
expect(movedJsFile.existsSync(), isTrue);
expect(movedJsFile.readAsStringSync(), 'foo');
expect(outputJsFile.existsSync(), isTrue);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
......@@ -1011,27 +980,21 @@ void main() {
final File depFile = environment.buildDir.childFile('dart2wasm.d');
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
processManager.addCommand(FakeCommand(
command: <String>[
..._kDart2WasmLinuxArgs,
'-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true',
'--depfile=${depFile.absolute.path}',
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
'-O2',
'--no-minify',
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
], onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo')));
processManager.addCommand(FakeCommand(
command: <String>[
..._kWasmOptLinuxArgrs,
'--debuginfo',
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
]));
await Dart2WasmTarget(
const WasmCompilerConfig(
wasmOpt: WasmOptLevel.debug,
......@@ -1039,10 +1002,7 @@ void main() {
)
).build(environment);
expect(outputJsFile.existsSync(), isFalse);
final File movedJsFile = environment.buildDir.childFile('main.dart.mjs');
expect(movedJsFile.existsSync(), isTrue);
expect(movedJsFile.readAsStringSync(), 'foo');
expect(outputJsFile.existsSync(), isTrue);
}, overrides: <Type, Generator>{
ProcessManager: () => processManager,
}));
......@@ -1060,9 +1020,11 @@ void main() {
'-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=true',
'--depfile=${depFile.absolute.path}',
environment.buildDir.childFile('main.dart').absolute.path,
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
'-O0',
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
environment.buildDir.childFile('main.dart').absolute.path,
], onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo')));
await Dart2WasmTarget(
......@@ -1080,31 +1042,26 @@ void main() {
environment.defines[WasmCompilerConfig.kRunWasmOpt] = WasmOptLevel.defaultValue.name;
final File depFile = environment.buildDir.childFile('dart2wasm.d');
final File outputJsFile = environment.buildDir.childFile('main.dart.unopt.mjs');
final File outputJsFile = environment.buildDir.childFile('main.dart.mjs');
processManager.addCommand(FakeCommand(
command: <String>[
..._kDart2WasmLinuxArgs,
'--extra-compiler-option=--import-shared-memory',
'--extra-compiler-option=--shared-memory-max-pages=32768',
'-Ddart.vm.product=true',
'-DFLUTTER_WEB_AUTO_DETECT=false',
'-DFLUTTER_WEB_USE_SKIA=false',
'-DFLUTTER_WEB_USE_SKWASM=true',
'--import-shared-memory',
'--shared-memory-max-pages=32768',
'--depfile=${depFile.absolute.path}',
'--extra-compiler-option=--depfile=${depFile.absolute.path}',
'-O2',
'--no-name-section',
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
environment.buildDir.childFile('main.dart').absolute.path,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
],
onRun: (_) => outputJsFile..createSync()..writeAsStringSync('foo'))
);
processManager.addCommand(FakeCommand(
command: <String>[
..._kWasmOptLinuxArgrs,
environment.buildDir.childFile('main.dart.unopt.wasm').absolute.path,
'-o',
environment.buildDir.childFile('main.dart.wasm').absolute.path,
])
);
await Dart2WasmTarget(
const WasmCompilerConfig(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment