// 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: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;

  /// 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!.targetRanges.length == _unchecked!.targetRanges.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,
      _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,
      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(
        references, useSentinelForOptionalParameters);
    return SelectorInfo._(dispatchTable, id, name, callCount,
        isSetter: isSetter)
      ..useMultipleEntryPoints = useMultipleEntryPoints
      ..isDynamicSubmoduleCallable = isDynamicSubmoduleCallable
      ..isDynamicSubmoduleOverridable = isDynamicSubmoduleOverridable
      .._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).targetRanges;
    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);
}

class SelectorTargets {
  /// Targets for all concrete classes implementing this selector.
  ///
  /// As a subclass hierarchy often inherits the same target, we associate the
  /// target with a range of class ids. The ranges are non-empty,
  /// non-overlapping and sorted in ascending order.
  final List<({Range range, Reference target})> targetRanges;

  /// Targets that a interface call will check & directly call before falling
  /// back to dispatch table calls.
  ///
  /// 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 [targetRanges], `class ID + offset` gives the offset of the
  /// class member for this selector.
  int? offset;

  SelectorTargets(this.targetRanges, this.staticDispatchRanges);

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

  void serialize(DataSerializer sink) {
    sink.writeInt(offset == null ? 0 : offset! + 1);
    sink.writeInt(targetRanges.length);
    for (final (:range, :target) in targetRanges) {
      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 targetRangesLength = source.readInt();
    final targetRanges = <({Range range, Reference target})>[];
    for (int i = 0; i < targetRangesLength; i++) {
      final range = Range.deserialize(source);
      final target = source.readReference();
      targetRanges.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));
    }
    return SelectorTargets(targetRanges, 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;
      for (final target in selector._references) {
        final member = target.asMember;
        isDynamicSubmoduleOverridable |=
            member.isDynamicSubmoduleOverridable(translator.coreTypes);
        isDynamicSubmoduleCallable |=
            member.isDynamicSubmoduleCallable(translator.coreTypes);
      }
      selector.isDynamicSubmoduleOverridable = isDynamicSubmoduleOverridable;
      selector.isDynamicSubmoduleCallable = isDynamicSubmoduleCallable;

      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(
            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(
          selector._references, selector._useSentinelForOptionalParameters);

      // Split up [ranges] into those that are statically dispatched to and
      // those are used via dispatch table.
      final staticDispatchRanges = selector.isDynamicSubmoduleOverridable
          ? const <({Range range, Reference target})>[]
          : (translator.options.polymorphicSpecialization || ranges.length == 1)
              ? ranges
              : ranges
                  .where(
                      (range) => staticDispatchPragmas.contains(range.target))
                  .toList();
      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(),
          staticDispatchRanges.map((r) => getChecked(r, false)).toList(),
        );
        final uncheckedTargets = SelectorTargets(
          ranges.map((r) => getChecked(r, true)).toList(),
          staticDispatchRanges.map((r) => getChecked(r, true)).toList(),
        );
        selector._checked = checkedTargets;
        selector._unchecked = uncheckedTargets;
      } else {
        final normalTargets = SelectorTargets(ranges, 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!.targetRanges)));
        rows.add(buildRow((selector._unchecked!.targetRanges)));
      } else {
        rows.add(buildRow((selector._normal!.targetRanges)));
      }
    }

    _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 =
        {};
    for (int i = 0; i < _table.length; i++) {
      Reference? target = _table[i];
      if (target != null) {
        w.BaseFunction? fun = translator.functions.getExistingFunction(target);
        // 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.
        if (fun != null) {
          final targetModule = fun.enclosingModule;
          if (targetModule == _definedWasmTable.enclosingModule) {
            if (isDynamicSubmoduleTable &&
                targetModule == 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);
            }
            _definedWasmTable.setElement(i, fun);
          } else {
            // This will generate the imported table if it doesn't already
            // exist.
            (getWasmTable(targetModule) as w.ImportedTable).setElements[i] =
                fun;
          }
        }
      }
    }
  }

  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);

  //  If there's 0 or 1 target than the call sites will either emit an
  //  unreachable or a direct call, so no call site goes via dispatch table, so
  //  we don't need a row in the table.
  if (targets.targetRanges.length <= 1) return false;

  // If all targets are dispatched to via static polymorphic dispatchers,
  // then no callsite will emit a dispatch table call, so we don't need a row in
  // the table.
  if (targets.staticDispatchRanges.length == targets.targetRanges.length) {
    return false;
  }

  return true;
}

ParameterInfo _parameterInfoFromReferences(
    List<Reference> references, bool useDefaultValueSentinel) {
  // 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 paramInfo = ParameterInfo.fromMember(
      first, useDefaultValueSentinel || first.asMember.isAbstract);
  for (final target in references.skip(1)) {
    paramInfo.merge(ParameterInfo.fromMember(
        target, useDefaultValueSentinel || target.asMember.isAbstract));
  }
  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;
}
