Skip to content

[dart2wasm] Reduce size of trivial async function bodies #60433

Open
@mkustermann

Description

@mkustermann

In ACX code there's a lot of static async functions that simply return a constant (e.g. grep for ulanHotShi).

For this example

main() async {
  print(await load1());
  print(await load2());
  print(await load3());
  print(await load4());
}

Future<Foo> load1() async => const Foo(1);
Future<Foo> load2() async => const Foo(2);
Future<Foo> load3() async => const Foo(3);
Future<Foo> load4() async => const Foo(4);

class Foo {
  final int i;
  const Foo(this.i);
}

dart2wasm currently compiles the inner bodies to

  (func $load1 inner (;193;) (param $var0 (ref $_AsyncSuspendState_35)) (param $var1 (ref null $#Top)) (param $var2 (ref null $#Top)) (param $var3 (ref null $_StringStackTrace_5)) (result (ref null $#Top))
    (local $var4 (ref $#Top))
    (local $var5 (ref $_StringStackTrace_5))
    try
      block $label1
        block $label0
          block $label2
            local.get $var0
            struct.get $_AsyncSuspendState_35 $field3
            br_table $label0 $label1 $label2
          end $label2
          unreachable
        end $label0
        local.get $var0
        struct.get $_AsyncSuspendState_35 $field4
        global.get $global208
        call $_AsyncCompleter.complete (body)
        ref.null none
        return
      end $label1
      local.get $var0
      struct.get $_AsyncSuspendState_35 $field4
      ref.null none
      call $_AsyncCompleter.complete (body)
      ref.null none
      return
    catch $tag0
      local.set $var5
      local.set $var4
      local.get $var0
      struct.get $_AsyncSuspendState_35 $field4
      local.get $var4
      local.get $var5
      call $_Completer.completeError
      ref.null none
      return
    catch_all
      local.get $var0
      struct.get $_AsyncSuspendState_35 $field4
      call $_JavaScriptError
      call $StackTrace.current
      call $_Completer.completeError
      ref.null none
      return
    end
    unreachable
  )

There's a few things here:

  • The body of the try/catch block has two cases where it calls _AsyncCompleter.complete even though the original Dart source code just has a single return statement
    => It seems this body should only have a single call to complete the async completer.
  • The original dart code function bodies are just returning constants. They are effect free and cannot cause exceptions to be thrown
    => We could avoid the try/catch in this case

/cc @osa1

Metadata

Metadata

Assignees

Labels

area-dart2wasmIssues for the dart2wasm compiler.type-performanceIssue relates to performance or code size

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions