[vm/aot/tfa] Build cache of dispatch targets in TFA instead of using ClosedWorldClassHierarchy from CFE

Previously, TFA used ClosedWorldClassHierarchy from CFE to look for
dispatch targets of invocations, and cached those lookups. However,
doing lookups via ClosedWorldClassHierarchy for the first time is still
slow. Now TFA builds maps of dispatch targets from AST and no longer
uses ClosedWorldClassHierarchy for the lookup.

Improves time of AOT compilation step 2 (TFA) on a large
Flutter application 170s -> 152s (-10.5%).

TEST=ci

Issue: https://github.com/dart-lang/sdk/issues/42442
Change-Id: I1a22d298e5b2c0ead57c38ddfbf5ebbd1876732f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/215985
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 625616f..089a4c9 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -550,8 +550,7 @@
       TypeFlowAnalysis typeFlowAnalysis) {
     final TFClass cls = receiver.cls;
 
-    Member? target =
-        (cls as _TFClassImpl).getDispatchTarget(selector, typeFlowAnalysis);
+    Member? target = (cls as _TFClassImpl).getDispatchTarget(selector);
 
     if (target != null) {
       if (kPrintTrace) {
@@ -948,9 +947,13 @@
   /// exceeds this constant, then WideConeType approximation is used.
   static const int maxAllocatedTypesInSetSpecializations = 128;
 
+  final _TFClassImpl? superclass;
   final Set<_TFClassImpl> supertypes; // List of super-types including this.
   final Set<_TFClassImpl> _allocatedSubtypes = new Set<_TFClassImpl>();
-  final Map<Selector, Member> _dispatchTargets = <Selector, Member>{};
+  late final Map<Name, Member> _dispatchTargetsSetters =
+      _initDispatchTargets(true);
+  late final Map<Name, Member> _dispatchTargetsNonSetters =
+      _initDispatchTargets(false);
   final _DependencyTracker dependencyTracker = new _DependencyTracker();
 
   /// Flag indicating if this class has a noSuchMethod() method not inherited
@@ -958,7 +961,7 @@
   /// Lazy initialized by ClassHierarchyCache.hasNonTrivialNoSuchMethod().
   bool? hasNonTrivialNoSuchMethod;
 
-  _TFClassImpl(int id, Class classNode, this.supertypes)
+  _TFClassImpl(int id, Class classNode, this.superclass, this.supertypes)
       : super(id, classNode) {
     supertypes.add(this);
   }
@@ -1001,19 +1004,37 @@
     _specializedConeType = null; // Reset cached specialization.
   }
 
-  Member? getDispatchTarget(
-      Selector selector, TypeFlowAnalysis typeFlowAnalysis) {
-    Member? target = _dispatchTargets[selector];
-    if (target == null) {
-      target = typeFlowAnalysis.hierarchyCache.hierarchy.getDispatchTarget(
-          classNode, selector.name,
-          setter: selector.isSetter);
-      target ??= _DispatchableInvocation.kNoSuchMethodMarker;
-      _dispatchTargets[selector] = target;
+  Map<Name, Member> _initDispatchTargets(bool setters) {
+    Map<Name, Member> targets;
+    final superclass = this.superclass;
+    if (superclass != null) {
+      targets = Map.from(setters
+          ? superclass._dispatchTargetsSetters
+          : superclass._dispatchTargetsNonSetters);
+    } else {
+      targets = {};
     }
-    return identical(target, _DispatchableInvocation.kNoSuchMethodMarker)
-        ? null
-        : target;
+    for (Field f in classNode.fields) {
+      if (!f.isStatic && !f.isAbstract) {
+        if (!setters || f.hasSetter) {
+          targets[f.name] = f;
+        }
+      }
+    }
+    for (Procedure p in classNode.procedures) {
+      if (!p.isStatic && !p.isAbstract) {
+        if (p.isSetter == setters) {
+          targets[p.name] = p;
+        }
+      }
+    }
+    return targets;
+  }
+
+  Member? getDispatchTarget(Selector selector) {
+    return (selector.isSetter
+        ? _dispatchTargetsSetters
+        : _dispatchTargetsNonSetters)[selector.name];
   }
 
   String dump() => "$this {supers: $supertypes}";
@@ -1127,7 +1148,10 @@
     for (var sup in c.supers) {
       supertypes.addAll(getTFClass(sup.classNode).supertypes);
     }
-    return new _TFClassImpl(++_classIdCounter, c, supertypes);
+    Class? superclassNode = c.superclass;
+    _TFClassImpl? superclass =
+        superclassNode != null ? getTFClass(superclassNode) : null;
+    return new _TFClassImpl(++_classIdCounter, c, superclass, supertypes);
   }
 
   ConcreteType addAllocatedClass(Class cl) {