Skip to content

Devtools benchmarks fail with dart2wasm on highest optimization level #56664

Closed

Description

@eyebrowsoffire

The devtools benchmarks run with the newest version of flutter causes dart2wasm to emit code that results in a typecasting failure, but only at the highest optimization levels.

Steps to Reproduce:

Results:
Tests output the following exception:

  Caught browser-side error: Type '(minified:Class2107) => minified:Class4570<void>' is not a subtype of type '(Object) => minified:Class4570<void>' in type cast
      at _TypeError._throwAsCheckError (http://localhost:9999/main.dart.wasm:wasm-function[1117]:0x1aa4a2)
      at _RouterState.restoreState closure at file:///home/runner/work/devtools/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:623:72 (http://localhost:9999/main.dart.wasm:wasm-function[33056]:0x4ade86)
      at closure wrapper at file:///home/runner/work/devtools/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:623:72 trampoline (http://localhost:9999/main.dart.wasm:wasm-function[33060]:0x4adeb4)
      at _RouterState._processParsedRouteInformation closure at file:///home/runner/work/devtools/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:759:12 inner (http://localhost:9999/main.dart.wasm:wasm-function[32757]:0x4a80cf)
      at _RouterState._processParsedRouteInformation closure at file:///home/runner/work/devtools/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:759:12 (http://localhost:9999/main.dart.wasm:wasm-function[32754]:0x4a7fce)
      at closure wrapper at file:///home/runner/work/devtools/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:759:12 trampoline (http://localhost:9999/main.dart.wasm:wasm-function[32756]:0x4a7ff8)
      at _rootRunUnary (http://localhost:9999/main.dart.wasm:wasm-function[1550]:0x1bfa56)
      at _CustomZone.runUnary (http://localhost:9999/main.dart.wasm:wasm-function[33328]:0x4b5988)

This only appears to occur at the full optimization level. Changing the web benchmarking code to compile at -O1, -O1 or -O2 does not emit this error. Unfortunately, it's difficult to tell what exactly is being cast due to the minified types.

Activity

  1. dart-github-bot commented on Sep 6, 2024

    @dart-github-bot
    Collaborator

    Summary: Dart2wasm emits incorrect code when compiling Devtools benchmarks at the highest optimization level, causing a type casting error during runtime. The issue only occurs at -O3 and not at lower optimization levels.

  2. added
    area-dart2wasmIssues for the dart2wasm compiler.
    triage-automationSee https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot.
    type-bugIncorrect behavior (everything from a crash to more subtle misbehavior)
    on Sep 6, 2024
  3. removed
    triage-automationSee https://github.com/dart-lang/ecosystem/tree/main/pkgs/sdk_triage_bot.
    on Sep 7, 2024
  4. mkustermann commented on Sep 9, 2024

    @mkustermann
    Member

    I can confirm that this is happening iff --omit-implicit-type-checks is enabled.

    The error being thrown looks like this:

    Caught browser-side error:
       Type
           '(DevToolsRouteConfiguration) => Future<void>' is not a subtype of type
           '(Object) => Future<void>'
       in type cast
    

    The code looks like this:

      @override
      void restoreState(RestorationBucket? oldBucket, bool initialRestore) {
        registerForRestoration(_routeInformation, 'route');
        if (_routeInformation.value != null) {
          assert(widget.routeInformationParser != null);
          _processRouteInformation(_routeInformation.value!, () => widget.routerDelegate.setRestoredRoutePath);
        } else if (widget.routeInformationProvider != null) {
          _processRouteInformation(widget.routeInformationProvider!.value, () => widget.routerDelegate.setInitialRoutePath);
                                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        }
      }

    The inner closure returns a function. That function is a tear-off of RouterDelegate<T>.setInitialRoutePath.

    The widget.routerDelegate is a DevToolsRouterDelegate:

    class DevToolsRouterDelegate extends RouterDelegate<DevToolsRouteConfiguration> ... {
      ...
    }
    abstract class RouterDelegate<T> extends Listenable {
      Future<void> setInitialRoutePath(T configuration) { ...  }
      ...
    }

    => So at runtime this widget.routerDelegate.setInitialRoutePath will be (DevToolsRouteConfiguration) -> Future<void>

    So the closure we give to _processRouteInformations 2nd argument is () -> ((DevToolsRouteConfiguration) -> Future<void>).

    That function looks like this:

    class _RouterState<T> 
      void _processRouteInformation(RouteInformation information, ValueGetter<_RouteSetter<T>> delegateRouteSetter) {
        ....
      }
    }
    typedef ValueGetter<T> = T Function();
    typedef _RouteSetter<T> = Future<void> Function(T);
    

    => We seemingly have T == Object
    => We expect ValueGetter<_RouteSetter<T>>
    => We expect ValueGetter<_RouteSetter<Object>>
    => We expect ValueGetter<Future<void> Function(Object)>
    => We expect Future<void> Function(Object) Function()

    So we're trying to assign () -> ((DevToolsRouteConfiguration) -> Future<void> where () -> ((Object) -> Future<void>) is expected.

    Not quite clear yet why this happens precisely iff --omit-implicit-checks is enabled.

  5. mkustermann commented on Sep 9, 2024

    @mkustermann
    Member

    Turns out that because the tear-off is of a method with covariant parameters the parameter of the closure should be Object. Though in --omit-implicit-checks it was rather DevToolsRouteConfiguration.

    => cl/384285

  6. kenzieschmoll commented on Sep 11, 2024

    @kenzieschmoll
    Contributor

    I am still seeing this issue even with the attempted fix (which was first included in Dart 3.6.0-235.0.dev - see commit).

    Flutter 3.26.0-1.0.pre.76 • channel [user-branch] • unknown source
    Framework • revision 9108b6d0cf (9 hours ago) • 2024-09-11 05:11:17 -0400
    Engine • revision 0a14c519ea
    Tools • Dart 3.6.0 (build 3.6.0-238.0.dev) • DevTools 2.39.0
    

    Repro steps:

    1. patch Add wasm opt-in setting flutter/devtools#8270
    2. run devtools_tool serve --wasm --no-strip-wasm

    Exception:

    Type '(minified:Class2376) => minified:Class4651<void>' is not a subtype of type '(Object) => minified:Class4651<void>' in type cast
    main.dart.mjs:69     at _TypeError._throwAsCheckError (http://127.0.0.1:9103/main.dart.wasm:wasm-function[1106]:0x1b3fb0)
        at _RouterState.restoreState closure at file:///Users/kenzieschmoll/develop/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:623:72 (http://127.0.0.1:9103/main.dart.wasm:wasm-function[13887]:0x2e9b21)
        at closure wrapper at file:///Users/kenzieschmoll/develop/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:623:72 trampoline (http://127.0.0.1:9103/main.dart.wasm:wasm-function[13891]:0x2e9b4c)
        at _RouterState._processParsedRouteInformation closure at file:///Users/kenzieschmoll/develop/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:759:12 inner (http://127.0.0.1:9103/main.dart.wasm:wasm-function[13880]:0x2e96b5)
        at _RouterState._processParsedRouteInformation closure at file:///Users/kenzieschmoll/develop/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:759:12 (http://127.0.0.1:9103/main.dart.wasm:wasm-function[13877]:0x2e95b7)
        at closure wrapper at file:///Users/kenzieschmoll/develop/devtools/tool/flutter-sdk/packages/flutter/lib/src/widgets/router.dart:759:12 trampoline (http://127.0.0.1:9103/main.dart.wasm:wasm-function[13879]:0x2e95df)
        at _rootRunUnary (http://127.0.0.1:9103/main.dart.wasm:wasm-function[1539]:0x1c99ac)
        at _CustomZone.runUnary (http://127.0.0.1:9103/main.dart.wasm:wasm-function[34744]:0x4e3593)
    
  7. mkustermann commented on Sep 11, 2024

    @mkustermann
    Member

    From my testing it seems very clear that this error occurs with

    <flutter> % git reset --hard '2fb154f8203cbb021003b9cd9bf7661e8de6d473^'
    
    <devtools> % flutter clean
    <devtools> % flutter packages get
    <devtools> % dart ./benchmark/devtools_benchmarks_test.dart     
    ...                                                                                                                
    [CHROME]: DevTools listening on ws://127.0.0.1:10000/devtools/browser/b1b2aed3-5ed5-4a49-b43d-73066f493a73                    
                                                                                                                                  
    Connecting to DevTools: ws://localhost:10000/devtools/page/A61FEE23E814B2964DA720C9D59E2B6A                                   
                                                                                                                                                                                                                                                                 
    Connected to Chrome tab:  (http://localhost:9999/)                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                 
    Launching benchmark "devtools_navigateThroughOfflineScreens"                                                                                                                                                                                                 
                                                                                                                                  
    Unrecognized URL path: /api/ping                                                                                              
    02:23 +0 -1: Can run web benchmarks with WASM [E]                                                                             
                                                                                                                                  
      Caught browser-side error: Type '(minified:Class2110) => minified:Class4558<void>' is not a subtype of type '(Object) => minified:Class4558<void>' in type cast
          at _TypeError._throwAsCheckError (http://localhost:9999/main.dart.wasm:wasm-function[1108]:0x1ad1c3)        
    

    but no longer with

    <flutter> % git reset --hard '2fb154f8203cbb021003b9cd9bf7661e8de6d473'
    
    <devtools> % flutter clean
    <devtools> % flutter packages get
    <devtools> % dart ./benchmark/devtools_benchmarks_test.dart 
    ...    
    [CHROME]: DevTools listening on ws://127.0.0.1:10000/devtools/browser/4f1a5882-91fa-45df-9493-c4d9a526bb9b                    
                                                                                                                                                                                                                                                                 
    Connecting to DevTools: ws://localhost:10000/devtools/page/9AE8F6F0F0FC7A39DC8771612ADF4D24                                   
                                                                                                                                                                                                                                                                 
    Connected to Chrome tab:  (http://localhost:9999/)                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                 
    Launching benchmark "devtools_navigateThroughOfflineScreens"                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                 
    Unrecognized URL path: /api/ping                                                                                              
    [APP] TEST STATUS: Warming up.                                                                                                
                                                                   
    [APP] TEST STATUS: Warm-up finished.                                                                                          
                                                                                                                                                                                                                                                                 
    [APP] TEST STATUS: Navigate through offline DevTools tabs                                                                     
                                                                                                                                                                                                                                                                 
    [APP] TEST STATUS: switching to home screen (icon null, iconAsset: icons/app_bar/devtools.png)                                
                                                                                                                                  
    [APP] TEST STATUS: switching to performance screen (icon null, iconAsset: icons/app_bar/performance.png)                      
                                                                                                                                  
    [APP] TEST STATUS: switching to cpu-profiler screen (icon null, iconAsset: icons/app_bar/cpu_profiler.png)                    
                                                                                                                                  
    [APP] TEST STATUS: switching to memory screen (icon null, iconAsset: icons/app_bar/memory.png)                                                                                                                                                               
                                                                                                                                                                                                                                                                 
    [APP] TEST STATUS: switching to app-size screen (icon null, iconAsset: icons/app_bar/app_size.png)                                                                                                                                                           
                                                                                                                                                                                                                                                                 
    [APP] TEST STATUS: switching to deep-links screen (icon null, iconAsset: icons/app_bar/deep_links.png)           
    

    @kenzieschmoll Are you sure you're on the right flutter/flutter commits? Have you run flutter clean & flutter packages get afterwords?

  8. kenzieschmoll commented on Sep 11, 2024

    @kenzieschmoll
    Contributor

    When you run devtools_tool serve --wasm --no-strip-wasm, do you see the error? I ran flutter clean and flutter packages get and I still see the error when I build and serve DevTools with wasm.

    Flutter 3.26.0-1.0.pre.76 • channel [user-branch] • unknown source
    Framework • revision 9108b6d0cf (10 hours ago) • 2024-09-11 05:11:17 -0400
    Engine • revision 0a14c519ea
    Tools • Dart 3.6.0 (build 3.6.0-238.0.dev) • DevTools 2.39.0
    

    You no longer need to patch any code locally, just pull the latest from the Devtools master branch and run the serve command above. When Devtools loads in the browser, be sure to do a hard refresh (just clicking in the URL and hitting enter) to ensure that the browser is not caching an old version of DevTools.

  9. mkustermann commented on Sep 11, 2024

    @mkustermann
    Member

    You no longer need to patch any code locally, just pull the latest from the Devtools master branch and run the serve command above. When Devtools loads in the browser, be sure to do a hard refresh (just clicking in the URL and hitting enter) to ensure that the browser is not caching an old version of DevTools.

    I still used the original instructions to reproduce (and cannot reproduce anymore after the rolled fix).

    Will try with new instructions from #56664 (comment) and report back.

  10. mkustermann commented on Sep 11, 2024

    @mkustermann
    Member

    When you run devtools_tool serve --wasm --no-strip-wasm, do you see the error? I ran flutter clean and flutter packages get and I still see the error when I build and serve DevTools with wasm.

    So the instructions would be

    % git clone https://github.com/flutter/devtools; cd devtools
    devtools % cd tool; dart pub get; cd ..
    ...
    devtools % export LOCAL_DART_SDK=<path-to-real-dart-lang/sdk-gclient-checkout>
    devtools % tool/bin/devtools_tool serve --wasm --no-strip-wasm
    ...
    

    If I follow these instructions it seems to only serve dart2js (i.e. main.dart.js)

  11. kenzieschmoll commented on Sep 11, 2024

    @kenzieschmoll
    Contributor

    Are you on the tip of flutter/devtools master and the tip of the Dart SDK? there was a commit to each that landed this morning that you would need.

  12. kenzieschmoll commented on Sep 11, 2024

    @kenzieschmoll
    Contributor

    One potential difference between running devtools serve --wasm --no-strip-wasm and running the benchmark tests is that the former builds DevTools in release mode by default, and web_benchmarks builds Devtools in profile mode.

  13. mkustermann commented on Sep 12, 2024

    @mkustermann
    Member

    Are you on the tip of flutter/devtools master and the tip of the Dart SDK? there was a commit to each that landed this morning that you would need.

    Yes.

    If I follow these instructions it seems to only serve dart2js (i.e. main.dart.js)

    After debugging the JS a bit it turns out the packages/devtools_app/web/flutter_bootstrap.js's shouldUseSkwasm() returns false

    async function shouldUseSkwasm() {
      const searchParams = new URLSearchParams(window.location.search);
      const wasmEnabledFromQueryParameter = searchParams.get(wasmQueryParameterKey) === 'true';
      const wasmEnabledFromDevToolsPreference = await getDevToolsWasmPreference();
      return wasmEnabledFromQueryParameter === true || wasmEnabledFromDevToolsPreference === true;
    }

    Though I can manually serve via

    <devtools>/packages/devtools_app/build/web % dhttpd  '--headers=Cross-Origin-Embedder-Policy=credentialless;Cross-Origin-Opener-Policy=same-origin'
    

    and put ?wasm=true in the http://localhost:8080?wasm=true URL. Then it uses the main.dart.wasm and it works just fine (e.g. cpu profiler).

    => I see no sign in the console of the bug mentioned here.

    The error this issue is about makes entirely sense given the bug I've found and fixed - I would be very surprised if another bug manifests in the same way.

    => Without clear, detailed instructions on how to reproduce this with newest flutter master there's nothing I can do.

  14. mkustermann commented on Sep 20, 2024

    @mkustermann
    Member

    @kenzieschmoll Do you still experience this issue and have reproduction instructions? Or is the issue fixed for you as well (as I would expect)?

  15. kenzieschmoll commented on Sep 26, 2024

    @kenzieschmoll
    Contributor

    I tried to reproduce this morning and could not, so it appears this issue is fixed. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-dart2wasmIssues for the dart2wasm compiler.type-bugIncorrect behavior (everything from a crash to more subtle misbehavior)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions