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

  // 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, 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 =
        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;
