// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:math' show min;

import 'package:kernel/ast.dart';
import 'package:vm/metadata/procedure_attributes.dart';
import 'package:vm/metadata/table_selector.dart';
import 'package:vm/metadata/unreachable.dart';
import 'package:wasm_builder/wasm_builder.dart' as w;

import 'class_info.dart';
import 'dynamic_module_kernel_metadata.dart';
import 'dynamic_modules.dart';
import 'param_info.dart';
import 'reference_extensions.dart';
import 'serialization.dart';
import 'translator.dart';

/// Information for a dispatch table selector.
///
/// A selector encapsulates information to generate code that selects the right
/// member (method, getter, setter) implementation in an instance invocation,
/// from the dispatch table. Dispatch table is generated by [DispatchTable].
///
/// Target of a selector is a method, getter, or setter [Reference]. A target
/// does not have to correspond to a user-written Dart member, it can be for a
/// generated one. For example, for torn-off methods, we generate a [Reference]
/// for the tear-off getter a selector for it.
class SelectorInfo {
  final DispatchTable dispatchTable;

  Translator get translator => dispatchTable.translator;

  /// Unique ID of the selector.
  final int id;

  /// Number of use sites of the selector.
  final int callCount;

  /// Least upper bound of [ParameterInfo]s of all targets.
  late final ParameterInfo paramInfo;

  /// Is this an implicit or explicit setter?
  final bool isSetter;

  /// Whether we create multiple entry points for the selector.
  ///
  /// We create multiple entry points when any implementation of this selector
  /// performs type checks on the passed arguments.
  late bool useMultipleEntryPoints;

  late bool isDynamicSubmoduleOverridable;
  late bool isDynamicSubmoduleCallable;
  late bool isDynamicSubmoduleInheritable;

  /// Whether the computation of [paramInfo] should enforce usage of sentinels
  /// for optional parameters.
  late bool _useSentinelForOptionalParameters;

  /// Wasm function type for the selector.
  ///
  /// This should be read after all targets have been added to the selector.
  late final w.FunctionType signature = _computeSignature();

  /// The selector's member's name.
  final String name;

  SelectorTargets? _checked;
  SelectorTargets? _unchecked;
  SelectorTargets? _normal;

  /// The set of references we use to calculate the [paramInfo].
  final List<Reference> _references = [];

  SelectorTargets targets({required bool unchecked}) {
    if (useMultipleEntryPoints) {
      assert(_checked!.allTargetRanges.length ==
          _unchecked!.allTargetRanges.length);
      return unchecked ? _unchecked! : _checked!;
    }
    assert(_checked == null && _unchecked == null);
    return _normal!;
  }

  SelectorInfo._(
    this.dispatchTable,
    this.id,
    this.name,
    this.callCount, {
    required this.isSetter,
  });

  void serialize(DataSerializer sink) {
    sink.writeInt(id);
    sink.writeString(name);
    sink.writeInt(callCount);
    sink.writeBoolList([
      isSetter,
      useMultipleEntryPoints,
      isDynamicSubmoduleOverridable,
      isDynamicSubmoduleCallable,
      isDynamicSubmoduleInheritable,
      _useSentinelForOptionalParameters,
    ]);
    sink.writeNullable(_checked, (targets) => targets.serialize(sink));
    sink.writeNullable(_unchecked, (targets) => targets.serialize(sink));
    sink.writeNullable(_normal, (targets) => targets.serialize(sink));
    sink.writeList(_references, sink.writeReference);
  }

  factory SelectorInfo.deserialize(
      DataDeserializer source, DispatchTable dispatchTable) {
    final id = source.readInt();
    final name = source.readString();
    final callCount = source.readInt();
    final [
      isSetter,
      useMultipleEntryPoints,
      isDynamicSubmoduleOverridable,
      isDynamicSubmoduleCallable,
      isDynamicSubmoduleInheritable,
      useSentinelForOptionalParameters,
    ] = source.readBoolList();
    final checked =
        source.readNullable(() => SelectorTargets.deserialize(source));
    final unchecked =
        source.readNullable(() => SelectorTargets.deserialize(source));
    final normal =
        source.readNullable(() => SelectorTargets.deserialize(source));
    final references = source.readList(source.readReference);

    final paramInfo = _parameterInfoFromReferences(
        source.component
                .metadata[UnreachableNodeMetadataRepository.repositoryTag]
            as UnreachableNodeMetadataRepository,
        references,
        useSentinelForOptionalParameters);
    return SelectorInfo._(dispatchTable, id, name, callCount,
        isSetter: isSetter)
      ..useMultipleEntryPoints = useMultipleEntryPoints
      ..isDynamicSubmoduleCallable = isDynamicSubmoduleCallable
      ..isDynamicSubmoduleOverridable = isDynamicSubmoduleOverridable
      ..isDynamicSubmoduleInheritable = isDynamicSubmoduleInheritable
      .._useSentinelForOptionalParameters = useSentinelForOptionalParameters
      .._checked = checked
      .._unchecked = unchecked
      .._normal = normal
      .._references.addAll(references)
      ..paramInfo = paramInfo;
  }

  String entryPointName(bool unchecked) {
    if (!useMultipleEntryPoints) return name;
    return '$name (${unchecked ? 'unchecked' : 'checked'})';
  }

  /// Compute the signature for the functions implementing members targeted by
  /// this selector.
  ///
  /// When the selector has multiple targets, the type of each parameter/return
  /// is the upper bound across all targets, such that all targets have the
  /// same signature, and the actual representation types of the parameters and
  /// returns are subtypes (resp. supertypes) of the types in the signature.
  w.FunctionType _computeSignature() {
    var nameIndex = paramInfo.nameIndex;
    final int returnCount = isSetter ? 0 : 1;
    List<Set<w.ValueType>> inputSets =
        List.generate(1 + paramInfo.paramCount, (_) => {});
    List<Set<w.ValueType>> outputSets = List.generate(returnCount, (_) => {});
    List<bool> ensureBoxed = List.filled(1 + paramInfo.paramCount, false);
    Iterable<({Reference target, Range range})> targetRanges =
        targets(unchecked: false).allTargetRanges;
    for (final (range: _, :target) in targetRanges) {
      Member member = target.asMember;
      DartType receiver =
          InterfaceType(member.enclosingClass!, Nullability.nonNullable);
      List<DartType> positional;
      Map<String, DartType> named;
      List<DartType> returns;
      if (member is Field) {
        if (target.isImplicitGetter) {
          positional = const [];
          named = const {};
          returns = [translator.typeOfReturnValue(member)];
        } else {
          positional = [member.setterType];
          named = const {};
          returns = const [];
        }
      } else {
        FunctionNode function = member.function!;
        if (target.isTearOffReference) {
          positional = const [];
          named = const {};
          returns = [function.computeFunctionType(Nullability.nonNullable)];
        } else {
          final typeForParam = translator.typeOfParameterVariable;
          positional = [
            for (int i = 0; i < function.positionalParameters.length; i++)
              typeForParam(function.positionalParameters[i],
                  i < function.requiredParameterCount)
          ];
          named = {
            for (VariableDeclaration param in function.namedParameters)
              param.name!: typeForParam(param, param.isRequired)
          };
          returns = target.isSetter
              ? const []
              : [translator.typeOfReturnValue(member)];
        }
      }
      assert(returns.length <= outputSets.length);
      inputSets[0].add(isDynamicSubmoduleOverridable
          ? translator.topTypeNonNullable
          : translator.translateType(receiver));
      for (int i = 0; i < positional.length; i++) {
        DartType type = positional[i];
        inputSets[1 + i].add(translator.translateType(type));
        ensureBoxed[1 + i] |=
            paramInfo.positional[i] == ParameterInfo.defaultValueSentinel;
      }
      for (String name in named.keys) {
        int i = nameIndex[name]!;
        DartType type = named[name]!;
        inputSets[1 + i].add(translator.translateType(type));
        ensureBoxed[1 + i] |=
            paramInfo.named[name] == ParameterInfo.defaultValueSentinel;
      }
      for (int i = 0; i < returnCount; i++) {
        if (i < returns.length) {
          DartType type = returns[i];
          outputSets[i].add(translator.translateReturnType(type));
        } else {
          outputSets[i].add(translator.topType);
        }
      }
    }

    List<w.ValueType> typeParameters = List.filled(paramInfo.typeParamCount,
        translator.classInfo[translator.typeClass]!.nonNullableType);
    List<w.ValueType> inputs = List.generate(
        inputSets.length,
        (i) => _upperBound(inputSets[i],
            ensureBoxed: ensureBoxed[i], isReceiver: i == 0));
    if (name == '==') {
      // == can't be called with null
      inputs[1] = inputs[1].withNullability(false);
    }
    List<w.ValueType> outputs = List.generate(outputSets.length,
        (i) => _upperBound(outputSets[i], ensureBoxed: false));
    return translator.typesBuilder.defineFunction(
        [inputs[0], ...typeParameters, ...inputs.sublist(1)], outputs);
  }

  w.ValueType _upperBound(Set<w.ValueType> types,
      {required bool ensureBoxed, bool isReceiver = false}) {
    if (types.isEmpty) {
      // This happens if the selector doesn't have any targets. Any call site of
      // such a selector is unreachable. Though such call sites still have to
      // evaluate receiver and arguments. Doing so requires the signature. So we
      // create a dummy signature with top types. Receivers specifically should
      // be non-nullable since we must be invoking a selector on some object.
      assert(!isReceiver || isDynamicSubmoduleOverridable);
      return isReceiver ? translator.topTypeNonNullable : translator.topType;
    }
    if (!ensureBoxed && types.length == 1 && types.single.isPrimitive) {
      // Unboxed primitive.
      return types.single;
    }
    final bool nullable = types.any((type) => type.nullable);
    int minDepth = 999999999;
    Set<w.DefType> heapTypes = types
        .where((type) => type is! w.RefType || type.heapType is w.DefType)
        .map((type) {
      w.DefType def = type is w.RefType
          ? type.heapType as w.DefType
          : translator.classInfo[translator.boxedClasses[type]!]!.struct;
      minDepth = min(minDepth, def.depth);
      return def;
    }).toSet();
    if (heapTypes.isEmpty) {
      // Only abstract heap types.
      Set<w.HeapType> heapTypes =
          types.map((type) => (type as w.RefType).heapType).toSet();
      return w.RefType(heapTypes.single, nullable: nullable);
    }
    int targetDepth = minDepth;
    while (heapTypes.length > 1) {
      heapTypes = heapTypes.map((s) {
        while (s.depth > targetDepth) {
          s = s.superType!;
        }
        return s;
      }).toSet();
      targetDepth -= 1;
    }
    return w.RefType.def(heapTypes.single, nullable: nullable);
  }

  late final Set<Reference> _targetSet = useMultipleEntryPoints
      ? {
          ..._checked!._targetSet,
          ..._unchecked!._targetSet,
        }
      : _normal!._targetSet;

  bool containsTarget(Reference target) => _targetSet.contains(target);
}

/// The set of possible targets for a given selector.
///
/// Will have an entry for all concrete classes (i.e. classes that are
/// allocated according to TFA) that respond to this selector.
///
/// We group (class-id, target) entries with consecutive class ids together if
/// they have the same entry.
///
/// A call site will dispatch in different ways to these targets:
///
///   * dynamic call sites will use a dynamic invocation forwarder function
///   which loads the receiver class id, switches on the class id and emit direct
///   calls to the targets (it uses [allTargetRanges] for this).
///
///   * an interface call will
///
///       * call the target directly if there's only one possible target
///
///       * call a polymorphic dispatcher function (if some of the targets are
///         marked via `@pragma('wasm:static-dispatch')` - which will emit
///         direct calls to targets based on the [staticDispatchRanges] and
///         fallback to the dispatch table call (if there's target ranges not
///         covered in [staticDispatchRanges])
///
///       * call the dispatch table entry (if there's more than one possible
///       target and [staticDispatchRanges] is empty)
///
///
/// * [_dispatchTableRanges] contains the target ranges we call indirectly
///   via the dispatch table
///
/// * [staticDispatchRanges] contains the target ranges we call directly via
///   class id checks + calls (directly or via [PolymorphicDispatchers])
///
class SelectorTargets {
  /// All targets of this selector.
  ///
  /// This set is split up in the disjoint [_dispatchTableRanges] and
  /// [staticDispatchRanges].
  final List<({Range range, Reference target})> allTargetRanges;

  /// All targets of this selector that are invoked via the dispatch table (if
  /// any).
  ///
  /// This is a subset of [allTargetRanges]. These need entries in the
  /// dispatch table.
  final List<({Range range, Reference target})> _dispatchTableRanges;

  /// Targets that an interface call will check & directly call before falling
  /// back to dispatch table calls.
  ///
  /// This is a subset of [allTargetRanges]. These don't need entries in the
  /// dispatch table.
  ///
  /// The targets in here are mainly the ones annotated with
  /// `@pragma('wasm:static-dispatch')`. The compiler will generate then code
  /// that first checks the receiver for those targets directly and issue direct
  /// calls before falling back to dispatch table calls.
  final List<({Range range, Reference target})> staticDispatchRanges;

  /// Offset of the selector in the dispatch table.
  ///
  /// For a class in [_dispatchTableRanges], `class ID + offset` gives the
  /// offset of the class member for this selector.
  int? offset;

  SelectorTargets(this.allTargetRanges, this._dispatchTableRanges,
      this.staticDispatchRanges) {
    assert(allTargetRanges.length ==
        (_dispatchTableRanges.length + staticDispatchRanges.length));
    assert((() {
      int d = 0;
      int s = 0;
      for (int i = 0; i < allTargetRanges.length; ++i) {
        final e = allTargetRanges[i];
        if (d < _dispatchTableRanges.length && _dispatchTableRanges[d] == e) {
          d++;
          continue;
        }
        if (s < staticDispatchRanges.length && staticDispatchRanges[s] == e) {
          s++;
          continue;
        }
        return false;
      }
      return true;
    })());
  }

  late final Set<Reference> _targetSet =
      allTargetRanges.map((e) => e.target).toSet();

  void serialize(DataSerializer sink) {
    sink.writeInt(offset == null ? 0 : offset! + 1);
    sink.writeInt(_dispatchTableRanges.length);
    for (final (:range, :target) in _dispatchTableRanges) {
      range.serialize(sink);
      sink.writeReference(target);
    }
    sink.writeInt(staticDispatchRanges.length);
    for (final (:range, :target) in staticDispatchRanges) {
      range.serialize(sink);
      sink.writeReference(target);
    }
  }

  factory SelectorTargets.deserialize(DataDeserializer source) {
    final offset = source.readInt();
    final dispatchTableRangesLength = source.readInt();
    final dispatchTableRanges = <({Range range, Reference target})>[];
    for (int i = 0; i < dispatchTableRangesLength; i++) {
      final range = Range.deserialize(source);
      final target = source.readReference();
      dispatchTableRanges.add((range: range, target: target));
    }
    final staticDispatchRangesLength = source.readInt();
    final staticDispatchRanges = <({Range range, Reference target})>[];
    for (int i = 0; i < staticDispatchRangesLength; i++) {
      final range = Range.deserialize(source);
      final target = source.readReference();
      staticDispatchRanges.add((range: range, target: target));
    }
    final allTargetRanges = <({Range range, Reference target})>[];
    int s = 0;
    int d = 0;
    while (s < staticDispatchRangesLength || d < dispatchTableRangesLength) {
      final se =
          (s < staticDispatchRangesLength) ? staticDispatchRanges[s] : null;
      final de =
          (d < dispatchTableRangesLength) ? dispatchTableRanges[d] : null;
      if (se != null) {
        if (de == null || se.range.start < de.range.start) {
          allTargetRanges.add(se);
          s++;
          continue;
        }
      }
      assert(de != null && (se == null || de.range.start < se.range.start));
      allTargetRanges.add(de!);
      d++;
    }
    return SelectorTargets(
        allTargetRanges, dispatchTableRanges, staticDispatchRanges)
      ..offset = offset == 0 ? null : offset - 1;
  }
}

/// Builds the dispatch table for member calls.
class DispatchTable {
  static const _functionType = w.RefType.func(nullable: true);
  final bool isDynamicSubmoduleTable;

  late final Map<TreeNode, ProcedureAttributesMetadata>
      procedureAttributeMetadata =
      translator.isDynamicSubmodule && !isDynamicSubmoduleTable
          ? (translator.component
                      .metadata[dynamicMainModuleProcedureAttributeMetadataTag]
                  as ProcedureAttributesMetadataRepository)
              .mapping
          : translator.procedureAttributeMetadata;

  late final Translator translator;

  late final List<TableSelectorInfo> _selectorMetadata =
      translator.isDynamicSubmodule && !isDynamicSubmoduleTable
          ? (translator.component.metadata[dynamicMainModuleSelectorMetadataTag]
                  as TableSelectorMetadataRepository)
              .mapping[translator.component]!
              .selectors
          : (translator.component
                      .metadata[TableSelectorMetadataRepository.repositoryTag]
                  as TableSelectorMetadataRepository)
              .mapping[translator.component]!
              .selectors;
  late final int minClassId = isDynamicSubmoduleTable
      ? translator.classIdNumbering.firstDynamicSubmoduleClassId
      : 0;
  late final int maxClassId = isDynamicSubmoduleTable
      ? translator.classIdNumbering.maxDynamicSubmoduleConcreteClassId!
      : translator.classIdNumbering.maxConcreteClassId;

  /// Maps selector IDs to selectors.
  final Map<int, SelectorInfo> _selectorInfo = {};

  /// Maps member names to getter selectors with the same member name.
  final Map<Name, Set<SelectorInfo>> _dynamicGetters = {};

  /// Maps member names to setter selectors with the same member name.
  final Map<Name, Set<SelectorInfo>> _dynamicSetters = {};

  /// Maps member names to method selectors with the same member name.
  final Map<Name, Set<SelectorInfo>> _dynamicMethods = {};

  /// Contents of [_definedWasmTable]. For a selector with ID S and a target
  /// class of the selector with ID C, `table[S + C]` gives the reference to the
  /// class member for the selector.
  late final List<Reference?> _table;

  late final w.TableBuilder _definedWasmTable;
  late final WasmTableImporter _importedWasmTables =
      WasmTableImporter(translator, 'dispatch');

  /// The Wasm table for the dispatch table.
  w.Table getWasmTable(w.ModuleBuilder module) =>
      _importedWasmTables.get(_definedWasmTable, module);

  DispatchTable({this.isDynamicSubmoduleTable = false});

  void serialize(DataSerializer sink) {
    sink.writeList(_selectorInfo.values, (s) => s.serialize(sink));
    sink.writeList(_table, (r) => sink.writeNullable(r, sink.writeReference));
    // Preserve call selectors for closure calls which are handled dynamically.
    final callSelectors = _dynamicGetters[Name('call')]!;
    sink.writeList(callSelectors, (s) => sink.writeInt(s.id));
  }

  factory DispatchTable.deserialize(DataDeserializer source) {
    final dispatchTable = DispatchTable();

    final selectors =
        source.readList(() => SelectorInfo.deserialize(source, dispatchTable));
    final table = source
        .readList(() => source.readNullable(() => source.readReference()));
    final callSelectorIds = source.readList(source.readInt);

    for (final selector in selectors) {
      dispatchTable._selectorInfo[selector.id] = selector;
    }
    dispatchTable._table = table;

    // Preserve call selectors for closure calls which are handled dynamically.
    final callSelectors = <SelectorInfo>{};
    for (final selectorId in callSelectorIds) {
      callSelectors.add(dispatchTable._selectorInfo[selectorId]!);
    }
    dispatchTable._dynamicGetters[Name('call')] = callSelectors;

    return dispatchTable;
  }

  SelectorInfo selectorForTarget(Reference target) {
    Member member = target.asMember;
    bool isGetter = target.isGetter || target.isTearOffReference;
    ProcedureAttributesMetadata metadata = procedureAttributeMetadata[member]!;
    int selectorId = isGetter
        ? metadata.getterSelectorId
        : metadata.methodOrSetterSelectorId;
    return _selectorInfo[selectorId]!;
  }

  SelectorInfo _createSelectorForTarget(Reference target) {
    Member member = target.asMember;
    bool isGetter = target.isGetter || target.isTearOffReference;
    bool isSetter = target.isSetter;
    ProcedureAttributesMetadata metadata = procedureAttributeMetadata[member]!;
    int selectorId = isGetter
        ? metadata.getterSelectorId
        : metadata.methodOrSetterSelectorId;

    // _WasmBase and its subclass methods cannot be called dynamically
    final cls = member.enclosingClass;
    final isWasmType = cls != null && translator.isWasmType(cls);

    final calledDynamically = !isWasmType &&
        (metadata.getterCalledDynamically ||
            metadata.methodOrSetterCalledDynamically ||
            member.name.text == "call");

    // The compiler will generate calls to `noSuchMethod` in the dynamic
    // invocation forwarders. So we ensure that the call count is positive.
    final isNoSuchMethod = member == translator.objectNoSuchMethod;
    final callCount =
        _selectorMetadata[selectorId].callCount + (isNoSuchMethod ? 1 : 0);
    final selector = _selectorInfo.putIfAbsent(
        selectorId,
        () => SelectorInfo._(this, selectorId, member.name.text, callCount,
            isSetter: isSetter));
    assert(selector.isSetter == isSetter);
    selector._references.add(target);

    if (calledDynamically) {
      if (isGetter) {
        (_dynamicGetters[member.name] ??= {}).add(selector);
      } else if (isSetter) {
        (_dynamicSetters[member.name] ??= {}).add(selector);
      } else {
        (_dynamicMethods[member.name] ??= {}).add(selector);
      }
    }

    return selector;
  }

  /// Get selectors for getters and tear-offs with the given name.
  Iterable<SelectorInfo> dynamicGetterSelectors(Name memberName) =>
      _dynamicGetters[memberName] ?? Iterable.empty();

  /// Get selectors for setters with the given name.
  Iterable<SelectorInfo> dynamicSetterSelectors(Name memberName) =>
      _dynamicSetters[memberName] ?? Iterable.empty();

  /// Get selectors for methods with the given name.
  Iterable<SelectorInfo> dynamicMethodSelectors(Name memberName) =>
      _dynamicMethods[memberName] ?? Iterable.empty();

  void _initializeWasmTable() {
    final module = isDynamicSubmoduleTable
        ? translator.dynamicSubmodule
        : translator.mainModule;
    _definedWasmTable = module.tables.define(_functionType, _table.length);
    if (!isDynamicSubmoduleTable) {
      for (final module in translator.modules) {
        // Ensure the dispatch table is imported into every module as the first
        // table.
        getWasmTable(module);
      }
    }
  }

  void build() {
    if (!isDynamicSubmoduleTable && translator.isDynamicSubmodule) {
      _initializeWasmTable();
      return;
    }
    // Collect class/selector combinations

    // Maps class to selector IDs of the class
    final selectorsInClass = <Class, Map<SelectorInfo, Reference>>{};
    final staticDispatchPragmas = <Reference>{};

    // Add classes to selector targets for their members
    for (ClassInfo info in translator.classesSupersFirst) {
      final Class cls = info.cls ?? translator.coreTypes.objectClass;
      final Map<SelectorInfo, Reference> selectors;

      // Add the class to its inherited members' selectors. Skip `_WasmBase`:
      // it's defined as a Dart class (in `dart._wasm` library) but it's special
      // and does not inherit from `Object`.
      final ClassInfo? superInfo = info.superInfo;
      if (superInfo == null || cls == translator.wasmTypesBaseClass) {
        selectors = {};
      } else {
        final Class superCls =
            superInfo.cls ?? translator.coreTypes.objectClass;
        selectors = Map.of(selectorsInClass[superCls]!);
      }

      final classIsDynamicSubmoduleExtendable =
          cls.isDynamicSubmoduleExtendable(translator.coreTypes);

      /// Add a method (or getter, setter) of the current class ([info]) to
      /// [reference]'s selector's targets.
      ///
      /// Because we visit a superclass before its subclasses, if the class
      /// inherits [reference], then the selector will already have a target
      /// for the class. Override that target if [reference] is a not abstract.
      /// If it's abstract, then the superclass's method will be called, so do
      /// not update the target.
      void addMember(Reference reference, bool staticDispatch) {
        SelectorInfo selector = _createSelectorForTarget(reference);
        if (reference.asMember.isAbstract) {
          // Reference is abstract, do not override inherited concrete member
          selectors[selector] ??= reference;
        } else {
          // Reference is concrete, override inherited member
          selectors[selector] = reference;

          if (staticDispatch) staticDispatchPragmas.add(reference);
        }
      }

      // Add the class to its non-static members' selectors. If `info.cls` is
      // `null`, that means [info] represents the `#Top` type, which is not a
      // Dart class but has the members of `Object`.
      for (Member member in cls.members) {
        // Skip static members
        if (!member.isInstanceMember) {
          continue;
        }
        final bool staticDispatch =
            translator.getPragma<bool>(member, 'wasm:static-dispatch', true) ??
                false;
        if (member is Field) {
          addMember(member.getterReference, staticDispatch);
          if (member.hasSetter) {
            final target = member.setterReference!;
            addMember(target, staticDispatch);
          }
        } else if (member is Procedure) {
          final target = member.reference;
          addMember(target, staticDispatch);
          final procedureMetadata = procedureAttributeMetadata[member]!;
          // `hasTearOffUses` can be true for operators as well, even though
          // it's not possible to tear-off an operator. (no syntax for it)
          if (member.kind == ProcedureKind.Method &&
              (procedureMetadata.hasTearOffUses ||
                  // If the member can be invoked from a dynamic submodule then
                  // we need to include the tearoff too.
                  member.isDynamicSubmoduleCallable(translator.coreTypes) ||
                  classIsDynamicSubmoduleExtendable)) {
            addMember(member.tearOffReference, staticDispatch);
          }
        }
      }
      selectorsInClass[cls] = selectors;
    }

    final selectorTargets = <SelectorInfo, Map<int, Reference>>{};
    for (int classId = minClassId; classId <= maxClassId; ++classId) {
      final cls = translator.classes[classId].cls;
      if (cls != null) {
        selectorsInClass[cls]!.forEach((selectorInfo, target) {
          if (!target.asMember.isAbstract) {
            selectorTargets.putIfAbsent(selectorInfo, () => {})[classId] =
                target;
          }
        });
      }
    }

    _selectorInfo.forEach((_, selector) {
      bool isDynamicSubmoduleCallable = false;
      bool isDynamicSubmoduleOverridable = false;
      bool isDynamicSubmoduleInheritable = false;
      for (final target in selector._references) {
        final member = target.asMember;
        isDynamicSubmoduleOverridable |=
            member.isDynamicSubmoduleOverridable(translator.coreTypes);
        isDynamicSubmoduleCallable |=
            member.isDynamicSubmoduleCallable(translator.coreTypes);
        isDynamicSubmoduleInheritable |=
            member.isDynamicSubmoduleInheritable(translator.coreTypes);
      }
      selector.isDynamicSubmoduleOverridable = isDynamicSubmoduleOverridable;
      selector.isDynamicSubmoduleCallable = isDynamicSubmoduleCallable;
      selector.isDynamicSubmoduleInheritable = isDynamicSubmoduleInheritable;

      if (!selectorTargets.containsKey(selector)) {
        // There are no concrete implementations for the given [selector].
        selector._normal = SelectorTargets([], [], []);
        selector.useMultipleEntryPoints = false;
        selector._useSentinelForOptionalParameters = true;
        selector.paramInfo = _parameterInfoFromReferences(
            translator.unreachableMetadata,
            selector._references,
            selector._useSentinelForOptionalParameters);
      } else {
        // Will be initialized in the `selectorTargets.forEach()` below.
      }
    });
    selectorTargets
        .forEach((SelectorInfo selector, Map<int, Reference> targets) {
      final List<({Range range, Reference target})> ranges = targets.entries
          .map((entry) =>
              (range: Range(entry.key, entry.key), target: entry.value))
          .toList()
        ..sort((a, b) => a.range.start.compareTo(b.range.start));
      assert(ranges.isNotEmpty);
      int writeIndex = 0;
      for (int readIndex = 1; readIndex < ranges.length; ++readIndex) {
        final current = ranges[writeIndex];
        final next = ranges[readIndex];
        assert(next.range.length == 1);
        if ((current.range.end + 1) == next.range.start &&
            identical(current.target, next.target)) {
          ranges[writeIndex] = (
            range: Range(current.range.start, next.range.end),
            target: current.target
          );
        } else {
          ranges[++writeIndex] = next;
        }
      }
      ranges.length = writeIndex + 1;

      bool useMultipleEntryPoints = false;
      final implementationReferences = <Reference>[];
      for (final targetRange in ranges) {
        final target = targetRange.target;
        final member = target.asMember;
        assert(!member.isAbstract);

        // Compute [useMultipleEntryPoints]
        if (!member.isExternal &&
            !target.isGetter &&
            !target.isTearOffReference &&
            translator.needToCheckTypesFor(member)) {
          useMultipleEntryPoints = true;
        }
        implementationReferences.add(target);
      }
      selector.useMultipleEntryPoints = useMultipleEntryPoints;

      if (!selector.isDynamicSubmoduleOverridable &&
          implementationReferences.isNotEmpty) {
        // We have global knowledge of all targets of the selector. We can use
        // this global knowledge to compute the [ParameterInfo].
        selector._references.clear();
        selector._references.addAll(implementationReferences);
        selector._useSentinelForOptionalParameters = false;
      } else {
        // Case 1) We may have no targets for the selector, but there may
        // still be calls to it (see e.g. https://dartbug.com/60733).
        //
        // Case 2) We may have 3rd party implementations of the selector
        // in a dynamic module with unknown default values for optionals.
        //
        // => We make caller pass sentinel if the optional parameter is not
        // provided.
        selector._useSentinelForOptionalParameters = true;
      }
      selector.paramInfo = _parameterInfoFromReferences(
          translator.unreachableMetadata,
          selector._references,
          selector._useSentinelForOptionalParameters);

      // Split up [ranges] into those that are statically dispatched to and
      // those are used via dispatch table.
      final tableDispatchRanges = <({Range range, Reference target})>[];
      final staticDispatchRanges = <({Range range, Reference target})>[];
      if (selector.isDynamicSubmoduleOverridable) {
        tableDispatchRanges.addAll(ranges);
      } else {
        if (ranges.length == 1) {
          staticDispatchRanges.add(ranges.single);
        } else {
          for (final range in ranges) {
            if (translator.options.polymorphicSpecialization ||
                staticDispatchPragmas.contains(range.target)) {
              staticDispatchRanges.add(range);
            } else {
              tableDispatchRanges.add(range);
            }
          }
        }
      }
      if (selector.useMultipleEntryPoints) {
        ({Range range, Reference target}) getChecked(
          ({Range range, Reference target}) targetRange,
          bool unchecked,
        ) =>
            (
              range: targetRange.range,
              target: translator.getFunctionEntry(targetRange.target,
                  uncheckedEntry: unchecked)
            );
        final checkedTargets = SelectorTargets(
          ranges.map((r) => getChecked(r, false)).toList(),
          tableDispatchRanges.map((r) => getChecked(r, false)).toList(),
          staticDispatchRanges.map((r) => getChecked(r, false)).toList(),
        );
        final uncheckedTargets = SelectorTargets(
          ranges.map((r) => getChecked(r, true)).toList(),
          tableDispatchRanges.map((r) => getChecked(r, true)).toList(),
          staticDispatchRanges.map((r) => getChecked(r, true)).toList(),
        );
        selector._checked = checkedTargets;
        selector._unchecked = uncheckedTargets;
      } else {
        final normalTargets =
            SelectorTargets(ranges, tableDispatchRanges, staticDispatchRanges);
        selector._normal = normalTargets;
      }
    });

    // Assign selector offsets

    final List<SelectorInfo> selectors =
        selectorTargets.keys.where(_isUsedViaDispatchTableCall).toList();

    // Sort the selectors based on number of targets and number of use sites.
    // This is a heuristic to keep the table small.
    //
    // Place selectors with more targets first as they are less likely to fit
    // into the gaps left by selectors placed earlier.
    //
    // Among the selectors with approximately same number of targets, place
    // more used ones first, as the smaller selector offset will have a smaller
    // instruction encoding.
    int selectorSortWeight(SelectorInfo selector) =>
        selectorTargets[selector]!.length * 10 + selector.callCount;

    selectors.sort((a, b) => selectorSortWeight(b) - selectorSortWeight(a));

    final rows = <Row<Reference>>[];
    for (final selector in selectors) {
      Row<Reference> buildRow(
          List<({Range range, Reference target})> targetRanges) {
        final rowValues = <({int index, Reference value})>[];
        for (final (:range, :target) in targetRanges) {
          for (int classId = range.start; classId <= range.end; ++classId) {
            final adjustedClassId = classId - minClassId;
            rowValues.add((index: adjustedClassId, value: target));
          }
        }
        rowValues.sort((a, b) => a.index.compareTo(b.index));
        return Row(rowValues);
      }

      if (selector.useMultipleEntryPoints) {
        rows.add(buildRow((selector._checked!._dispatchTableRanges)));
        rows.add(buildRow((selector._unchecked!._dispatchTableRanges)));
      } else {
        rows.add(buildRow((selector._normal!._dispatchTableRanges)));
      }
    }

    _table = buildRowDisplacementTable<Reference>(rows);

    int rowIndex = 0;
    for (final selector in selectors) {
      if (selector.useMultipleEntryPoints) {
        selector._checked!.offset = rows[rowIndex++].offset;
        selector._unchecked!.offset = rows[rowIndex++].offset;
      } else {
        selector._normal!.offset = rows[rowIndex++].offset;
      }
    }

    _initializeWasmTable();
  }

  void output() {
    final Map<w.BaseFunction, w.BaseFunction> wrappedDynamicSubmoduleImports =
        {};
    int start = 0;
    while (start < _table.length) {
      Reference? target = _table[start];
      if (target == null) {
        start++;
        continue;
      }
      w.BaseFunction? fun = translator.functions.getExistingFunction(target);
      if (fun == null) {
        start++;
        continue;
      }

      // Any call to the dispatch table is guaranteed to hit a target.
      //
      // If a target is in a deferred module and that deferred module hasn't
      // been loaded yet, then the entry is `null`.
      //
      // Though we can only hit a target if that target's class has been
      // allocated. In order for the class to be allocated, the deferred
      // module must've been loaded to call the constructor.
      int end = start + 1;
      while (end < _table.length && _table[end] == target) {
        end++;
      }
      final strideWidth = end - start;

      // If the stride of the current function is more than this (i.e. the table
      // contains a large subsection with identical function entries) we
      // initialize that section in #start function.
      const strideElementTableLimit = 100;

      final targetModule = fun.enclosingModule;
      final targetModuleBuilder =
          translator.moduleToBuilder[fun.enclosingModule]!;
      if (targetModule == _definedWasmTable.enclosingModule) {
        if (isDynamicSubmoduleTable &&
            targetModuleBuilder == translator.dynamicSubmodule &&
            fun is w.ImportedFunction) {
          // Functions imported into submodules may need to be wrapped to
          // match the updated dispatch table signature.
          fun = wrappedDynamicSubmoduleImports[fun] ??=
              _wrapDynamicSubmoduleFunction(target, fun);
        }

        if (strideWidth < strideElementTableLimit) {
          for (int i = start; i < end; ++i) {
            _definedWasmTable.moduleBuilder.elements
                .activeFunctionSegmentBuilderFor(_definedWasmTable)
                .setFunctionAt(i, fun);
          }
        } else {
          targetModuleBuilder.elements.declarativeSegmentBuilder.declare(fun);
          final b = targetModuleBuilder.startFunction.body;
          b.i32_const(start);
          b.ref_func(fun);
          b.i32_const(strideWidth);
          b.table_fill(_definedWasmTable);
        }
      } else {
        // This will generate the imported table if it doesn't already
        // exist.
        final importedTable =
            getWasmTable(targetModuleBuilder) as w.ImportedTable;
        if (strideWidth < strideElementTableLimit) {
          for (int i = start; i < end; ++i) {
            targetModuleBuilder.elements
                .activeFunctionSegmentBuilderFor(importedTable)
                .setFunctionAt(i, fun);
          }
        } else {
          targetModuleBuilder.elements.declarativeSegmentBuilder.declare(fun);
          final b = targetModuleBuilder.startFunction.body;
          b.i32_const(start);
          b.ref_func(fun);
          b.i32_const(strideWidth);
          b.table_fill(importedTable);
        }
      }
      start += strideWidth;
    }
  }

  w.BaseFunction _wrapDynamicSubmoduleFunction(
      Reference target, w.BaseFunction importedFunction) {
    final mainSelector =
        translator.dynamicMainModuleDispatchTable!.selectorForTarget(target);
    final mainSignature = translator.signatureForMainModule(target);
    final localSelector = translator.dispatchTable.selectorForTarget(target);
    final localSignature = localSelector.signature;

    // If the type is the same in both the main module and the submodule, use
    // the imported function itself.
    if (mainSignature.isStructurallyEqualTo(localSignature)) {
      return importedFunction;
    }

    // Otherwise we need to create a wrapper to handle the differing types.
    // The local signature should include all the parameters necessary to call
    // the target in main since the local signature must include the target
    // member itself and any other members in the main module's selector range.
    final wrapper = translator.dynamicSubmodule.functions
        .define(localSignature, '${target.asMember} wrapper');

    final ib = wrapper.body;

    assert(mainSignature.inputs.length <= localSignature.inputs.length);

    final mainModulePreParamCount =
        (mainSelector.paramInfo.takesContextOrReceiver ? 1 : 0) +
            mainSelector.paramInfo.typeParamCount;
    final mainModuleBeforeNamedCount =
        mainModulePreParamCount + mainSelector.paramInfo.positional.length;
    int mainIndex = 0;
    for (; mainIndex < mainModuleBeforeNamedCount; mainIndex++) {
      final local = ib.locals[mainIndex];
      ib.local_get(local);
      translator.convertType(ib, local.type, mainSignature.inputs[mainIndex]);
    }

    final localPreParamCount =
        (localSelector.paramInfo.takesContextOrReceiver ? 1 : 0) +
            localSelector.paramInfo.typeParamCount;

    for (final name in mainSelector.paramInfo.names) {
      final namedIndex = localSelector.paramInfo.nameIndex[name]!;
      final local = ib.locals[localPreParamCount + namedIndex];
      ib.local_get(local);
      translator.convertType(ib, local.type, mainSignature.inputs[mainIndex++]);
    }
    ib.call(importedFunction);
    translator.convertType(
        ib, mainSignature.outputs.single, localSignature.outputs.single);
    ib.end();

    return wrapper;
  }
}

bool _isUsedViaDispatchTableCall(SelectorInfo selector) {
  // If there's no callers in this module and no callers in dynamic modules then
  // there's no need for us to create a dispatch table entry.
  if (selector.callCount == 0 && !selector.isDynamicSubmoduleCallable) {
    return false;
  }

  final targets = selector.targets(unchecked: false);
  return targets._dispatchTableRanges.isNotEmpty;
}

ParameterInfo _parameterInfoFromReferences(
    UnreachableNodeMetadataRepository unreachableMetadata,
    List<Reference> references,
    bool useDefaultValueSentinel) {
  final unreachableNodeMapping = unreachableMetadata.mapping;
  // We know all target implementations (closed world) if all of them use
  // the same default value for optionals, we can make the caller pass it.
  final first = references.first;
  final firstMember = first.asMember;
  final paramInfo = ParameterInfo.fromMember(
      first,
      useDefaultValueSentinel ||
          firstMember.isAbstract ||
          unreachableNodeMapping[firstMember] != null);
  for (final target in references.skip(1)) {
    final targetMember = target.asMember;
    paramInfo.merge(ParameterInfo.fromMember(
        target,
        useDefaultValueSentinel ||
            targetMember.isAbstract ||
            unreachableNodeMapping[targetMember] != null));
  }
  return paramInfo;
}

/// Build a row-displacement table based on fitting the [rows].
///
/// The returned list is the resulting row displacement table with `null`
/// entries representing unused space.
///
/// The offset of all [Row]s will be initialized.
List<V?> buildRowDisplacementTable<V extends Object>(List<Row<V>> rows,
    {int firstAvailable = 0}) {
  final table = <V?>[];
  for (final row in rows) {
    final values = row.values;
    int offset = firstAvailable - values.first.index;
    bool fits;
    do {
      fits = true;
      for (final value in values) {
        final int entry = offset + value.index;
        if (entry >= table.length) {
          // Fits
          break;
        }
        if (table[entry] != null) {
          fits = false;
          break;
        }
      }
      if (!fits) offset++;
    } while (!fits);
    row.offset = offset;
    for (final (:index, :value) in values) {
      final int tableIndex = offset + index;
      while (table.length <= tableIndex) {
        table.add(null);
      }
      assert(table[tableIndex] == null);
      table[tableIndex] = value;
    }
    while (firstAvailable < table.length && table[firstAvailable] != null) {
      firstAvailable++;
    }
  }
  return table;
}

class Row<V extends Object> {
  /// The values of the table row, represented sparsely as (index, value) tuples.
  final List<({int index, V value})> values;

  /// The given [values] must not be empty and should be sorted by index.
  Row(this.values) {
    assert(values.isNotEmpty);
    assert(() {
      int previous = values.first.index;
      for (final value in values.skip(1)) {
        if (value.index <= previous) return false;
        previous = value.index;
      }
      return true;
    }());
  }

  /// The selected offset of this row.
  late final int offset;

  int get width => values.last.index - values.first.index + 1;
  int get holes => width - values.length;
  int get density => (100 * values.length) ~/ width;
  int get sparsity => 100 - density;
}
