// 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(
      VariableDeclaration 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);
  }

  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, bool isFactory = 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) +
        // VM expects that type arguments vector passed to a factory
        // constructor is counted in numArguments, and not counted in
        // numTypeArgs.
        // TODO(alexmarkov): Clean this up.
        (isFactory ? 1 : 0);
    final int numTypeArguments = isFactory ? 0 : 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 = _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(
        objectTable.numEnclosingFunctionTypeParameters +
            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;
