// Copyright (c) 2024, 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 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart' show CoreTypes;

import 'bytecode_serialization.dart'
    show
        BufferedWriter,
        BufferedReader,
        BytecodeObject,
        BytecodeSizeStatistics,
        ForwardReference,
        NamedEntryStatistics,
        doubleToIntBits,
        intBitsToDouble,
        ObjectReader,
        ObjectWriter,
        StringWriter;
import 'declarations.dart' show SourceFile, TypeParametersDeclaration;

enum ObjectKind {
  kInvalid,
  kLibrary,
  kScript,
  kClass,
  kMember,
  kClosure,
  kName,
  kConstObject,
  kType,
  kTypeArguments,
  kArgDesc,
}

enum ConstTag {
  kInvalid,
  kInt,
  kDouble,
  kBool,
  kString,
  kSymbol,
  kInstance,
  kList,
  kMap,
  kSet,
  kRecord,
  kTearOff,
  kTearOffInstantiation,
}

enum TypeTag {
  kInvalid,
  kDynamic,
  kVoid,
  kNull,
  kNever,
  kSimpleType,
  kGenericType,
  kTypeParameter,
  kFunctionType,
  kRecordType,
}

/// Name of artificial class containing top-level members of a library.
const String topLevelClassName = '';

String objectKindToString(ObjectKind kind) =>
    kind.toString().substring('ObjectKind.k'.length);

String nullabilityToString(Nullability nullability) {
  switch (nullability) {
    case Nullability.nullable:
      return '?';
    case Nullability.undetermined:
      return '%';
    case Nullability.nonNullable:
      return '';
  }
}

/// Represents object (library, class, member, closure, type or name) in the
/// object table.
abstract class ObjectHandle extends BytecodeObject {
  static const int referenceBit = 1 << 0;
  static const int indexShift = 1;
  static const int inlineObject = -1;

  static const int kindShift = 1;
  static const int kindMask = 0x0F;

  static const int flagBit0 = 1 << 5;
  static const int flagBit1 = 1 << 6;
  static const int flagBit2 = 1 << 7;
  static const int flagBit3 = 1 << 8;
  static const int flagBit4 = 1 << 9;
  static const int flagBit5 = 1 << 10;
  static const int flagsMask =
      flagBit0 | flagBit1 | flagBit2 | flagBit3 | flagBit4 | flagBit5;

  static int _makeReference(int index) => (index << indexShift) | referenceBit;

  static int _getIndexFromReference(int reference) {
    assert((reference & referenceBit) != 0);
    return reference >> indexShift;
  }

  static int _makeHeader(ObjectKind kind, int flags) {
    assert((kind.index & kindMask) == kind.index);
    assert((flags & flagsMask) == flags);
    return (kind.index << kindShift) | flags;
  }

  static ObjectKind _getKindFromHeader(int header) {
    assert((header & referenceBit) == 0);
    return ObjectKind.values[(header >> kindShift) & kindMask];
  }

  static int _getFlagsFromHeader(int header) {
    assert((header & referenceBit) == 0);
    return header & flagsMask;
  }

  int _useCount = 0;
  int? _reference;

  ObjectHandle();

  ObjectKind get kind;

  int get flags => 0;
  set flags(int value) {}

  bool get isCacheable => true;
  bool get shouldBeIncludedIntoIndexTable =>
      _useCount >= ObjectTable.indexTableUseCountThreshold && isCacheable;

  factory ObjectHandle._empty(ObjectKind kind, int flags) {
    switch (kind) {
      case ObjectKind.kInvalid:
        return new _InvalidHandle();
      case ObjectKind.kLibrary:
        return new _LibraryHandle._empty();
      case ObjectKind.kClass:
        return new _ClassHandle._empty();
      case ObjectKind.kMember:
        return new _MemberHandle._empty();
      case ObjectKind.kClosure:
        return new _ClosureHandle._empty();
      case ObjectKind.kName:
        return ((flags & _NameHandle.flagIsPublic) != 0)
            ? new _PublicNameHandle._empty()
            : _PrivateNameHandle._empty();
      case ObjectKind.kTypeArguments:
        return new _TypeArgumentsHandle._empty();
      case ObjectKind.kConstObject:
        return new _ConstObjectHandle._empty();
      case ObjectKind.kArgDesc:
        return new _ArgDescHandle._empty();
      case ObjectKind.kScript:
        return new _ScriptHandle._empty();
      case ObjectKind.kType:
        final Nullability nullability =
            ((flags & _TypeHandle.flagIsNullable) != 0)
            ? Nullability.nullable
            : Nullability.nonNullable;
        switch (TypeTag.values[(flags & _TypeHandle.tagMask) ~/ flagBit0]) {
          case TypeTag.kInvalid:
            break;
          case TypeTag.kDynamic:
            return new _DynamicTypeHandle();
          case TypeTag.kVoid:
            return new _VoidTypeHandle();
          case TypeTag.kNull:
            return new _NullTypeHandle();
          case TypeTag.kNever:
            return new _NeverTypeHandle(nullability);
          case TypeTag.kSimpleType:
            return new _SimpleTypeHandle._empty(nullability);
          case TypeTag.kTypeParameter:
            return new _TypeParameterHandle._empty(nullability);
          case TypeTag.kGenericType:
            return new _GenericTypeHandle._empty(nullability);
          case TypeTag.kFunctionType:
            return new _FunctionTypeHandle._empty(nullability);
          case TypeTag.kRecordType:
            return new _RecordTypeHandle._empty(nullability);
        }
        throw 'Unexpected type tag $flags';
    }
  }

  void _write(BufferedWriter writer) {
    int header = _makeHeader(kind, flags);
    assert((header & referenceBit) == 0);
    writer.writePackedUInt30(header);
    writeContents(writer);
  }

  void writeContents(BufferedWriter writer);

  factory ObjectHandle._read(BufferedReader reader, int header) {
    assert((header & referenceBit) == 0);
    final ObjectKind kind = _getKindFromHeader(header);
    final int flags = _getFlagsFromHeader(header);
    final obj = new ObjectHandle._empty(kind, flags);
    obj.flags = flags;
    obj.readContents(reader);
    return obj;
  }

  void readContents(BufferedReader reader);

  void accountUsesForObjectCopies(int numCopies) {}

  void indexStrings(StringWriter strings) {}
}

class _InvalidHandle extends ObjectHandle {
  _InvalidHandle();

  @override
  ObjectKind get kind => ObjectKind.kInvalid;

  @override
  void writeContents(BufferedWriter writer) {}

  @override
  void readContents(BufferedReader reader) {}

  @override
  String toString() => 'Invalid';
}

class _LibraryHandle extends ObjectHandle {
  late _ConstObjectHandle uri;

  _LibraryHandle._empty();

  _LibraryHandle(this.uri);

  @override
  ObjectKind get kind => ObjectKind.kLibrary;

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(uri);
  }

  @override
  void readContents(BufferedReader reader) {
    uri = reader.readPackedObject();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    uri._useCount += numCopies;
  }

  @override
  int get hashCode => uri.hashCode + 11;

  @override
  bool operator ==(other) => other is _LibraryHandle && this.uri == other.uri;

  @override
  String toString() => uri.value;
}

class _ClassHandle extends ObjectHandle {
  late _LibraryHandle library;
  late _NameHandle name;

  _ClassHandle._empty();

  _ClassHandle(this.library, this.name);

  @override
  ObjectKind get kind => ObjectKind.kClass;

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(library);
    writer.writePackedObject(name);
  }

  @override
  void readContents(BufferedReader reader) {
    library = reader.readPackedObject();
    name = reader.readPackedObject();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    library._useCount += numCopies;
    name._useCount += numCopies;
  }

  @override
  int get hashCode => _combineHashes(library.hashCode, name.hashCode);

  @override
  bool operator ==(other) =>
      other is _ClassHandle &&
      this.library == other.library &&
      this.name == other.name;

  @override
  String toString() =>
      name.name == topLevelClassName ? '$library' : '$library::${name.name}';
}

class _MemberHandle extends ObjectHandle {
  static const int flagIsField = ObjectHandle.flagBit0;
  static const int flagIsConstructor = ObjectHandle.flagBit1;

  int _flags = 0;
  late _ClassHandle parent;
  late _NameHandle name;

  _MemberHandle._empty();
  _MemberHandle(this.parent, this.name, bool isField, bool isConstructor) {
    if (isField) {
      _flags |= flagIsField;
    }
    if (isConstructor) {
      _flags |= flagIsConstructor;
    }
  }

  @override
  ObjectKind get kind => ObjectKind.kMember;

  @override
  int get flags => _flags;

  @override
  set flags(int value) {
    _flags = value;
  }

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(parent);
    writer.writePackedObject(name);
  }

  @override
  void readContents(BufferedReader reader) {
    parent = reader.readPackedObject();
    name = reader.readPackedObject();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    parent._useCount += numCopies;
    name._useCount += numCopies;
  }

  @override
  int get hashCode => _combineHashes(parent.hashCode, name.hashCode);

  @override
  bool operator ==(other) =>
      other is _MemberHandle &&
      this.parent == other.parent &&
      this.name == other.name &&
      this.flags == other.flags;

  @override
  String toString() =>
      '$parent::${name.name}' +
      (flags & flagIsField != 0 ? ' (field)' : '') +
      (flags & flagIsConstructor != 0 ? ' (constructor)' : '');
}

class _ClosureHandle extends ObjectHandle {
  late _MemberHandle enclosingMember;
  late int closureIndex;

  _ClosureHandle._empty();

  _ClosureHandle(this.enclosingMember, this.closureIndex) {
    assert(closureIndex >= 0);
  }

  @override
  ObjectKind get kind => ObjectKind.kClosure;

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(enclosingMember);
    writer.writePackedUInt30(closureIndex);
  }

  @override
  void readContents(BufferedReader reader) {
    enclosingMember = reader.readPackedObject();
    closureIndex = reader.readPackedUInt30();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    enclosingMember._useCount += numCopies;
  }

  @override
  int get hashCode => _combineHashes(enclosingMember.hashCode, closureIndex);

  @override
  bool operator ==(other) =>
      other is _ClosureHandle &&
      this.enclosingMember == other.enclosingMember &&
      this.closureIndex == other.closureIndex;

  @override
  String toString() => '$enclosingMember::Closure/$closureIndex';
}

abstract class _TypeHandle extends ObjectHandle {
  static const int tagMask =
      ObjectHandle.flagBit0 |
      ObjectHandle.flagBit1 |
      ObjectHandle.flagBit2 |
      ObjectHandle.flagBit3;
  static const int flagIsNullable = ObjectHandle.flagBit4;

  final TypeTag tag;
  Nullability nullability;

  _TypeHandle(this.tag, this.nullability);

  @override
  ObjectKind get kind => ObjectKind.kType;

  @override
  int get flags =>
      (tag.index * ObjectHandle.flagBit0) |
      (nullability == Nullability.nullable ? flagIsNullable : 0);

  @override
  set flags(int value) {
    if (value != flags) {
      throw 'Unable to set flags for _TypeHandle (they are occupied by type tag and nnbd)';
    }
  }
}

class _DynamicTypeHandle extends _TypeHandle {
  _DynamicTypeHandle() : super(TypeTag.kDynamic, Nullability.nullable);

  @override
  void writeContents(BufferedWriter writer) {}

  @override
  void readContents(BufferedReader reader) {}

  @override
  int get hashCode => 2029;

  @override
  bool operator ==(other) => other is _DynamicTypeHandle;

  @override
  String toString() => 'dynamic';
}

class _VoidTypeHandle extends _TypeHandle {
  _VoidTypeHandle() : super(TypeTag.kVoid, Nullability.nullable);

  @override
  void writeContents(BufferedWriter writer) {}

  @override
  void readContents(BufferedReader reader) {}

  @override
  int get hashCode => 2039;

  @override
  bool operator ==(other) => other is _VoidTypeHandle;

  @override
  String toString() => 'void';
}

class _NullTypeHandle extends _TypeHandle {
  _NullTypeHandle() : super(TypeTag.kNull, Nullability.nullable);

  @override
  void writeContents(BufferedWriter writer) {}

  @override
  void readContents(BufferedReader reader) {}

  @override
  int get hashCode => 2057;

  @override
  bool operator ==(other) => other is _NullTypeHandle;

  @override
  String toString() => 'Null';
}

class _NeverTypeHandle extends _TypeHandle {
  _NeverTypeHandle(Nullability nullability)
    : super(TypeTag.kNever, nullability);

  @override
  void writeContents(BufferedWriter writer) {}

  @override
  void readContents(BufferedReader reader) {}

  @override
  int get hashCode => _combineHashes(2049, nullability.index);

  @override
  bool operator ==(other) =>
      other is _NeverTypeHandle && this.nullability == other.nullability;

  @override
  String toString() => 'Never${nullabilityToString(nullability)}';
}

class _SimpleTypeHandle extends _TypeHandle {
  late _ClassHandle class_;

  _SimpleTypeHandle._empty(Nullability nullability)
    : super(TypeTag.kSimpleType, nullability);

  _SimpleTypeHandle(this.class_, Nullability nullability)
    : super(TypeTag.kSimpleType, nullability);

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(class_);
  }

  @override
  void readContents(BufferedReader reader) {
    class_ = reader.readPackedObject();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    class_._useCount += numCopies;
  }

  @override
  int get hashCode => _combineHashes(class_.hashCode, nullability.index);

  @override
  bool operator ==(other) =>
      other is _SimpleTypeHandle &&
      this.class_ == other.class_ &&
      this.nullability == other.nullability;

  @override
  String toString() => '$class_${nullabilityToString(nullability)}';
}

class TypeParameterDeclaration {
  final ObjectHandle name;
  final ObjectHandle? bound;
  final ObjectHandle? defaultType;

  TypeParameterDeclaration(this.name, this.bound, this.defaultType);

  @override
  int get hashCode => _combineHashes(
    name.hashCode,
    _combineHashes(bound.hashCode, defaultType.hashCode),
  );

  @override
  bool operator ==(other) =>
      other is TypeParameterDeclaration &&
      this.name == other.name &&
      this.bound == other.bound &&
      this.defaultType == other.defaultType;

  @override
  String toString() => '${name} extends $bound (default $defaultType)';
}

class _TypeParameterHandle extends _TypeHandle {
  ObjectHandle? parent;
  late int indexInParent;

  _TypeParameterHandle._empty(Nullability nullability)
    : super(TypeTag.kTypeParameter, nullability);

  _TypeParameterHandle(this.parent, this.indexInParent, Nullability nullability)
    : super(TypeTag.kTypeParameter, nullability) {
    assert(
      parent is _ClassHandle ||
          parent is _MemberHandle ||
          parent is _ClosureHandle ||
          parent == null,
    );
    assert(indexInParent >= 0);
  }

  @override
  bool get isCacheable => (parent != null);

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(parent);
    writer.writePackedUInt30(indexInParent);
  }

  @override
  void readContents(BufferedReader reader) {
    parent = reader.readPackedObject();
    indexInParent = reader.readPackedUInt30();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    final parent = this.parent;
    if (parent != null) {
      parent._useCount += numCopies;
    }
  }

  @override
  int get hashCode => _combineHashes(
    parent.hashCode,
    _combineHashes(indexInParent, nullability.index),
  );

  @override
  bool operator ==(other) =>
      other is _TypeParameterHandle &&
      this.parent == other.parent &&
      this.indexInParent == other.indexInParent &&
      this.nullability == other.nullability;

  @override
  String toString() =>
      '$parent::TypeParam/$indexInParent${nullabilityToString(nullability)}';
}

class _GenericTypeHandle extends _TypeHandle {
  late _ClassHandle class_;
  _TypeArgumentsHandle? typeArgs;

  _GenericTypeHandle._empty(Nullability nullability)
    : super(TypeTag.kGenericType, nullability);

  _GenericTypeHandle(this.class_, this.typeArgs, Nullability nullability)
    : super(TypeTag.kGenericType, nullability);

  @override
  bool get isCacheable => typeArgs?.isCacheable ?? true;

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(class_);
    writer.writePackedObject(typeArgs);
  }

  @override
  void readContents(BufferedReader reader) {
    class_ = reader.readPackedObject();
    typeArgs = reader.readPackedObject();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    class_._useCount += numCopies;
    final typeArgs = this.typeArgs;
    if (typeArgs != null) {
      typeArgs._useCount += numCopies;
    }
  }

  @override
  int get hashCode => _combineHashes(
    class_.hashCode,
    _combineHashes(typeArgs.hashCode, nullability.index),
  );

  @override
  bool operator ==(other) =>
      other is _GenericTypeHandle &&
      this.class_ == other.class_ &&
      this.typeArgs == other.typeArgs &&
      this.nullability == other.nullability;

  @override
  String toString() => '$class_ $typeArgs${nullabilityToString(nullability)}';
}

class NameAndType {
  _NameHandle name;
  _TypeHandle type;

  NameAndType(ObjectHandle name_, ObjectHandle type_)
    : name = name_ as _NameHandle,
      type = type_ as _TypeHandle;

  @override
  int get hashCode => _combineHashes(name.hashCode, type.hashCode);

  @override
  bool operator ==(other) =>
      other is NameAndType &&
      this.name == other.name &&
      this.type == other.type;

  @override
  String toString() => '$type ${name.name}';
}

class ParameterFlags {
  // Parameter flags in FunctionDeclaration, ClosureDeclaration and
  // FunctionType.
  static const isRequiredFlag = 1 << 0;
  // Parameter flags in Code.
  static const isCovariantFlag = 1 << 0;
  static const isCovariantByClassFlag = 1 << 1;

  static List<int>? finalizeFlags(List<int> paramFlags) {
    for (int flags in paramFlags) {
      if (flags != 0) {
        return paramFlags;
      }
    }
    return null;
  }

  static int getVariableDeclarationFlags(Variable variable, bool isCode) {
    int flags = 0;
    if (isCode) {
      if (variable.isCovariantByDeclaration) {
        flags |= isCovariantFlag;
      }
      if (variable.isCovariantByClass) {
        flags |= isCovariantByClassFlag;
      }
    } else {
      if (variable.isRequired) {
        flags |= isRequiredFlag;
      }
    }
    return flags;
  }

  // Get parameter flags for the given [function].
  // Returns null if parameters do not have any flags.
  static List<int>? getFunctionFlags(
    FunctionNode function, {
    required bool isCode,
  }) {
    final paramFlags = <int>[];
    if (isCode) {
      for (var param in function.positionalParameters) {
        paramFlags.add(getVariableDeclarationFlags(param, isCode));
      }
    }
    for (var param in function.namedParameters) {
      paramFlags.add(getVariableDeclarationFlags(param, isCode));
    }
    return finalizeFlags(paramFlags);
  }

  static int getNamedTypeFlags(NamedType param) {
    int flags = 0;
    if (param.isRequired) {
      flags |= isRequiredFlag;
    }
    return flags;
  }

  // Get flags for named parameters of the given [functionType].
  // Returns null if named parameters do not have any flags.
  static List<int>? getFunctionTypeFlags(FunctionType functionType) {
    final namedParameters = functionType.namedParameters;
    final paramFlags = List<int>.generate(
      namedParameters.length,
      (i) => getNamedTypeFlags(namedParameters[i]),
    );
    return finalizeFlags(paramFlags);
  }
}

class _FunctionTypeHandle extends _TypeHandle {
  static const int flagHasOptionalPositionalParams = 1 << 0;
  static const int flagHasOptionalNamedParams = 1 << 1;
  static const int flagHasTypeParams = 1 << 2;
  static const int flagHasEnclosingTypeParameters = 1 << 3;
  static const int flagHasParameterFlags = 1 << 4;

  int functionTypeFlags = 0;
  late int numEnclosingTypeParameters;
  TypeParametersDeclaration? typeParameters;
  late int numRequiredParams;
  late List<_TypeHandle> positionalParams;
  late List<NameAndType> namedParams;
  // Only contains the required flag for named parameters when present.
  late List<int>? parameterFlags;
  late _TypeHandle returnType;

  _FunctionTypeHandle._empty(Nullability nullability)
    : super(TypeTag.kFunctionType, nullability);

  _FunctionTypeHandle(
    this.numEnclosingTypeParameters,
    this.typeParameters,
    this.numRequiredParams,
    this.positionalParams,
    this.namedParams,
    this.parameterFlags,
    this.returnType,
    Nullability nullability,
  ) : super(TypeTag.kFunctionType, nullability) {
    assert(numRequiredParams <= positionalParams.length + namedParams.length);
    if (numRequiredParams < positionalParams.length) {
      assert(namedParams.isEmpty);
      functionTypeFlags |= flagHasOptionalPositionalParams;
    }
    if (namedParams.isNotEmpty) {
      assert(numRequiredParams == positionalParams.length);
      functionTypeFlags |= flagHasOptionalNamedParams;
    }
    if (parameterFlags != null) {
      assert(namedParams.isNotEmpty);
      assert(parameterFlags!.length == namedParams.length);
      functionTypeFlags |= flagHasParameterFlags;
    }
    if (typeParameters != null) {
      functionTypeFlags |= flagHasTypeParams;
    }
    if (numEnclosingTypeParameters != 0) {
      functionTypeFlags |= flagHasEnclosingTypeParameters;
    }
  }

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedUInt30(functionTypeFlags);
    if ((functionTypeFlags & flagHasEnclosingTypeParameters) != 0) {
      writer.writePackedUInt30(numEnclosingTypeParameters);
    }
    if ((functionTypeFlags & flagHasTypeParams) != 0) {
      typeParameters!.write(writer);
    }
    writer.writePackedUInt30(positionalParams.length + namedParams.length);
    if (functionTypeFlags &
            (flagHasOptionalPositionalParams | flagHasOptionalNamedParams) !=
        0) {
      writer.writePackedUInt30(numRequiredParams);
    }
    for (var param in positionalParams) {
      writer.writePackedObject(param);
    }
    for (var param in namedParams) {
      writer.writePackedObject(param.name);
      writer.writePackedObject(param.type);
    }
    if ((functionTypeFlags & flagHasParameterFlags) != 0) {
      final parameterFlags = this.parameterFlags!;
      writer.writePackedUInt30(parameterFlags.length);
      parameterFlags.forEach((flags) => writer.writePackedUInt30(flags));
    }
    writer.writePackedObject(returnType);
  }

  @override
  void readContents(BufferedReader reader) {
    functionTypeFlags = reader.readPackedUInt30();
    numEnclosingTypeParameters =
        ((functionTypeFlags & flagHasEnclosingTypeParameters) != 0)
        ? reader.readPackedUInt30()
        : 0;
    typeParameters = ((functionTypeFlags & flagHasTypeParams) != 0)
        ? TypeParametersDeclaration.read(reader)
        : null;
    final int numParams = reader.readPackedUInt30();
    numRequiredParams = numParams;
    if ((functionTypeFlags &
            (flagHasOptionalPositionalParams | flagHasOptionalNamedParams)) !=
        0) {
      numRequiredParams = reader.readPackedUInt30();
    }
    final bool hasNamedParams =
        (functionTypeFlags & flagHasOptionalNamedParams) != 0;
    positionalParams = new List<_TypeHandle>.generate(
      hasNamedParams ? numRequiredParams : numParams,
      (_) => reader.readPackedObject(),
    );
    if (hasNamedParams) {
      namedParams = new List<NameAndType>.generate(
        numParams - numRequiredParams,
        (_) => new NameAndType(
          reader.readPackedObject(),
          reader.readPackedObject(),
        ),
      );
    } else {
      namedParams = const <NameAndType>[];
    }
    parameterFlags = ((functionTypeFlags & flagHasParameterFlags) != 0)
        ? List<int>.generate(
            reader.readPackedUInt30(),
            (_) => reader.readPackedUInt30(),
          )
        : null;
    returnType = reader.readPackedObject();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    positionalParams.forEach((p) {
      p._useCount += numCopies;
    });
    namedParams.forEach((p) {
      p.name._useCount += numCopies;
      p.type._useCount += numCopies;
    });
  }

  @override
  bool get isCacheable {
    if ((functionTypeFlags & flagHasEnclosingTypeParameters) != 0) {
      return false;
    }
    for (var param in positionalParams) {
      if (!param.isCacheable) {
        return false;
      }
    }
    for (var param in namedParams) {
      if (!param.type.isCacheable) {
        return false;
      }
    }
    if (!returnType.isCacheable) {
      return false;
    }
    return true;
  }

  @override
  int get hashCode {
    int hash = typeParameters.hashCode;
    hash = _combineHashes(hash, numEnclosingTypeParameters);
    hash = _combineHashes(hash, numRequiredParams);
    hash = _combineHashes(hash, listHashCode(positionalParams));
    hash = _combineHashes(hash, listHashCode(namedParams));
    if (parameterFlags != null) {
      hash = _combineHashes(hash, listHashCode(parameterFlags!));
    }
    hash = _combineHashes(hash, returnType.hashCode);
    hash = _combineHashes(hash, nullability.index);
    return hash;
  }

  @override
  bool operator ==(other) =>
      other is _FunctionTypeHandle &&
      this.numEnclosingTypeParameters == other.numEnclosingTypeParameters &&
      this.typeParameters == other.typeParameters &&
      this.numRequiredParams == other.numRequiredParams &&
      listEquals(this.positionalParams, other.positionalParams) &&
      listEquals(this.namedParams, other.namedParams) &&
      (identical(this.parameterFlags, other.parameterFlags) ||
          (this.parameterFlags != null &&
              other.parameterFlags != null &&
              listEquals(this.parameterFlags!, other.parameterFlags!))) &&
      this.returnType == other.returnType &&
      this.nullability == other.nullability;

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('FunctionType');
    if ((functionTypeFlags & flagHasEnclosingTypeParameters) != 0) {
      sb.write(' <enclosing-type-params: $numEnclosingTypeParameters>');
    }
    if ((functionTypeFlags & flagHasTypeParams) != 0) {
      sb.write(' $typeParameters');
    }
    sb.write(' (');
    sb.write(positionalParams.sublist(0, numRequiredParams).join(', '));
    if (numRequiredParams != positionalParams.length) {
      if (numRequiredParams > 0) {
        sb.write(', ');
      }
      sb.write('[ ${positionalParams.sublist(numRequiredParams).join(', ')} ]');
    }
    if (namedParams.isNotEmpty) {
      if (numRequiredParams > 0) {
        sb.write(', ');
      }
      sb.write('{ ');
      final flags = this.parameterFlags;
      assert(flags == null || flags.length == namedParams.length);
      for (int i = 0; i < namedParams.length; ++i) {
        if (i != 0) {
          sb.write(', ');
        }
        // We only store the required flag.
        if (flags != null && (flags[i] & ParameterFlags.isRequiredFlag) != 0) {
          sb.write('required ');
        }
        sb.write(namedParams[i]);
      }
      sb.write(' }');
    }
    sb.write(')${nullabilityToString(nullability)} -> ');
    sb.write(returnType);
    return sb.toString();
  }
}

class _RecordTypeHandle extends _TypeHandle {
  late List<_TypeHandle> positional;
  late List<NameAndType> named;

  _RecordTypeHandle._empty(Nullability nullability)
    : super(TypeTag.kRecordType, nullability);

  _RecordTypeHandle(this.positional, this.named, Nullability nullability)
    : super(TypeTag.kRecordType, nullability);

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedUInt30(positional.length);
    writer.writePackedUInt30(named.length);
    for (var field in positional) {
      writer.writePackedObject(field);
    }
    for (var field in named) {
      writer.writePackedObject(field.name);
      writer.writePackedObject(field.type);
    }
  }

  @override
  void readContents(BufferedReader reader) {
    final int numPositional = reader.readPackedUInt30();
    final int numNamed = reader.readPackedUInt30();
    positional = List<_TypeHandle>.generate(
      numPositional,
      (_) => reader.readPackedObject(),
    );
    named = List<NameAndType>.generate(
      numNamed,
      (_) =>
          new NameAndType(reader.readPackedObject(), reader.readPackedObject()),
    );
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    positional.forEach((f) {
      f._useCount += numCopies;
    });
    named.forEach((f) {
      f.name._useCount += numCopies;
      f.type._useCount += numCopies;
    });
  }

  @override
  bool get isCacheable {
    for (var f in positional) {
      if (!f.isCacheable) {
        return false;
      }
    }
    for (var f in named) {
      if (!f.type.isCacheable) {
        return false;
      }
    }
    return true;
  }

  @override
  int get hashCode {
    int hash = _combineHashes(listHashCode(positional), listHashCode(named));
    hash = _combineHashes(hash, nullability.index);
    return hash;
  }

  @override
  bool operator ==(other) =>
      other is _RecordTypeHandle &&
      listEquals(this.positional, other.positional) &&
      listEquals(this.named, other.named) &&
      this.nullability == other.nullability;

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('RecordType(');
    sb.write(positional.join(', '));
    if (named.isNotEmpty) {
      if (positional.isNotEmpty) {
        sb.write(', ');
      }
      sb.write(named.join(', '));
    }
    sb.write(')${nullabilityToString(nullability)}');
    return sb.toString();
  }
}

abstract class _NameHandle extends ObjectHandle {
  static const int flagIsPublic = ObjectHandle.flagBit0;

  String get name;

  @override
  ObjectKind get kind => ObjectKind.kName;

  @override
  void indexStrings(StringWriter strings) {
    strings.put(name);
  }

  @override
  String toString() => "'$name'";
}

class _PublicNameHandle extends _NameHandle {
  late String name;

  _PublicNameHandle._empty();

  _PublicNameHandle(this.name);

  @override
  int get flags => _NameHandle.flagIsPublic;

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedStringReference(name);
  }

  @override
  void readContents(BufferedReader reader) {
    name = reader.readPackedStringReference();
  }

  @override
  int get hashCode => name.hashCode;

  @override
  bool operator ==(other) =>
      other is _PublicNameHandle && this.name == other.name;

  @override
  String toString() => "'$name'";
}

class _PrivateNameHandle extends _NameHandle {
  late _LibraryHandle library;
  late String name;

  _PrivateNameHandle._empty();

  _PrivateNameHandle(this.library, this.name);

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(library);
    writer.writePackedStringReference(name);
  }

  @override
  void readContents(BufferedReader reader) {
    library = reader.readPackedObject();
    name = reader.readPackedStringReference();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    library._useCount += numCopies;
  }

  @override
  int get hashCode => _combineHashes(name.hashCode, library.hashCode);

  @override
  bool operator ==(other) =>
      other is _PrivateNameHandle &&
      this.name == other.name &&
      this.library == other.library;

  @override
  String toString() => "'$name'";
}

class _TypeArgumentsHandle extends ObjectHandle {
  late List<_TypeHandle> args;

  _TypeArgumentsHandle._empty();

  _TypeArgumentsHandle(this.args);

  @override
  ObjectKind get kind => ObjectKind.kTypeArguments;

  @override
  bool get isCacheable {
    for (var arg in args) {
      if (!arg.isCacheable) {
        return false;
      }
    }
    return true;
  }

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedList(args);
  }

  @override
  void readContents(BufferedReader reader) {
    args = reader.readPackedList<_TypeHandle>();
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    args.forEach((t) {
      t._useCount += numCopies;
    });
  }

  @override
  int get hashCode => listHashCode(args);

  @override
  bool operator ==(other) =>
      other is _TypeArgumentsHandle && listEquals(this.args, other.args);

  @override
  String toString() => '< ${args.join(', ')} >';
}

class _ConstObjectHandle extends ObjectHandle {
  late ConstTag tag;
  late dynamic value;
  ObjectHandle? type;
  int _hashCode = 0;

  _ConstObjectHandle._empty();

  _ConstObjectHandle(this.tag, this.value, [this.type]);

  @override
  ObjectKind get kind => ObjectKind.kConstObject;

  @override
  int get flags => tag.index * ObjectHandle.flagBit0;

  @override
  set flags(int value) {
    tag = ConstTag.values[value ~/ ObjectHandle.flagBit0];
    assert(tag != ConstTag.kInvalid);
  }

  bool get isCacheable => (tag != ConstTag.kInt) && (tag != ConstTag.kBool);

  @override
  void writeContents(BufferedWriter writer) {
    switch (tag) {
      case ConstTag.kInt:
        writer.writeSLEB128(value as int);
        break;
      case ConstTag.kDouble:
        writer.writeSLEB128(doubleToIntBits(value as double));
        break;
      case ConstTag.kBool:
        writer.writeByte((value as bool) ? 1 : 0);
        break;
      case ConstTag.kInstance:
        {
          final fieldValues = value as Map<ObjectHandle, ObjectHandle?>;
          writer.writePackedObject(type);
          writer.writePackedUInt30(fieldValues.length);
          fieldValues.forEach((ObjectHandle field, ObjectHandle? value) {
            writer.writePackedObject(field);
            writer.writePackedObject(value);
          });
        }
        break;
      case ConstTag.kList:
      case ConstTag.kRecord:
      case ConstTag.kMap:
      case ConstTag.kSet:
        {
          final elems = value as List<ObjectHandle?>;
          writer.writePackedObject(type);
          writer.writePackedList(elems);
        }
        break;
      case ConstTag.kTearOff:
        {
          final target = value as ObjectHandle;
          writer.writePackedObject(target);
        }
        break;
      case ConstTag.kSymbol:
        {
          final name = value as ObjectHandle;
          writer.writePackedObject(name);
        }
        break;
      case ConstTag.kTearOffInstantiation:
        {
          final tearOff = value as ObjectHandle;
          writer.writePackedObject(tearOff);
          writer.writePackedObject(type as _TypeArgumentsHandle);
        }
        break;
      case ConstTag.kString:
        writer.writePackedStringReference(value as String);
        break;
      default:
        throw 'Unexpected constant tag: $tag';
    }
  }

  @override
  void readContents(BufferedReader reader) {
    switch (tag) {
      case ConstTag.kInt:
        value = reader.readSLEB128();
        break;
      case ConstTag.kDouble:
        value = intBitsToDouble(reader.readSLEB128());
        break;
      case ConstTag.kBool:
        value = reader.readByte() != 0;
        break;
      case ConstTag.kInstance:
        type = reader.readPackedObject();
        value = Map<ObjectHandle, ObjectHandle?>.fromEntries(
          new List<MapEntry<ObjectHandle, ObjectHandle?>>.generate(
            reader.readPackedUInt30(),
            (_) => new MapEntry<ObjectHandle, ObjectHandle?>(
              reader.readPackedObject(),
              reader.readPackedObject(),
            ),
          ),
        );
        break;
      case ConstTag.kList:
      case ConstTag.kRecord:
      case ConstTag.kMap:
      case ConstTag.kSet:
        type = reader.readPackedObject();
        value = reader.readPackedList<ObjectHandle?>();
        break;
      case ConstTag.kTearOff:
        value = reader.readPackedObject();
        break;
      case ConstTag.kSymbol:
        value = reader.readPackedObject();
        break;
      case ConstTag.kTearOffInstantiation:
        value = reader.readPackedObject();
        type = reader.readPackedObject();
        break;
      case ConstTag.kString:
        value = reader.readPackedStringReference();
        break;
      default:
        throw 'Unexpected constant tag: $tag';
    }
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    switch (tag) {
      case ConstTag.kInt:
      case ConstTag.kDouble:
      case ConstTag.kBool:
      case ConstTag.kString:
        break;
      case ConstTag.kInstance:
        {
          type!._useCount += numCopies;
          final fieldValues = value as Map<ObjectHandle, ObjectHandle?>;
          fieldValues.forEach((ObjectHandle field, ObjectHandle? value) {
            field._useCount += numCopies;
            value?._useCount += numCopies;
          });
        }
        break;
      case ConstTag.kList:
      case ConstTag.kRecord:
      case ConstTag.kMap:
      case ConstTag.kSet:
        {
          final elems = value as List<ObjectHandle?>;
          for (var elem in elems) {
            elem?._useCount += numCopies;
          }
          type!._useCount += numCopies;
        }
        break;
      case ConstTag.kTearOff:
        {
          final target = value as ObjectHandle;
          target._useCount += numCopies;
        }
        break;
      case ConstTag.kSymbol:
        {
          final name = value as ObjectHandle;
          name._useCount += numCopies;
        }
        break;
      case ConstTag.kTearOffInstantiation:
        {
          final tearOff = value as ObjectHandle;
          tearOff._useCount += numCopies;
          final type = this.type;
          if (type != null) {
            type._useCount += numCopies;
          }
        }
        break;
      default:
        throw 'Unexpected constant tag: $tag';
    }
  }

  static int mapHashCode(Map map) {
    final entryHashes = List<int>.filled(map.length, -1);
    int i = 0;
    for (MapEntry entry in map.entries) {
      entryHashes[i++] = _combineHashes(
        entry.key.hashCode,
        entry.value.hashCode,
      );
    }
    entryHashes.sort();
    return listHashCode(entryHashes);
  }

  static int listHashCode(List list) {
    int hash = 31;
    for (int i = 0; i < list.length; ++i) {
      hash = _combineHashes(hash, list[i].hashCode);
    }
    return hash;
  }

  @override
  int get hashCode {
    if (_hashCode != 0) {
      return _hashCode;
    }
    switch (tag) {
      case ConstTag.kInt:
      case ConstTag.kDouble:
      case ConstTag.kBool:
      case ConstTag.kTearOff:
      case ConstTag.kSymbol:
      case ConstTag.kString:
        return _hashCode = value.hashCode;
      case ConstTag.kInstance:
        {
          final fieldValues = value as Map<ObjectHandle, ObjectHandle?>;
          return _hashCode = _combineHashes(
            type.hashCode,
            mapHashCode(fieldValues),
          );
        }
      case ConstTag.kList:
      case ConstTag.kRecord:
      case ConstTag.kMap:
      case ConstTag.kSet:
        {
          final elems = value as List<ObjectHandle?>;
          return _hashCode = _combineHashes(type.hashCode, listHashCode(elems));
        }
      case ConstTag.kTearOffInstantiation:
        return _hashCode = _combineHashes(value.hashCode, type.hashCode);
      default:
        throw 'Unexpected constant tag: $tag';
    }
  }

  @override
  bool operator ==(other) {
    if (identical(this, other)) {
      return true;
    }
    if (other is _ConstObjectHandle && this.tag == other.tag) {
      switch (tag) {
        case ConstTag.kInt:
        case ConstTag.kBool:
        case ConstTag.kTearOff:
        case ConstTag.kSymbol:
        case ConstTag.kString:
          return this.value == other.value;
        case ConstTag.kDouble:
          return this.value.compareTo(other.value) == 0;
        case ConstTag.kInstance:
          return this.type == other.type && mapEquals(this.value, other.value);
        case ConstTag.kList:
        case ConstTag.kRecord:
        case ConstTag.kMap:
        case ConstTag.kSet:
          return this.type == other.type && listEquals(this.value, other.value);
        case ConstTag.kTearOffInstantiation:
          return this.type == other.type && this.value == other.value;
        default:
          throw 'Unexpected constant tag: $tag';
      }
    }
    return false;
  }

  @override
  String toString() {
    switch (tag) {
      case ConstTag.kInt:
      case ConstTag.kDouble:
      case ConstTag.kBool:
      case ConstTag.kSymbol:
        return 'const $value';
      case ConstTag.kInstance:
        return 'const $type $value';
      case ConstTag.kList:
        return 'const List<$type> $value';
      case ConstTag.kRecord:
        return 'const Record<$type> $value';
      case ConstTag.kMap:
        return 'const Map<$type> $value';
      case ConstTag.kSet:
        return 'const Set<$type> $value';
      case ConstTag.kTearOff:
        return 'const tear-off $value';
      case ConstTag.kTearOffInstantiation:
        return 'const $type $value';
      case ConstTag.kString:
        return "'$value'";
      default:
        throw 'Unexpected constant tag: $tag';
    }
  }
}

class _ArgDescHandle extends ObjectHandle {
  static const int flagHasNamedArgs = ObjectHandle.flagBit0;
  static const int flagHasTypeArgs = ObjectHandle.flagBit1;

  int _flags = 0;
  late int numArguments;
  late int numTypeArguments;
  late List<_PublicNameHandle> argNames;

  _ArgDescHandle._empty();

  _ArgDescHandle(this.numArguments, this.numTypeArguments, this.argNames) {
    if (argNames.isNotEmpty) {
      _flags |= flagHasNamedArgs;
    }
    if (numTypeArguments > 0) {
      _flags |= flagHasTypeArgs;
    }
  }

  @override
  ObjectKind get kind => ObjectKind.kArgDesc;

  @override
  int get flags => _flags;

  @override
  set flags(int value) {
    _flags = value;
  }

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedUInt30(numArguments);
    if ((_flags & flagHasTypeArgs) != 0) {
      writer.writePackedUInt30(numTypeArguments);
    }
    if ((_flags & flagHasNamedArgs) != 0) {
      writer.writePackedList(argNames);
    }
  }

  @override
  void readContents(BufferedReader reader) {
    numArguments = reader.readPackedUInt30();
    numTypeArguments = ((_flags & flagHasTypeArgs) != 0)
        ? reader.readPackedUInt30()
        : 0;
    argNames = ((_flags & flagHasNamedArgs) != 0)
        ? reader.readPackedList<_PublicNameHandle>()
        : const <_PublicNameHandle>[];
  }

  @override
  void accountUsesForObjectCopies(int numCopies) {
    for (var name in argNames) {
      name._useCount += numCopies;
    }
  }

  @override
  int get hashCode => _combineHashes(
    numArguments,
    _combineHashes(numTypeArguments, listHashCode(argNames)),
  );

  @override
  bool operator ==(other) =>
      other is _ArgDescHandle &&
      this.numArguments == other.numArguments &&
      this.numTypeArguments == other.numTypeArguments &&
      listEquals(this.argNames, other.argNames);

  @override
  String toString() =>
      'ArgDesc num-args $numArguments, num-type-args $numTypeArguments, names $argNames';
}

class _ScriptHandle extends ObjectHandle {
  static const int flagHasSourceFile = ObjectHandle.flagBit0;

  int _flags = 0;
  late ObjectHandle uri;
  SourceFile? _source;
  ForwardReference<SourceFile>? _sourceForwardReference;

  _ScriptHandle._empty();

  _ScriptHandle(this.uri, this._source) {
    if (_source != null) {
      _flags |= flagHasSourceFile;
    }
  }

  @override
  ObjectKind get kind => ObjectKind.kScript;

  // Include scripts into index table if there are more than 1 reference
  // in order to make sure there are no duplicated script objects within the
  // same bytecode component.
  @override
  bool get shouldBeIncludedIntoIndexTable => _useCount > 1;

  @override
  int get flags => _flags;

  @override
  set flags(int value) {
    _flags = value;
  }

  SourceFile? get source {
    // Unwrap forward reference on the first access.
    final sourceForwardReference = this._sourceForwardReference;
    if (sourceForwardReference != null) {
      _source = sourceForwardReference.get();
      _sourceForwardReference = null;
    }
    return _source;
  }

  set source(SourceFile? sourceFile) {
    _source = sourceFile;
    if (_source != null) {
      _flags |= flagHasSourceFile;
    } else {
      _flags &= ~flagHasSourceFile;
    }
  }

  @override
  void writeContents(BufferedWriter writer) {
    writer.writePackedObject(uri);
    if ((_flags & flagHasSourceFile) != 0) {
      writer.writeLinkOffset(source!);
    }
  }

  @override
  void readContents(BufferedReader reader) {
    uri = reader.readPackedObject();
    if ((_flags & flagHasSourceFile) != 0) {
      // Script handles in the object table may be read before source files,
      // so use forwarding reference here.
      _sourceForwardReference = reader
          .readLinkOffsetAsForwardReference<SourceFile>();
    }
  }

  @override
  int get hashCode => uri.hashCode;

  @override
  bool operator ==(other) => other is _ScriptHandle && this.uri == other.uri;

  @override
  String toString() => "$uri${source != null ? '($source)' : ''}";
}

class ObjectTable implements ObjectWriter, ObjectReader {
  /// Object is added to an index table if it is used more than this
  /// number of times.
  static const int indexTableUseCountThreshold = 3;

  final List<ObjectHandle> _objects = <ObjectHandle>[];
  final Map<ObjectHandle, ObjectHandle> _canonicalizationCache =
      <ObjectHandle, ObjectHandle>{};
  final Map<Node, ObjectHandle> _nodeCache = <Node, ObjectHandle>{};
  final Map<String, _PublicNameHandle> _publicNames =
      <String, _PublicNameHandle>{};
  List<ObjectHandle>? _indexTable;
  late _TypeHandle _dynamicType;
  late _TypeHandle _voidType;
  late _TypeHandle _nullType;
  late _NodeVisitor _nodeVisitor;
  int numEnclosingFunctionTypeParameters = 0;

  ObjectTable(CoreTypes coreTypes) {
    _dynamicType = getOrAddObject(_DynamicTypeHandle()) as _TypeHandle;
    _voidType = getOrAddObject(_VoidTypeHandle()) as _TypeHandle;
    _nullType = getOrAddObject(_NullTypeHandle()) as _TypeHandle;
    _nodeVisitor = _NodeVisitor(this, coreTypes);
  }

  // Can be used to add instantiated types and constants which
  // should not depend on type parameters of the enclosing function.
  T withoutEnclosingFunctionTypeParameters<T>(T Function() action) {
    final saved = numEnclosingFunctionTypeParameters;
    numEnclosingFunctionTypeParameters = 0;
    final result = action();
    numEnclosingFunctionTypeParameters = saved;
    return result;
  }

  ObjectHandle? getHandle(Node? node) {
    if (node == null) {
      return null;
    }
    ObjectHandle? handle = _nodeCache[node];
    if (handle == null) {
      handle = node.accept(_nodeVisitor);
      if (handle != null && handle.isCacheable) {
        _nodeCache[node] = handle;
      }
    } else {
      ++handle._useCount;
    }
    return handle;
  }

  List<ObjectHandle?> getHandles(List<Node?> nodes) {
    return List<ObjectHandle?>.generate(
      nodes.length,
      (int i) => getHandle(nodes[i]),
    );
  }

  List<ObjectHandle> getNonNullHandles(List<Node> nodes) {
    return List<ObjectHandle>.generate(
      nodes.length,
      (int i) => getHandle(nodes[i])!,
    );
  }

  String mangleGetterName(String name) => 'get:$name';

  String mangleSetterName(String name) => 'set:$name';

  String mangleSelectorName(String name, bool isGetter, bool isSetter) {
    if (isGetter) {
      return mangleGetterName(name);
    } else if (isSetter) {
      return mangleSetterName(name);
    } else {
      return name;
    }
  }

  String mangleMemberName(Member member, bool isGetter, bool isSetter) {
    final name = member.name.text;
    if (isGetter || (member is Procedure && member.isGetter)) {
      return mangleGetterName(name);
    }
    if (isSetter || (member is Procedure && member.isSetter)) {
      return mangleSetterName(name);
    }
    return name;
  }

  _PublicNameHandle getPublicNameHandle(String name) {
    _PublicNameHandle? handle = _publicNames[name];
    if (handle == null) {
      handle = getOrAddObject(_PublicNameHandle(name)) as _PublicNameHandle;
      _publicNames[name] = handle;
    }
    return handle;
  }

  ObjectHandle getNameHandle(Library? library, String name) {
    if (library == null) {
      return getPublicNameHandle(name);
    }
    final libraryHandle = getHandle(library) as _LibraryHandle;
    return getOrAddObject(_PrivateNameHandle(libraryHandle, name));
  }

  List<_PublicNameHandle> getPublicNameHandles(List<String> names) {
    if (names.isEmpty) {
      return const <_PublicNameHandle>[];
    }
    return List<_PublicNameHandle>.generate(
      names.length,
      (int i) => getPublicNameHandle(names[i]),
    );
  }

  ObjectHandle getConstStringHandle(String value) =>
      getOrAddObject(new _ConstObjectHandle(ConstTag.kString, value));

  List<ObjectHandle> getConstStringHandles(List<String> values) {
    if (values.isEmpty) {
      return const <ObjectHandle>[];
    }
    return List<ObjectHandle>.generate(
      values.length,
      (int i) => getConstStringHandle(values[i]),
    );
  }

  ObjectHandle getSelectorNameHandle(
    Name name, {
    bool isGetter = false,
    bool isSetter = false,
  }) {
    return getNameHandle(
      name.library,
      mangleSelectorName(name.text, isGetter, isSetter),
    );
  }

  ObjectHandle getTopLevelClassHandle(Library library) {
    final libraryHandle = getHandle(library) as _LibraryHandle;
    final name = getPublicNameHandle(topLevelClassName);
    return getOrAddObject(new _ClassHandle(libraryHandle, name));
  }

  ObjectHandle getMemberHandle(
    Member member, {
    bool isGetter = false,
    bool isSetter = false,
  }) {
    final parent = member.parent;
    _ClassHandle classHandle;
    if (parent is Class) {
      classHandle = getHandle(parent) as _ClassHandle;
    } else if (parent is Library) {
      classHandle = getTopLevelClassHandle(parent) as _ClassHandle;
    } else {
      throw "Unexpected Member's parent ${parent.runtimeType} $parent";
    }
    final nameHandle =
        getNameHandle(
              member.name.library,
              mangleMemberName(member, isGetter, isSetter),
            )
            as _NameHandle;
    bool isField = member is Field && !isGetter && !isSetter;
    bool isConstructor =
        member is Constructor || (member is Procedure && member.isFactory);
    return getOrAddObject(
      new _MemberHandle(classHandle, nameHandle, isField, isConstructor),
    );
  }

  ObjectHandle? getTypeArgumentsHandle(List<DartType>? typeArgs) {
    if (typeArgs == null) {
      return null;
    }
    final handles = List<_TypeHandle>.generate(
      typeArgs.length,
      (int i) => getHandle(typeArgs[i]) as _TypeHandle,
    );
    return getOrAddObject(new _TypeArgumentsHandle(handles));
  }

  ObjectHandle getArgDescHandle(
    int numArguments, [
    int numTypeArguments = 0,
    List<String> argNames = const <String>[],
  ]) {
    return getOrAddObject(
      new _ArgDescHandle(
        numArguments,
        numTypeArguments,
        getPublicNameHandles(argNames),
      ),
    );
  }

  ObjectHandle getArgDescHandleByArguments(
    Arguments args, {
    bool hasReceiver = false,
  }) {
    List<_PublicNameHandle> argNames = const <_PublicNameHandle>[];
    final namedArguments = args.named;
    if (namedArguments.isNotEmpty) {
      argNames = List<_PublicNameHandle>.generate(
        namedArguments.length,
        (int i) => getPublicNameHandle(namedArguments[i].name),
      );
    }
    final int numArguments =
        args.positional.length + args.named.length + (hasReceiver ? 1 : 0);
    final int numTypeArguments = args.types.length;
    return getOrAddObject(
      new _ArgDescHandle(numArguments, numTypeArguments, argNames),
    );
  }

  ObjectHandle getScriptHandle(Uri uri, SourceFile? source) {
    ObjectHandle uriHandle = getPublicNameHandle(uri.toString());
    _ScriptHandle handle =
        getOrAddObject(_ScriptHandle(uriHandle, source)) as _ScriptHandle;
    if (handle.source == null && source != null) {
      handle.source = source;
    }
    return handle;
  }

  List<TypeParameterDeclaration> getTypeParameterHandles(
    List<TypeParameter> typeParams,
  ) {
    if (typeParams.isEmpty) {
      return const <TypeParameterDeclaration>[];
    }
    return List<TypeParameterDeclaration>.generate(
      typeParams.length,
      (int i) => TypeParameterDeclaration(
        getPublicNameHandle(typeParams[i].name!),
        getHandle(typeParams[i].bound)!,
        getHandle(typeParams[i].defaultType)!,
      ),
    );
  }

  List<TypeParameterDeclaration> getStructuralParameterHandles(
    List<StructuralParameter> typeParams,
  ) {
    if (typeParams.isEmpty) {
      return const <TypeParameterDeclaration>[];
    }
    return List<TypeParameterDeclaration>.generate(
      typeParams.length,
      (int i) => TypeParameterDeclaration(
        getPublicNameHandle(typeParams[i].name!),
        getHandle(typeParams[i].bound)!,
        getHandle(typeParams[i].defaultType)!,
      ),
    );
  }

  void declareClosure(
    FunctionNode function,
    Member enclosingMember,
    int closureIndex,
  ) {
    final handle = getOrAddObject(
      new _ClosureHandle(
        getHandle(enclosingMember) as _MemberHandle,
        closureIndex,
      ),
    );
    _nodeCache[function] = handle;
  }

  ObjectHandle getOrAddObject(ObjectHandle obj) {
    assert(obj._useCount == 0);
    ObjectHandle? canonical = _canonicalizationCache[obj];
    if (canonical == null) {
      assert(_indexTable == null);
      _objects.add(obj);
      _canonicalizationCache[obj] = obj;
      canonical = obj;
    }
    ++canonical._useCount;
    return canonical;
  }

  void allocateIndexTable() {
    int tableSize = 1; // Reserve invalid entry.
    for (var obj in _objects.reversed) {
      assert(obj._reference == null);
      if (obj.shouldBeIncludedIntoIndexTable) {
        // This object will be included into index table.
        ++tableSize;
      } else {
        // This object will be copied and written inline. Bump use count for
        // objects referenced from this one for each copy after the first.
        obj._reference = ObjectHandle.inlineObject;
        obj.accountUsesForObjectCopies(obj._useCount - 1);
      }
    }
    final indexTable = _indexTable = List<ObjectHandle>.filled(
      tableSize,
      _InvalidHandle(),
    );
    int count = 0;
    indexTable[count++] = _InvalidHandle()
      .._reference = ObjectHandle._makeReference(0);
    for (var obj in _objects) {
      if (obj._reference == null) {
        obj._reference = ObjectHandle._makeReference(count);
        indexTable[count++] = obj;
      } else {
        assert(obj._reference == ObjectHandle.inlineObject);
      }
    }
    assert(count == tableSize);
  }

  @override
  void writeObject(BytecodeObject? object, BufferedWriter writer) {
    ObjectHandle? handle = object as ObjectHandle?;
    if (handle == null) {
      writer.writePackedUInt30(ObjectHandle._makeReference(0));
      return;
    }
    final handleReference = handle._reference!;
    if (handleReference == ObjectHandle.inlineObject) {
      handle._write(writer);
    } else {
      assert(handleReference >= 0);
      assert((handleReference & ObjectHandle.referenceBit) != 0);
      writer.writePackedUInt30(handleReference);
    }
  }

  @override
  BytecodeObject? readObject(BufferedReader reader) {
    final int header = reader.readPackedUInt30();
    if ((header & ObjectHandle.referenceBit) == 0) {
      return new ObjectHandle._read(reader, header);
    } else {
      final int index = ObjectHandle._getIndexFromReference(header);
      return (index == 0) ? null : _indexTable![index];
    }
  }

  void write(BufferedWriter writer) {
    assert(writer.objectWriter == this);
    final indexTable = _indexTable!;
    final start = writer.offset;
    if (BytecodeSizeStatistics.objectTableStats.isEmpty) {
      for (var kind in ObjectKind.values) {
        BytecodeSizeStatistics.objectTableStats.add(
          new NamedEntryStatistics(objectKindToString(kind)),
        );
      }
    }

    BufferedWriter contentsWriter = new BufferedWriter.fromWriter(writer);
    List<int> offsets = List<int>.generate(indexTable.length, (int i) {
      final offset = contentsWriter.offset;
      indexTable[i]._write(contentsWriter);

      final entryStat =
          BytecodeSizeStatistics.objectTableStats[indexTable[i].kind.index];
      entryStat.size += (contentsWriter.offset - offset);
      ++entryStat.count;

      return offset;
    });

    writer.writePackedUInt30(indexTable.length);
    writer.writePackedUInt30(contentsWriter.offset);
    writer.appendWriter(contentsWriter);
    for (var offs in offsets) {
      writer.writePackedUInt30(offs);
    }

    // Index strings in objects which will be written inline
    // in constant pool entries.
    for (var obj in _objects) {
      if (obj._reference == ObjectHandle.inlineObject) {
        obj.indexStrings(writer.stringWriter);
      }
    }

    BytecodeSizeStatistics.objectTableSize += (writer.offset - start);
    BytecodeSizeStatistics.objectTableEntriesCount += indexTable.length;
  }

  ObjectTable.read(BufferedReader reader) {
    reader.objectReader = this;

    final int numEntries = reader.readPackedUInt30();
    reader.readPackedUInt30(); // Contents length

    final indexTable = _indexTable = List<ObjectHandle>.filled(
      numEntries,
      _InvalidHandle(),
    );
    for (int i = 0; i < numEntries; ++i) {
      final int header = reader.readPackedUInt30();
      indexTable[i] = new ObjectHandle._read(reader, header)
        .._reference = ObjectHandle._makeReference(i);
    }
    // Skip index table.
    for (int i = 0; i < numEntries; ++i) {
      reader.readPackedUInt30();
    }
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.writeln('ObjectTable {');
    final indexTable = _indexTable!;
    for (int i = 0; i < indexTable.length; ++i) {
      final obj = indexTable[i];
      sb.writeln('  [$i] = ${objectKindToString(obj.kind)} $obj');
    }
    sb.writeln('}');
    return sb.toString();
  }
}

class _NodeVisitor extends VisitorDefault<ObjectHandle?>
    with VisitorThrowingMixin<ObjectHandle?> {
  final ObjectTable objectTable;
  final CoreTypes coreTypes;
  final _typeParameters = <StructuralParameter, ObjectHandle>{};

  _NodeVisitor(this.objectTable, this.coreTypes);

  @override
  ObjectHandle? defaultNode(Node node) =>
      throw 'Unexpected node ${node.runtimeType} $node';

  @override
  ObjectHandle? visitLibrary(Library node) {
    final uri =
        objectTable.getConstStringHandle(node.importUri.toString())
            as _ConstObjectHandle;
    return objectTable.getOrAddObject(new _LibraryHandle(uri));
  }

  @override
  ObjectHandle? visitClass(Class node) {
    final library =
        objectTable.getHandle(node.enclosingLibrary) as _LibraryHandle;
    final name = node.name.startsWith('_')
        ? (objectTable.getOrAddObject(
                new _PrivateNameHandle(library, node.name),
              )
              as _PrivateNameHandle)
        : objectTable.getPublicNameHandle(node.name);
    return objectTable.getOrAddObject(new _ClassHandle(library, name));
  }

  @override
  ObjectHandle defaultMember(Member node) => objectTable.getMemberHandle(node);

  @override
  ObjectHandle? visitDynamicType(DynamicType node) => objectTable._dynamicType;

  @override
  ObjectHandle? visitVoidType(VoidType node) => objectTable._voidType;

  @override
  ObjectHandle? visitNullType(NullType node) => objectTable._nullType;

  @override
  ObjectHandle? visitNeverType(NeverType node) =>
      objectTable.getOrAddObject(new _NeverTypeHandle(node.nullability));

  @override
  ObjectHandle? visitInterfaceType(InterfaceType node) {
    final classHandle = objectTable.getHandle(node.classNode) as _ClassHandle;
    if (node.classNode.typeParameters.isEmpty) {
      return objectTable.getOrAddObject(
        new _SimpleTypeHandle(classHandle, node.nullability),
      );
    }

    final typeArgsHandle =
        objectTable.getTypeArgumentsHandle(node.typeArguments)
            as _TypeArgumentsHandle?;
    return objectTable.getOrAddObject(
      _GenericTypeHandle(classHandle, typeArgsHandle, node.nullability),
    );
  }

  @override
  ObjectHandle? visitFutureOrType(FutureOrType node) {
    final classNode = coreTypes.deprecatedFutureOrClass;
    final classHandle = objectTable.getHandle(classNode) as _ClassHandle;
    final typeArgsHandle =
        objectTable.getTypeArgumentsHandle([node.typeArgument])
            as _TypeArgumentsHandle?;
    final result = objectTable.getOrAddObject(
      new _GenericTypeHandle(classHandle, typeArgsHandle, node.nullability),
    );
    return result;
  }

  @override
  ObjectHandle? visitTypeParameterType(TypeParameterType node) {
    final param = node.parameter;
    final parent = param.declaration;
    if (parent == null) {
      throw 'Type parameter $param without declaration';
    }

    ObjectHandle parentHandle;
    if (parent is Class) {
      parentHandle = objectTable.getHandle(parent)!;
    } else if (parent is Member) {
      parentHandle = objectTable.getHandle(parent)!;
    } else if (parent is LocalFunction) {
      parentHandle = objectTable.getHandle(parent.function)!;
    } else {
      throw 'Unexpected parent declaration of TypeParameter: ${parent.runtimeType} $parent';
    }
    final indexInParent = parent.typeParameters.indexOf(param);
    if (indexInParent < 0) {
      throw 'Type parameter $param is not found in its parent class $parent';
    }
    return objectTable.getOrAddObject(
      new _TypeParameterHandle(parentHandle, indexInParent, node.nullability),
    );
  }

  @override
  ObjectHandle? visitStructuralParameterType(StructuralParameterType node) {
    final param = node.parameter;
    final handle = _typeParameters[param] as _TypeParameterHandle;
    if (handle.nullability == node.nullability) {
      return handle;
    }
    return objectTable.getOrAddObject(
      new _TypeParameterHandle(
        handle.parent,
        handle.indexInParent,
        node.nullability,
      ),
    );
  }

  @override
  ObjectHandle? visitFunctionType(FunctionType node) {
    final int numEnclosingTypeParameters =
        objectTable.numEnclosingFunctionTypeParameters + _typeParameters.length;
    for (int i = 0; i < node.typeParameters.length; ++i) {
      _typeParameters[node.typeParameters[i]] = objectTable.getOrAddObject(
        new _TypeParameterHandle(
          null,
          numEnclosingTypeParameters + i,
          Nullability.nonNullable,
        ),
      );
    }
    final typeParameters = node.typeParameters.isNotEmpty
        ? TypeParametersDeclaration(
            objectTable.getStructuralParameterHandles(node.typeParameters),
          )
        : null;

    final positionalParams = List<_TypeHandle>.generate(
      node.positionalParameters.length,
      (int i) =>
          objectTable.getHandle(node.positionalParameters[i]) as _TypeHandle,
    );
    final namedParams = List<NameAndType>.generate(
      node.namedParameters.length,
      (int i) {
        final param = node.namedParameters[i];
        return NameAndType(
          objectTable.getPublicNameHandle(param.name),
          objectTable.getHandle(param.type)!,
        );
      },
    );
    final parameterFlags = ParameterFlags.getFunctionTypeFlags(node);
    final returnType = objectTable.getHandle(node.returnType) as _TypeHandle;

    final result = objectTable.getOrAddObject(
      new _FunctionTypeHandle(
        numEnclosingTypeParameters,
        typeParameters,
        node.requiredParameterCount,
        positionalParams,
        namedParams,
        parameterFlags,
        returnType,
        node.nullability,
      ),
    );

    for (int i = 0; i < node.typeParameters.length; ++i) {
      _typeParameters.remove(node.typeParameters[i]);
    }

    return result;
  }

  @override
  ObjectHandle? visitRecordType(RecordType node) {
    final positional = List<_TypeHandle>.generate(
      node.positional.length,
      (int i) => objectTable.getHandle(node.positional[i]) as _TypeHandle,
    );
    final named = List<NameAndType>.generate(node.named.length, (int i) {
      final namedField = node.named[i];
      return NameAndType(
        objectTable.getPublicNameHandle(namedField.name),
        objectTable.getHandle(namedField.type)!,
      );
    });
    return objectTable.getOrAddObject(
      _RecordTypeHandle(positional, named, node.nullability),
    );
  }

  @override
  ObjectHandle? visitTypedefType(TypedefType node) =>
      objectTable.getHandle(node.unalias);

  @override
  ObjectHandle? visitIntersectionType(IntersectionType node) =>
      objectTable.getHandle(node.left);

  @override
  ObjectHandle? visitExtensionType(ExtensionType node) =>
      objectTable.getHandle(node.extensionTypeErasure);

  @override
  ObjectHandle? visitNullConstant(NullConstant node) => null;

  @override
  ObjectHandle? visitBoolConstant(BoolConstant node) => objectTable
      .getOrAddObject(new _ConstObjectHandle(ConstTag.kBool, node.value));

  @override
  ObjectHandle? visitIntConstant(IntConstant node) => objectTable
      .getOrAddObject(new _ConstObjectHandle(ConstTag.kInt, node.value));

  @override
  ObjectHandle? visitDoubleConstant(DoubleConstant node) => objectTable
      .getOrAddObject(new _ConstObjectHandle(ConstTag.kDouble, node.value));

  @override
  ObjectHandle? visitStringConstant(StringConstant node) =>
      objectTable.getConstStringHandle(node.value);

  @override
  ObjectHandle? visitSymbolConstant(SymbolConstant node) =>
      objectTable.getOrAddObject(
        new _ConstObjectHandle(
          ConstTag.kSymbol,
          objectTable.getNameHandle(
            node.libraryReference?.asLibrary,
            node.name,
          ),
        ),
      );

  @override
  ObjectHandle? visitListConstant(ListConstant node) =>
      objectTable.getOrAddObject(
        new _ConstObjectHandle(
          ConstTag.kList,
          objectTable.getHandles(node.entries),
          objectTable.getHandle(node.typeArgument),
        ),
      );

  @override
  ObjectHandle? visitRecordConstant(RecordConstant node) =>
      objectTable.getOrAddObject(
        new _ConstObjectHandle(
          ConstTag.kRecord,
          objectTable.getHandles([...node.positional, ...node.named.values]),
          objectTable.getHandle(node.recordType),
        ),
      );

  @override
  ObjectHandle? visitMapConstant(MapConstant node) =>
      objectTable.getOrAddObject(
        new _ConstObjectHandle(
          ConstTag.kMap,
          [
            for (var e in node.entries) ...[
              objectTable.getHandle(e.key),
              objectTable.getHandle(e.value),
            ],
          ],
          objectTable.getHandle(
            InterfaceType(coreTypes.mapClass, Nullability.nonNullable, [
              node.keyType,
              node.valueType,
            ]),
          ),
        ),
      );

  @override
  ObjectHandle? visitSetConstant(SetConstant node) =>
      objectTable.getOrAddObject(
        new _ConstObjectHandle(
          ConstTag.kSet,
          objectTable.getHandles(node.entries),
          objectTable.getHandle(node.typeArgument),
        ),
      );

  @override
  ObjectHandle? visitInstanceConstant(InstanceConstant node) =>
      objectTable.getOrAddObject(
        new _ConstObjectHandle(
          ConstTag.kInstance,
          node.fieldValues.map<ObjectHandle, ObjectHandle?>(
            (Reference fieldRef, Constant value) => new MapEntry(
              objectTable.getHandle(fieldRef.asField)!,
              objectTable.getHandle(value),
            ),
          ),
          objectTable.getHandle(
            InterfaceType(
              node.classNode,
              Nullability.nonNullable,
              node.typeArguments,
            ),
          ),
        ),
      );

  @override
  ObjectHandle? visitStaticTearOffConstant(StaticTearOffConstant node) =>
      objectTable.getOrAddObject(
        new _ConstObjectHandle(
          ConstTag.kTearOff,
          objectTable.getHandle(node.target),
        ),
      );

  @override
  ObjectHandle? visitConstructorTearOffConstant(
    ConstructorTearOffConstant node,
  ) => objectTable.getOrAddObject(
    new _ConstObjectHandle(
      ConstTag.kTearOff,
      objectTable.getHandle(node.target),
    ),
  );

  @override
  ObjectHandle? visitRedirectingFactoryTearOffConstant(
    RedirectingFactoryTearOffConstant node,
  ) => objectTable.getOrAddObject(
    new _ConstObjectHandle(
      ConstTag.kTearOff,
      objectTable.getHandle(node.target),
    ),
  );

  @override
  ObjectHandle? visitTypeLiteralConstant(TypeLiteralConstant node) =>
      objectTable.getHandle(node.type);

  @override
  ObjectHandle? visitInstantiationConstant(InstantiationConstant node) =>
      objectTable.getOrAddObject(
        new _ConstObjectHandle(
          ConstTag.kTearOffInstantiation,
          objectTable.getHandle(node.tearOffConstant),
          objectTable.getTypeArgumentsHandle(node.types),
        ),
      );
}

int _combineHashes(int hash1, int hash2) =>
    (((hash1 * 31) & 0x3fffffff) + hash2) & 0x3fffffff;
